feat: better gen-list + pr template (#100)

This commit is contained in:
Jacob Nguyen
2023-09-01 11:51:35 -05:00
committed by GitHub
parent c0a36cc204
commit 63253dce8f
18 changed files with 280 additions and 137 deletions

35
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,35 @@
## Plugin Submission Checklist
Before submitting your plugin, please ensure that you have followed the specifications below:
- [ ] Your plugin code includes a JSDoc block with `@plugin` at the beginning and `@end` at the end.
- [ ] The order of plugin metadata within the JSDoc block follows the structure provided:
1. `@plugin`
2. `description`
3. `@author` (you can have multiple authors in this format: `@author @jacoobes [<@182326315813306368>]`)
4. `@version` (with the version number)
5. `@example` (a nice example of how to use your plugin)
6. `@end`
## Plugin Submission Details
**Description:**
_[Please provide a brief description of your plugin here.]_
**Authors:**
_[List the authors of the plugin along with their Discord IDs in the format `@username [<@discord_id>]`. You can add multiple authors in this manner.]_
**Version:**
_[Specify the version number of your plugin.]_
**Example:**
_[Provide an example of how your plugin can be used here.]_
## Additional Notes
_[Include any additional information or notes you'd like to provide regarding your plugin submission.]_

3
.gitignore vendored
View File

@@ -1 +1,2 @@
node_modules/
node_modules/
.nrepl-port

View File

@@ -1,5 +1,6 @@
//@ts-nocheck
/**
* @plugin
* This plugin checks the fields of a ModalSubmitInteraction
* with regex or a custom callback
*
@@ -25,6 +26,7 @@
* }
* })
* ```
* @plugin
*/
import { CommandControlPlugin, CommandType, controller } from "@sern/handler";
import type { ModalSubmitInteraction } from "discord.js";

View File

@@ -1,5 +1,6 @@
//@ts-nocheck
/**
* @plugin
* This is buttonConfirmation plugin, it runs confirmation prompt in the form of buttons.
* Note that you need to use edit/editReply in the command itself because we are already replying in the plugin!
* Credits to original plugin of confirmation using reactions and its author!
@@ -17,6 +18,7 @@
* }
* })
* ```
* @end
*/
import { CommandControlPlugin, CommandType, controller } from "@sern/handler";

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* This plugin checks if a channel is the specified type
*
* @author @Benzo-Fury [<@762918086349029386>]
@@ -16,6 +17,7 @@
* }
* })
* ```
* @end
*/
import { ChannelType } from "discord.js";
import { CommandControlPlugin, CommandType, controller } from "@sern/handler";

View File

@@ -1,5 +1,6 @@
//@ts-nocheck
/**
* @plugin
* Asks the user for a confirmation message before executing the command
*
* @author @trueharuu [<@504698587221852172>]
@@ -18,6 +19,7 @@
* }
* })
* ```
* @end
*/
import {

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* Allows you to set cooldowns (or "ratelimits") for commands
* limits user/channel/guild actions,
* @author @trueharuu [<@504698587221852172>]
@@ -15,6 +16,7 @@
* }
* })
* ```
* @end
*/
import {

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* Disables a command entirely, for whatever reasons you may need.
*
* @author @jacoobes [<@182326315813306368>]
@@ -15,7 +16,8 @@
* //your code here
* }
* })
* ```
* ```
* @end
*/
import { CommandType, CommandControlPlugin, controller } from "@sern/handler";
import {

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* This is dmOnly plugin, it allows commands to be run only in DMs.
*
* @author @EvolutionX-10 [<@697795666373640213>]
@@ -14,7 +15,8 @@
* //your code here
* }
* })
* ```
* ```
* @end
*/
import { CommandControlPlugin, CommandType, controller } from "@sern/handler";
export function dmOnly(content?: string, ephemeral?: boolean) {

View File

@@ -605,6 +605,7 @@ export type FilterOptions = {
* // your code here
* }
* });
* @end
*/
export const filter =

View File

@@ -1,5 +1,6 @@
//@ts-nocheck
/**
* @plugin
* This plugin checks if the channel is nsfw and responds to user with a specified response if not nsfw
*
* @author @Benzo-Fury [<@762918086349029386>]
@@ -14,7 +15,8 @@
* //your code here
* }
* })
* ```
* ```
* @end
*/
import {
ChannelType,

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* This is OwnerOnly plugin, it allows only bot owners to run the command, like eval.
*
* @author @EvolutionX-10 [<@697795666373640213>]
@@ -14,7 +15,8 @@
* //your code here
* }
* })
* ```
* ```
* @end
*/
import { CommandType, CommandControlPlugin, controller } from "@sern/handler";

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* This is perm check, it allows users to parse the permission you want and let the plugin do the rest. (check user for that perm).
*
* @author @Benzo-Fury [<@762918086349029386>]
@@ -15,6 +16,7 @@
* }
* })
* ```
* @end
*/
import type { GuildMember, PermissionResolvable } from "discord.js";

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* This is publish plugin, it allows you to publish your application commands using the discord.js library with ease.
*
* @author @EvolutionX-10 [<@697795666373640213>]
@@ -15,7 +16,8 @@
* //your code here
* }
* })
* ```
* ```
* @end
*/
import {
CommandInitPlugin,

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* This is perm check, it allows users to parse the permission you want and let the plugin do the rest. (check bot or user for that perm).
*
* @author @Benzo-Fury [<@762918086349029386>]
@@ -15,7 +16,8 @@
* //your code here
* }
* })
* ```
* ```
* @end
*/
import type { GuildMember, PermissionResolvable } from "discord.js";

