mirror of
https://github.com/keanuplayz/TravBot-v3.git
synced 2024-08-15 02:33:12 +00:00
Added example of temporary solution for slash commands
This commit is contained in:
parent
69a8452574
commit
533ce58647
10 changed files with 309 additions and 30 deletions
|
@ -5,6 +5,7 @@
|
|||
.husky/
|
||||
Dockerfile
|
||||
LICENSE
|
||||
*.txt
|
||||
|
||||
# Specific to this repository
|
||||
dist/
|
||||
|
|
65
package-lock.json
generated
65
package-lock.json
generated
|
@ -10,9 +10,11 @@
|
|||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^0.8.2",
|
||||
"canvas": "^2.8.0",
|
||||
"chalk": "^4.1.2",
|
||||
"discord.js": "^13.3.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"figlet": "^1.5.2",
|
||||
"glob": "^7.2.0",
|
||||
"inquirer": "^8.2.0",
|
||||
|
@ -653,13 +655,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/@discordjs/builders": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.1.tgz",
|
||||
"integrity": "sha512-kYJMvZ/BjRD1/6G2t1pQop2yoJNUmYvvKeG4mOBUCHFmfb7WIeBFmN/eSiP3cVSfRx3lbNiyxkdd5JzhjQnGbg==",
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz",
|
||||
"integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.2.0",
|
||||
"discord-api-types": "^0.24.0",
|
||||
"ow": "^0.28.1",
|
||||
"ow": "^0.27.0",
|
||||
"ts-mixer": "^6.0.0",
|
||||
"tslib": "^2.3.1"
|
||||
},
|
||||
|
@ -2172,6 +2174,14 @@
|
|||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
|
@ -4523,15 +4533,15 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ow": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.28.1.tgz",
|
||||
"integrity": "sha512-1EZTywPZeUKac9gD7q8np3Aj+V54kvfIcjNEVNDSbG2Ys5xA5foW2HquvMMqgyWGLqIFMlc0Iq/HmyMHqN48sA==",
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
|
||||
"integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==",
|
||||
"dependencies": {
|
||||
"@sindresorhus/is": "^4.2.0",
|
||||
"@sindresorhus/is": "^4.0.1",
|
||||
"callsites": "^3.1.0",
|
||||
"dot-prop": "^6.0.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"type-fest": "^2.3.4",
|
||||
"type-fest": "^1.2.1",
|
||||
"vali-date": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
|
@ -4542,11 +4552,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ow/node_modules/type-fest": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.5.2.tgz",
|
||||
"integrity": "sha512-WMbytmAs5PUTqwGJRE+WoRrD2S0bYFtHX8k4Y/1l18CG5kqA3keJud9pPQ/r30FE9n8XRFCXF9BbccHIZzRYJw==",
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
|
||||
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==",
|
||||
"engines": {
|
||||
"node": ">=12.20"
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
|
@ -6378,13 +6388,13 @@
|
|||
"dev": true
|
||||
},
|
||||
"@discordjs/builders": {
|
||||
"version": "0.8.1",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.1.tgz",
|
||||
"integrity": "sha512-kYJMvZ/BjRD1/6G2t1pQop2yoJNUmYvvKeG4mOBUCHFmfb7WIeBFmN/eSiP3cVSfRx3lbNiyxkdd5JzhjQnGbg==",
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.8.2.tgz",
|
||||
"integrity": "sha512-/YRd11SrcluqXkKppq/FAVzLIPRVlIVmc6X8ZklspzMIHDtJ+A4W37D43SHvLdH//+NnK+SHW/WeOF4Ts54PeQ==",
|
||||
"requires": {
|
||||
"@sindresorhus/is": "^4.2.0",
|
||||
"discord-api-types": "^0.24.0",
|
||||
"ow": "^0.28.1",
|
||||
"ow": "^0.27.0",
|
||||
"ts-mixer": "^6.0.0",
|
||||
"tslib": "^2.3.1"
|
||||
}
|
||||
|
@ -7576,6 +7586,11 @@
|
|||
"is-obj": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"dotenv": {
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q=="
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
|
@ -9265,22 +9280,22 @@
|
|||
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
|
||||
},
|
||||
"ow": {
|
||||
"version": "0.28.1",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.28.1.tgz",
|
||||
"integrity": "sha512-1EZTywPZeUKac9gD7q8np3Aj+V54kvfIcjNEVNDSbG2Ys5xA5foW2HquvMMqgyWGLqIFMlc0Iq/HmyMHqN48sA==",
|
||||
"version": "0.27.0",
|
||||
"resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz",
|
||||
"integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==",
|
||||
"requires": {
|
||||
"@sindresorhus/is": "^4.2.0",
|
||||
"@sindresorhus/is": "^4.0.1",
|
||||
"callsites": "^3.1.0",
|
||||
"dot-prop": "^6.0.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"type-fest": "^2.3.4",
|
||||
"type-fest": "^1.2.1",
|
||||
"vali-date": "^1.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"type-fest": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.5.2.tgz",
|
||||
"integrity": "sha512-WMbytmAs5PUTqwGJRE+WoRrD2S0bYFtHX8k4Y/1l18CG5kqA3keJud9pPQ/r30FE9n8XRFCXF9BbccHIZzRYJw=="
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz",
|
||||
"integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -5,19 +5,21 @@
|
|||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"build": "rimraf dist && tsc --project tsconfig.prod.json && npm prune --production",
|
||||
"start": "node .",
|
||||
"start": "node -r dotenv/config .",
|
||||
"once": "tsc && npm start",
|
||||
"dev": "tsc-watch --onSuccess \"npm run dev-instance\"",
|
||||
"dev-fast": "tsc-watch --onSuccess \"node . dev\"",
|
||||
"dev-instance": "rimraf dist && tsc && node . dev",
|
||||
"dev-fast": "tsc-watch --onSuccess \"node -r dotenv/config . dev\"",
|
||||
"dev-instance": "rimraf dist && tsc && node -r dotenv/config . dev",
|
||||
"test": "jest",
|
||||
"format": "prettier --write **/*",
|
||||
"postinstall": "husky install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@discordjs/builders": "^0.8.2",
|
||||
"canvas": "^2.8.0",
|
||||
"chalk": "^4.1.2",
|
||||
"discord.js": "^13.3.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"figlet": "^1.5.2",
|
||||
"glob": "^7.2.0",
|
||||
"inquirer": "^8.2.0",
|
||||
|
|
|
@ -8,7 +8,7 @@ module.exports = {
|
|||
jsxSingleQuote: false,
|
||||
trailingComma: "none",
|
||||
bracketSpacing: false,
|
||||
jsxBracketSameLine: false,
|
||||
bracketSameLine: false,
|
||||
arrowParens: "always",
|
||||
endOfLine: "auto" // Apparently, the GitHub repository still uses CRLF. I don't know how to force it to use LF, and until someone figures that out, I'm changing this to auto because I don't want more than one line ending commit.
|
||||
};
|
||||
|
|
91
slash-cmd-brainstorming.txt
Normal file
91
slash-cmd-brainstorming.txt
Normal file
|
@ -0,0 +1,91 @@
|
|||
-= [Fun] =-
|
||||
/8ball <question: string>
|
||||
/cookie all
|
||||
/cookie (<@user>)
|
||||
/eco show (<@user>)
|
||||
/eco daily - "... Same as /eco get."
|
||||
/eco get - "... Same as /eco daily."
|
||||
/eco pay <@user> <amount: int>
|
||||
/eco guild
|
||||
/eco leaderboard - "... Same as /eco top."
|
||||
/eco top - "... Same as /eco leaderboard."
|
||||
/eco buy <item: string>
|
||||
/eco shop
|
||||
/eco monday
|
||||
/eco bet <@user> <amount: int> <duration: string>
|
||||
/eco award <@user> (<amount: int>)
|
||||
/eco post
|
||||
/eco delete --- "Operation successful. 5000 rows affected."
|
||||
/figlet <input: string>
|
||||
/insult
|
||||
/love
|
||||
/ok
|
||||
/owoify <input>
|
||||
/party
|
||||
/pat (<@user>)
|
||||
/poll <question: string> (<seconds: int>)
|
||||
/ravi (<index: int>)
|
||||
/thonk (<text: string>)
|
||||
/urban <word: string>
|
||||
/vaporwave <text: string>
|
||||
/weather <city: string>
|
||||
/whoami
|
||||
/whois <@user>
|
||||
|
||||
-= [System] =- ("/admin other ..." if needed)
|
||||
/admin prefix (<prefix: string>)
|
||||
/admin messageembeds <enabled: boolean>
|
||||
/admin welcome type <[none, text, graphical]: string>
|
||||
/admin welcome channel <#channel>
|
||||
/admin stream <#channel>
|
||||
/admin defaultname (<name: string>)
|
||||
/admin logs (<verbosity: string>)
|
||||
/admin status
|
||||
/admin clear <amount: int>
|
||||
/admin nickname <nickname: string>
|
||||
/admin guilds
|
||||
/admin activity <type: string> (<description: string>)
|
||||
/admin syslog
|
||||
/admin autoroles list
|
||||
/admin autoroles reset
|
||||
/admin autoroles add <@role>
|
||||
/admin autoroles remove <@role>
|
||||
/admin streamroles set <@role> <category: string>
|
||||
/admin streamroles remove <@role>
|
||||
/webhook register <url: string>
|
||||
/webhook delete <url: string>
|
||||
|
||||
-= [Utility] =-
|
||||
/calc <expression: string>
|
||||
/code
|
||||
/desc <name: string>
|
||||
/docs <query: string>
|
||||
/emote <emotes: string>
|
||||
/info
|
||||
/info avatar (<@user>)
|
||||
/info bot
|
||||
/info guild <name: string>
|
||||
/info guild <id: int>
|
||||
/info <@user>
|
||||
/invite (<flag: int>)
|
||||
/lsemotes <regex: string> (<isCaseSensitive: boolean>)
|
||||
/purge
|
||||
/react <emotes: string> (<target: string>)
|
||||
/say <message: string>
|
||||
/scanemotes (<forceReset: boolean>)
|
||||
/shorten <url: string>
|
||||
/stream description set (<description: string>)
|
||||
/stream description remove
|
||||
/stream thumbnail set (<link: string>)
|
||||
/stream thumbnail remove
|
||||
/stream category set (<category: string>)
|
||||
/stream category remove
|
||||
/time show (<@user>)
|
||||
/time setup
|
||||
/time delete
|
||||
/time utc
|
||||
/time daylight
|
||||
/todo show
|
||||
/todo add <note: string>
|
||||
/todo remove <note: string>
|
||||
/todo clear
|
16
src/commands/fun/whoami.ts
Normal file
16
src/commands/fun/whoami.ts
Normal file
|
@ -0,0 +1,16 @@
|
|||
import {SlashCommandBuilder} from "@discordjs/builders";
|
||||
import {CommandInteraction} from "discord.js";
|
||||
import {registry} from "./whois";
|
||||
|
||||
export const header = new SlashCommandBuilder().setDescription("Tells you who you are");
|
||||
|
||||
export function handler(interaction: CommandInteraction) {
|
||||
const {user} = interaction;
|
||||
const id = user.id;
|
||||
|
||||
if (id in registry) {
|
||||
interaction.reply({content: `${user} ${registry[id]}`, allowedMentions: {parse: []}});
|
||||
} else {
|
||||
interaction.reply("You haven't been added to the registry yet!");
|
||||
}
|
||||
}
|
|
@ -1,8 +1,10 @@
|
|||
import {User} from "discord.js";
|
||||
import {Command, NamedCommand, getUserByNickname, RestCommand} from "onion-lasers";
|
||||
import {SlashCommandBuilder} from "@discordjs/builders";
|
||||
import {CommandInteraction} from "discord.js";
|
||||
|
||||
// Quotes must be used here or the numbers will change
|
||||
const registry: {[id: string]: string} = {
|
||||
export const registry: {[id: string]: string} = {
|
||||
"465662909645848577": "You're an idiot, that's what.",
|
||||
"306499531665833984":
|
||||
"Kuma, you eldritch fuck, I demand you to release me from this Discord bot and let me see my Chromebook!",
|
||||
|
@ -50,6 +52,24 @@ const registry: {[id: string]: string} = {
|
|||
"138840343855497216": "your face is a whois entry"
|
||||
};
|
||||
|
||||
export const header = new SlashCommandBuilder()
|
||||
.setDescription("Tells you who the specified user is")
|
||||
.addUserOption((option) =>
|
||||
option.setName("target").setDescription("The person to inquire about").setRequired(true)
|
||||
);
|
||||
|
||||
export function handler(interaction: CommandInteraction) {
|
||||
const {options} = interaction;
|
||||
const user = options.getUser("target", true);
|
||||
const id = user.id;
|
||||
|
||||
if (id in registry) {
|
||||
interaction.reply({content: `${user} ${registry[id]}`, allowedMentions: {parse: []}});
|
||||
} else {
|
||||
interaction.reply({content: `${user} hasn't been added to the registry yet!`, allowedMentions: {parse: []}});
|
||||
}
|
||||
}
|
||||
|
||||
export default new NamedCommand({
|
||||
description: "Tells you who you or the specified user is.",
|
||||
aliases: ["whoami"],
|
||||
|
|
|
@ -14,6 +14,9 @@ export const client = new Client({
|
|||
Intents.FLAGS.GUILD_MESSAGES,
|
||||
Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
|
||||
Intents.FLAGS.DIRECT_MESSAGES
|
||||
],
|
||||
partials: [
|
||||
"CHANNEL" // Needed so the bot can receive DM messages
|
||||
]
|
||||
});
|
||||
|
||||
|
@ -76,6 +79,7 @@ launch(client, path.join(__dirname, "commands"), {
|
|||
});
|
||||
|
||||
// Initialize Modules //
|
||||
import "./modules/slashCommands";
|
||||
import "./modules/ready";
|
||||
import "./modules/presence";
|
||||
// TODO: Reimplement entire music system, contact Sink
|
||||
|
|
54
src/modules/slashCommands.ts
Normal file
54
src/modules/slashCommands.ts
Normal file
|
@ -0,0 +1,54 @@
|
|||
import {client} from "../index";
|
||||
import {join} from "path";
|
||||
import {loadCommands} from "../modules/slashCommandsLoader";
|
||||
|
||||
loadCommands(join(__dirname, "..", "commands")).then((result) => {
|
||||
const [headers, handlers] = result;
|
||||
const useDevGuild = IS_DEV_MODE && !!process.env.DEV_GUILD;
|
||||
|
||||
// Send slash command data to Discord
|
||||
|
||||
client.on("ready", async () => {
|
||||
try {
|
||||
if (useDevGuild) {
|
||||
await client.guilds.cache
|
||||
.get(process.env.DEV_GUILD!)!
|
||||
.commands.set(headers.map((header) => header.toJSON()));
|
||||
} else {
|
||||
await client.application!.commands.set(headers.map((header) => header.toJSON()));
|
||||
}
|
||||
|
||||
console.log(
|
||||
`Successfully loaded command definitions into Discord using ${
|
||||
useDevGuild ? "development" : "production"
|
||||
} mode.`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
});
|
||||
|
||||
// Listen for slash commands
|
||||
|
||||
client.on("interactionCreate", async (interaction) => {
|
||||
if (interaction.isCommand()) {
|
||||
if (handlers.has(interaction.commandName)) {
|
||||
try {
|
||||
await handlers.get(interaction.commandName)!(interaction);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
// Use these when implementing subcommands and subcommand groups
|
||||
// interaction.options.getSubcommandGroup(false); // string if exists, null if not
|
||||
// interaction.options.getSubcommand(false); // string if exists, null if not
|
||||
} else {
|
||||
interaction.reply({
|
||||
content:
|
||||
"**Error:** Invalid command name! This probably means that the command definitions forgot to be updated.",
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
76
src/modules/slashCommandsLoader.ts
Normal file
76
src/modules/slashCommandsLoader.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
import {Collection, CommandInteraction} from "discord.js";
|
||||
import {SlashCommandBuilder} from "@discordjs/builders";
|
||||
import glob from "glob";
|
||||
import path from "path";
|
||||
|
||||
export async function loadCommands(
|
||||
commandsDir: string
|
||||
): Promise<
|
||||
[Collection<string, SlashCommandBuilder>, Collection<string, (interaction: CommandInteraction) => Promise<any>>]
|
||||
> {
|
||||
// Add a trailing separator so that the reduced filename list will reliably cut off the starting part.
|
||||
// "C:/some/path/to/commands" --> "C:/some/path/to/commands/" (and likewise for \)
|
||||
commandsDir = path.normalize(commandsDir);
|
||||
if (!commandsDir.endsWith(path.sep)) commandsDir += path.sep;
|
||||
|
||||
const headers = new Collection<string, SlashCommandBuilder>();
|
||||
const handlers = new Collection<string, () => Promise<any>>();
|
||||
const files = await globP(path.join(commandsDir, "**", "*.js")); // This stage filters out source maps (.js.map).
|
||||
// Because glob will use / regardless of platform, the following regex pattern can rely on / being the case.
|
||||
const filesClean = files.map((filename) => filename.substring(commandsDir.length));
|
||||
// Extract the usable parts from commands directory if the path is 1 to 2 subdirectories (a or a/b, not a/b/c).
|
||||
// No further checks will be made to exclude template command files or test command files, keeping it structure-agnostic.
|
||||
const pattern = /^([^/]+(?:\/[^/]+)?)\.js$/;
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const match = pattern.exec(filesClean[i]);
|
||||
if (!match) continue;
|
||||
const commandID = match[1]; // e.g. "utilities/info"
|
||||
const slashIndex = commandID.indexOf("/");
|
||||
const isMiscCommand = slashIndex !== -1;
|
||||
const commandName = isMiscCommand ? commandID.substring(slashIndex + 1) : commandID; // e.g. "info"
|
||||
|
||||
// This try-catch block MUST be here or Node.js' dynamic require() will silently fail.
|
||||
try {
|
||||
// If the dynamic import works, it must be an object at the very least. Then, just test to see if it's a proper instance.
|
||||
const {header, handler} = (await import(files[i])) as {header: unknown; handler: unknown};
|
||||
|
||||
if (header instanceof SlashCommandBuilder && handler instanceof Function) {
|
||||
if (headers.has(commandName) || handlers.has(commandName)) {
|
||||
console.warn(
|
||||
`Command "${commandID}" already exists! Make sure to make each command uniquely identifiable across categories!`
|
||||
);
|
||||
} else {
|
||||
// Set the slash command name to the filename only if there isn't already a name set
|
||||
if (header.name === undefined) {
|
||||
header.setName(commandName);
|
||||
}
|
||||
|
||||
headers.set(header.name, header);
|
||||
handlers.set(header.name, handler as any); // Just got to hope that the user puts in good data
|
||||
console.log(`Loaded Command: "${commandID}" as "${header.name}"`); // Use header.name to show what the slash command name is (should be the same)
|
||||
}
|
||||
} else {
|
||||
console.warn(
|
||||
`Command "${commandID}" doesn't export a "header" property (SlashCommandBuilder instance) or a "handler" property (function)!`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
|
||||
return [headers, handlers];
|
||||
}
|
||||
|
||||
function globP(path: string) {
|
||||
return new Promise<string[]>((resolve, reject) => {
|
||||
glob(path, (error, files) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
resolve(files);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Reference in a new issue