View File

@@ -1,5 +1,6 @@
// @ts-nocheck
/**
* @plugin
* Checks if a command is available in a specific server.
*
* @author @Peter-MJ-Parker [<@371759410009341952>]
@@ -17,6 +18,7 @@
* },
* });
* ```
* @end
*/
import { CommandType, controller, CommandControlPlugin } from "@sern/handler";

View File

@@ -1,110 +1,113 @@
{
"JavaScript": [
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/publish.js",
"name": "publish"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/buttonConfirmation.js",
"name": "buttonConfirmation"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/requirePermission.js",
"name": "requirePermission"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/nsfwOnly.js",
"name": "nsfwOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/serverOnly.js",
"name": "serverOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/ownerOnly.js",
"name": "ownerOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/confirmation.js",
"name": "confirmation"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/permCheck.js",
"name": "permCheck"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/dmOnly.js",
"name": "dmOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/disable.js",
"name": "disable"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/channelType.js",
"name": "channelType"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/assertFields.js",
"name": "assertFields"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/JavaScript/cooldown.js",
"name": "cooldown"
}
],
"TypeScript": [
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/permCheck.ts",
"name": "permCheck"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/assertFields.ts",
"name": "assertFields"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/serverOnly.ts",
"name": "serverOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/dmOnly.ts",
"name": "dmOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/disable.ts",
"name": "disable"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/publish.ts",
"name": "publish"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/cooldown.ts",
"name": "cooldown"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/confirmation.ts",
"name": "confirmation"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/ownerOnly.ts",
"name": "ownerOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/channelType.ts",
"name": "channelType"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/nsfwOnly.ts",
"name": "nsfwOnly"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/requirePermission.ts",
"name": "requirePermission"
},
{
"link": "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/buttonConfirmation.ts",
"name": "buttonConfirmation"
}
]
}
[ {
"description" : "\n\n This plugin checks the fields of a ModalSubmitInteraction\n with regex or a custom callback\n",
"hash" : "2da46f3202e2b209ab24620d4f890da2",
"name" : "assertFields",
"author" : [ "@jacoobes [<@182326315813306368>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/assertFields.ts",
"example" : "\n\n ```ts\n export default commandModule({\n type: CommandType.Modal,\n plugins: [\n assertFields({\n fields: {\n // check the modal field \"mcUsernameInput\" with the regex /a+b+c/\n mcUsernameInput: /a+b+c+/\n },\n failure: (errors, interaction) => {\n interaction.reply(errors.join(\"\\n\"))\n }\n }),\n ],\n execute: ctx => {\n ctx.reply(\"nice!\")\n }\n })\n ```\n\n/",
"version" : "1.0.0"
}, {
"description" : "\n\n This is buttonConfirmation plugin, it runs confirmation prompt in the form of buttons.\n Note that you need to use edit/editReply in the command itself because we are already replying in the plugin!\n Credits to original plugin of confirmation using reactions and its author!\n",
"hash" : "d752596f5d9871e469d142ccf5569691",
"name" : "buttonConfirmation",
"author" : [ "@EvolutionX-10 [<@697795666373640213>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/buttonConfirmation.ts",
"example" : "\n\n ```ts\n import { buttonConfirmation } from \"../plugins/buttonConfirmation\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ buttonConfirmation() ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```",
"version" : "1.0.0"
}, {
"description" : "\n\n This plugin checks if a channel is the specified type\n",
"hash" : "a3f95ec62e1480b8c3318443cc8184c0",
"name" : "channelType",
"author" : [ "@Benzo-Fury [<@762918086349029386>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/channelType.ts",
"example" : "\n\n ```ts\n import { channelType } from \"../plugins/channelType\";\n import { ChannelType } from \"discord.js\"\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ channelType([ChannelType.GuildText], 'This cannot be used here') ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```",
"version" : "1.0.0"
}, {
"description" : "\n\n Asks the user for a confirmation message before executing the command\n",
"hash" : "77e7cc0e4f9706183d2debb918056809",
"name" : "confirmation",
"author" : [ "@trueharuu [<@504698587221852172>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/confirmation.ts",
"example" : "\n\n ```ts\n import { confirmation } from \"../plugins/confirmation\";\n import { CommandType, commandModule } from \"@sern/handler\";\n\n // YOU MUST HAVE GUILD MESSAGE REACTION INTENTS ON YOUR CLIENT!!!!\n export default commandModule({\n type : CommandType.Both\n plugins: [confirmation()],\n \texecute: (ctx, args) => {\n \t\tctx.interaction.followUp('Hello welcome to the secret club')\n \t}\n })\n ```",
"version" : "1.0.0"
}, {
"description" : "\n\n Allows you to set cooldowns (or \"ratelimits\") for commands\n limits user/channel/guild actions,",
"hash" : "5dfb3c2f533878a15cf9764ffb921d1e",
"name" : "cooldown",
"author" : [ "@trueharuu [<@504698587221852172>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/cooldown.ts",
"example" : "\n\n ```ts\n import { cooldown } from \"../plugins/cooldown\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [cooldown.add( [ ['channel', '1/4'] ] )], // limit to 1 action every 4 seconds per channel\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```",
"version" : "1.0.0"
}, {
"description" : "\n\n Disables a command entirely, for whatever reasons you may need.\n",
"hash" : "96e4b5b562500b0bcdc442fbf130a555",
"name" : "disable",
"author" : [ "@jacoobes [<@182326315813306368>]", "@Peter-MJ-Parker [<@371759410009341952>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/disable.ts",
"example" : "\n\n ```ts\n import { disable } from \"../plugins/disable\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ disable() ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ",
"version" : "2.0.0"
}, {
"description" : "\n\n This is dmOnly plugin, it allows commands to be run only in DMs.\n",
"hash" : "844e68aa0c9147c98930b34a5d716a22",
"name" : "dmOnly",
"author" : [ "@EvolutionX-10 [<@697795666373640213>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/dmOnly.ts",
"example" : "\n\n ```ts\n import { dmOnly } from \"../plugins/dmOnly\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [dmOnly()],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ",
"version" : "1.0.0"
}, {
"description" : "\n\n Generalized `filter` plugin. revised by jacoobes, all credit to original author.\n Perform declarative conditionals as plugins. ",
"hash" : "ba85e67d23bbfacc337f82e9fade283c",
"name" : "filter",
"author" : [ "@trueharuu [<@504698587221852172>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/filter.ts",
"example" : "\n\n import { filter, not, isGuildOwner, canMentionEveryone } from '../plugins/filter';\n import { commandModule } from '@sern/handler';\n\n export default commandModule({\n plugins: [filter({ condition: [not(isGuildOwner()), canMentionEveryone()] })],\n async execute(context) {\n // your code here\n }\n });",
"version" : "2.0.0"
}, {
"description" : "\n\n This plugin checks if the channel is nsfw and responds to user with a specified response if not nsfw\n",
"hash" : "65ff8138fd20486d6eeff17cdb7b93cf",
"name" : "nsfwOnly",
"author" : [ "@Benzo-Fury [<@762918086349029386>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/nsfwOnly.ts",
"example" : "\n\n ```ts\n import { nsfwOnly } from \"../plugins/nsfwOnly\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ nsfwOnly('response', true) ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ",
"version" : "1.0.0"
}, {
"description" : "\n\n This is OwnerOnly plugin, it allows only bot owners to run the command, like eval.\n",
"hash" : "5ffb76d3a2ecdb0516fa98a93dd1d15d",
"name" : "ownerOnly",
"author" : [ "@EvolutionX-10 [<@697795666373640213>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/ownerOnly.ts",
"example" : "\n\n ```ts\n import { ownerOnly } from \"../plugins/ownerOnly\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ ownerOnly() ], // can also pass array of IDs to override default owner IDs\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ",
"version" : "1.2.0"
}, {
"description" : "\n\n This is perm check, it allows users to parse the permission you want and let the plugin do the rest. (check user for that perm).\n",
"hash" : "45fb62d9ffe908469ea58aabb550daf7",
"name" : "permCheck",
"author" : [ "@Benzo-Fury [<@762918086349029386>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/permCheck.ts",
"example" : "\n\n ```ts\n import { permCheck } from \"../plugins/permCheck\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ permCheck('permission', 'No permission response') ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ```",
"version" : "1.0.1"
}, {
"description" : "\n\n This is publish plugin, it allows you to publish your application commands using the discord.js library with ease.\n",
"hash" : "3f76c395a51cccc9c66de9ea65d28b19",
"name" : "publish",
"author" : [ "@EvolutionX-10 [<@697795666373640213>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/publish.ts",
"example" : "\n\n ```ts\n import { publish } from \"../plugins/publish\";\n import { commandModule } from \"@sern/handler\";\n export default commandModule({\n plugins: [ publish() ], // put an object containing permissions, ids for guild commands, boolean for dmPermission\n // plugins: [ publish({ guildIds: ['guildId'], defaultMemberPermissions: 'Administrator'})]\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ",
"version" : "2.0.0"
}, {
"description" : "\n\n This is perm check, it allows users to parse the permission you want and let the plugin do the rest. (check bot or user for that perm).\n",
"hash" : "bad95c4cf2105d9f60363ddf16ab7b82",
"name" : "requirePermission",
"author" : [ "@Benzo-Fury [<@762918086349029386>]", "@needhamgary [<@342314924804014081>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/requirePermission.ts",
"example" : "\n\n ```ts\n import { requirePermission } from \"../plugins/myPermCheck\";\n import { commandModule, CommandType } from \"@sern/handler\";\n export default commandModule({\n plugins: [ requirePermission<CommandType>('target', 'permission', 'No response (optional)') ],\n execute: (ctx) => {\n \t\t//your code here\n }\n })\n ``` ",
"version" : "1.2.0"
}, {
"description" : "\n\n Checks if a command is available in a specific server.\n",
"hash" : "b1d78678451c260286a97de8f1cb9e07",
"name" : "serverOnly",
"author" : [ "@Peter-MJ-Parker [<@371759410009341952>]" ],
"link" : "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/serverOnly.ts",
"example" : "\n\n ```ts\n import { commandModule, CommandType } from \"@sern/handler\";\n import { serverOnly } from \"../plugins/serverOnly\";\n export default commandModule({\n type: CommandType.Both,\n plugins: [serverOnly([\"guildId\"], failMessage)], // fail message is the message you will see when the command is ran in the wrong server.\n description: \"command description\",\n execute: async (ctx, args) => {\n // your code here\n },\n });\n ```",
"version" : "1.0.0"
} ]

View File

@@ -1,33 +1,110 @@
(require '[cheshire.core :as json])
(require '[babashka.http-client :as http]
'[babashka.fs :as fs])
(defn directory [name]
(io/file (str "./" name)))
(defn make-link [lang]
(fn [name] (str "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/" lang "/" name)))
(defn make-link [name]
(str "https://raw.githubusercontent.com/sern-handler/awesome-plugins/main/TypeScript/" name))
(defn name-without-extension [name]
(if-let [last-dot-index (str/last-index-of name ".")]
(subs name 0 last-dot-index)
name))
(defn file-names [dir-name]
(defn read-lines [file]
(fs/read-all-lines file))
; remove not jsdoc lines
(defn remove-non-jsdoc [lines]
( ->> lines
(filter #(re-find #"^\s*\*|/\*\*|\*/" %))))
(defn into-jsdoc-content [lines]
"get jsdoc from lines of file"
( ->> lines
remove-non-jsdoc
(map #(str/replace % #"^\s*\*(\s*)|\/\*\*(\s*)|\*\/" "$1"))))
(defn parse-author [line]
( -> line
(str/replace #"@author" "")
(str/trim)))
(defn group-doc [line]
(cond
(str/includes? line "@plugin") {:plugin ""}
(str/includes? line "@author") {:author (parse-author line)}
(str/includes? line "@example") {:example ""}
(str/includes? line "@end") {:end "" }
(str/includes? line "@version") {:version (-> line
(str/replace #"@version" "")
(str/trim))}
:else {:unknown line}
))
(defn get-description [file-data, kyword]
"description will be the first section of unknown lines, up until an author tag"
(split-with (comp not kyword) file-data))
(defn combine-lines [acc cur]
(str acc "\n" cur))
(defn accumulate-multiple [acc cur]
(let [authors (:author cur)]
(conj acc cur)))
(defn file-data [plugin-name]
"gets all jsdoc content. Transforms into lazy seq of data"
(let [file (io/file (str "./TypeScript/" plugin-name))
; We start a plugin metadata block.
; this will transform the first JSDOC block that
; starts with a @plugin tag
lines (drop-while (comp not :plugin) (->> (read-lines file)
into-jsdoc-content
(map group-doc)))
; description of plugin should come next, up until the first author tag appears
[description, remaining] (get-description lines :author)
; get authors, and then the version of plugin should appear.
[authors, [version, & remaining2]] (get-description remaining :version)]
; transform into map
{:description (reduce combine-lines "" (map :unknown description))
:version (:version version)
:author (reduce accumulate-multiple [] (map :author authors))
:example (reduce combine-lines "" (map :unknown ( ->> remaining2
(take-while (comp not :end)))))}
))
(defn get-filename [file]
(.getName file))
(defn copy+md5 [source sink]
(let [digest (java.security.MessageDigest/getInstance "MD5")]
(with-open [input-stream (io/input-stream source)
digest-stream (java.security.DigestInputStream. input-stream digest)
output-stream (io/output-stream sink)]
(io/copy digest-stream output-stream))
(format "%032x" (BigInteger. 1 (.digest digest)))))
(defn generate-content [dir-name]
(->>
(directory dir-name)
file-seq
(file-seq (directory dir-name))
(filter #(.isFile %))
(map #(.getName %))))
(defn file-links-and-basenames [dir]
(let [base-link (make-link dir)]
(mapv #(zipmap [:link :name] ((juxt base-link name-without-extension) %))
(file-names dir))))
(def file-info-map (juxt keyword file-links-and-basenames))
(def json
(into {} (map file-info-map ["JavaScript" "TypeScript"])))
(map (fn [file]
(let [
fname (get-filename file)
file-data (file-data fname)]
(conj (hash-map
:name (name-without-extension fname)
:link (make-link fname)
:hash (copy+md5 file (java.io.OutputStream/nullOutputStream)))
file-data ))))))
(def json (generate-content "./TypeScript") )
(json/generate-stream json (io/writer "pluginlist.json") { :pretty true })