diff --git a/NodejsConsoleApp1.njsproj b/NodejsConsoleApp1.njsproj new file mode 100644 index 0000000..2482882 --- /dev/null +++ b/NodejsConsoleApp1.njsproj @@ -0,0 +1,121 @@ + + + 14.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + NodejsConsoleApp1 + NodejsConsoleApp1 + + + + Debug + 2.0 + 0dde9ded-3734-43ac-a218-393675657d81 + . + app.ts + False + + + . + . + v4.0 + {3AF33F2E-1136-4D97-BBB7-1795711AC8B8};{9092AA53-FB77-4645-B42D-1CCCA6BD08BD} + true + false + + + true + + + true + + + + + + + + + + + + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + Code + + + + + + + + + + + + False + True + 0 + / + http://localhost:48022/ + False + True + http://localhost:1337 + False + + + + + + + CurrentPage + True + False + False + False + + + + + + + + + False + False + + + + + \ No newline at end of file diff --git a/NodejsConsoleApp1.sln b/NodejsConsoleApp1.sln new file mode 100644 index 0000000..3c32d38 --- /dev/null +++ b/NodejsConsoleApp1.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31808.319 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9092AA53-FB77-4645-B42D-1CCCA6BD08BD}") = "NodejsConsoleApp1", "NodejsConsoleApp1.njsproj", "{0DDE9DED-3734-43AC-A218-393675657D81}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0DDE9DED-3734-43AC-A218-393675657D81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DDE9DED-3734-43AC-A218-393675657D81}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DDE9DED-3734-43AC-A218-393675657D81}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DDE9DED-3734-43AC-A218-393675657D81}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {86AD99D1-E808-449F-9D8E-174746181BE1} + EndGlobalSection +EndGlobal diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..4e4926a --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: node dist/index.js \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fe71799 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# NodejsConsoleApp1 + + diff --git a/app.js b/app.js new file mode 100644 index 0000000..8d2d434 --- /dev/null +++ b/app.js @@ -0,0 +1,23 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const Client_1 = require("./types/Client"); +const token = "NzIyMjE0MTA3MjM5MDIyNjcy.Xuf0TQ.R4epY00OqZSiY5zcfQ86Wo1GPg0"; +const client = new Client_1.MyClient("./commands/", "./events"); +client.on("ready", () => { + if (!client.user) + return; + console.info(`Logged in as ${client.user.tag}!`); + client.user.setActivity("on sound waves.", { type: "PLAYING" }); +}); +client.on("messageCreate", async (message) => { + if (message.guild) + await message.guild.commands.set(client.restCommands); +}); +client.on("interactionCreate", interaction => { + if (interaction.isCommand() && client.commands.has(interaction.commandName)) { + const command = client.commands.get(interaction.commandName); + command.run(client, interaction); + } +}); +client.login(token); +//# sourceMappingURL=app.js.map \ No newline at end of file diff --git a/app.js.map b/app.js.map new file mode 100644 index 0000000..b71c0ce --- /dev/null +++ b/app.js.map @@ -0,0 +1 @@ +{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,2CAA0C;AAE1C,MAAM,KAAK,GAAG,6DAA6D,CAAC;AAE5E,MAAM,MAAM,GAAG,IAAI,iBAAQ,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC;AAEvD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;IACpB,IAAI,CAAC,MAAM,CAAC,IAAI;QACZ,OAAO;IACX,OAAO,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;IACjD,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,iBAAiB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;IACzC,IAAI,OAAO,CAAC,KAAK;QACb,MAAM,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,WAAW,CAAC,EAAE;IACzC,IAAI,WAAW,CAAC,SAAS,EAAE,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,EAAE;QACzE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;KACpC;AACL,CAAC,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC"} \ No newline at end of file diff --git a/app.ts b/app.ts new file mode 100644 index 0000000..a963e5a --- /dev/null +++ b/app.ts @@ -0,0 +1,28 @@ +"use strict"; + +import { MyClient } from "./types/Client"; + +const token = process.env.DISCORD_TOKEN; + +const client = new MyClient("./commands/", "./events"); + +client.on("ready", () => { + if (!client.user) + return; + console.info(`Logged in as ${client.user.tag}!`); + client.user.setActivity("on sound waves.", { type: "PLAYING" }); +}); + +client.on("messageCreate", async (message) => { + if (message.guild) + await message.guild.commands.set(client.restCommands); +}); + +client.on("interactionCreate", interaction => { + if (interaction.isCommand() && client.commands.has(interaction.commandName)) { + const command = client.commands.get(interaction.commandName); + command.run(client, interaction); + } +}); + +client.login(token); \ No newline at end of file diff --git a/commands/clear.js b/commands/clear.js new file mode 100644 index 0000000..dd17f4a --- /dev/null +++ b/commands/clear.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + if (ctx.guildId === null) + return; + const player = client.players.getPlayer(ctx.guildId); + if (player) { + player.clear(); + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Queue has been cleared."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } +} +exports.run = run; +const data = { + name: "clear", + description: "Clears queue.", +}; +exports.data = data; +//# sourceMappingURL=clear.js.map \ No newline at end of file diff --git a/commands/clear.js.map b/commands/clear.js.map new file mode 100644 index 0000000..471a2d6 --- /dev/null +++ b/commands/clear.js.map @@ -0,0 +1 @@ +{"version":3,"file":"clear.js","sourceRoot":"","sources":["clear.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4I;AAOrI,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI;QACpB,OAAO;IAEX,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAErD,IAAI,MAAM,EAAE;QACR,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;aAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;aACzC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAEzC,IAAI;YACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SACxC;QAAC,MAAM,GAAG;KACd;AACL,CAAC;AAjBD,kBAiBC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,eAAe;CAC/B,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/clear.ts b/commands/clear.ts new file mode 100644 index 0000000..223ae92 --- /dev/null +++ b/commands/clear.ts @@ -0,0 +1,34 @@ +import { design } from "../config"; + +import { ButtonInteraction, ColorResolvable, CommandInteraction, Message, MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; +import { generateQueue } from "../types/Misc"; +import { EmojiIdentifierResolvable } from "discord.js"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + if (ctx.guildId === null) + return; + + const player = client.players.getPlayer(ctx.guildId); + + if (player) { + player.clear(); + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Queue has been cleared."); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } +} + +const data = { + name: "clear", + description: "Clears queue.", +} + +export { data } \ No newline at end of file diff --git a/commands/connect.js b/commands/connect.js new file mode 100644 index 0000000..c7f8295 --- /dev/null +++ b/commands/connect.js @@ -0,0 +1,42 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + if (ctx.guildId === null) + return; + let player = client.players.getPlayer(ctx.guildId); + if (!player) + player = client.players.genPlayer(ctx.guildId); + if (!player.connection) { + const channel = ctx.member.voice.channel; + if (channel) { + await player.connect(channel); + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle(`Successfully connected to ${channel.name}.`); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } + else { + client.players.delPlayer(ctx.guildId); + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Please connect to a voice channel."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } + } +} +exports.run = run; +const data = { + name: "connect", + description: "Connect to voice channel." +}; +exports.data = data; +//# sourceMappingURL=connect.js.map \ No newline at end of file diff --git a/commands/connect.js.map b/commands/connect.js.map new file mode 100644 index 0000000..e36ee58 --- /dev/null +++ b/commands/connect.js.map @@ -0,0 +1 @@ +{"version":3,"file":"connect.js","sourceRoot":"","sources":["connect.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4F;AAKrF,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI;QACpB,OAAO;IAGX,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM;QACP,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACpB,MAAM,OAAO,GAAI,GAAG,CAAC,MAAsB,CAAC,KAAK,CAAC,OAAO,CAAC;QAC1D,IAAI,OAAO,EAAE;YACT,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAE9B,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;iBAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;iBACzC,QAAQ,CAAC,6BAA6B,OAAO,CAAC,IAAI,GAAG,CAAC,CAAA;YAE3D,IAAI;gBACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aACxC;YAAC,MAAM,GAAG;SACd;aACI;YACD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAEtC,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;iBAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;iBACzC,QAAQ,CAAC,oCAAoC,CAAC,CAAA;YAEnD,IAAI;gBACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;aACxC;YAAC,MAAM,GAAG;SACd;KACJ;AACL,CAAC;AAnCD,kBAmCC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,2BAA2B;CAC3C,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/connect.ts b/commands/connect.ts new file mode 100644 index 0000000..37b3822 --- /dev/null +++ b/commands/connect.ts @@ -0,0 +1,50 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + if (ctx.guildId === null) + return; + + + let player = client.players.getPlayer(ctx.guildId); + + if (!player) + player = client.players.genPlayer(ctx.guildId); + + if (!player.connection) { + const channel = (ctx.member as GuildMember).voice.channel; + if (channel) { + await player.connect(channel); + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle(`Successfully connected to ${channel.name}.`) + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + else { + client.players.delPlayer(ctx.guildId); + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Please connect to a voice channel.") + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + } +} + +const data = { + name: "connect", + description: "Connect to voice channel." +} + +export { data } \ No newline at end of file diff --git a/commands/insert.js b/commands/insert.js new file mode 100644 index 0000000..aa82228 --- /dev/null +++ b/commands/insert.js @@ -0,0 +1,46 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + const pos = ctx.options.getString("position"); + const query = ctx.options.getString("query"); + if (ctx.guildId === null || query === null) + return; + let player = client.players.getPlayer(ctx.guildId); + if (!player) + return; + let state; + if (!isNaN(Number(query))) { + await player.addTrack(query, ctx.user, Number(query) - 1); + } + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Inserted."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } +} +exports.run = run; +const data = { + name: "insert", + description: "Insert new track to specific position.", + options: [ + { + name: "query", + description: "Title or URL of the song.", + type: "STRING", + required: true + }, + { + name: "position", + description: "Position to insert.", + type: "STRING", + required: true + } + ] +}; +exports.data = data; +//# sourceMappingURL=insert.js.map \ No newline at end of file diff --git a/commands/insert.js.map b/commands/insert.js.map new file mode 100644 index 0000000..473f4f9 --- /dev/null +++ b/commands/insert.js.map @@ -0,0 +1 @@ +{"version":3,"file":"insert.js","sourceRoot":"","sources":["insert.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4F;AAKrF,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,MAAM,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE7C,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;QACtC,OAAO;IAGX,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM;QACP,OAAO;IAEX,IAAI,KAAc,CAAC;IAEnB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;QACvB,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;KAC7D;IAED,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;SAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;SACzC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAE3B,IAAI;QACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACxC;IAAC,MAAM,GAAG;AAEf,CAAC;AA3BD,kBA2BC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,wCAAwC;IACrD,OAAO,EAAE;QACL;YACI,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;SACjB;QACD;YACI,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,qBAAqB;YAClC,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;SACjB;KACJ;CACJ,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/insert.ts b/commands/insert.ts new file mode 100644 index 0000000..986ff6b --- /dev/null +++ b/commands/insert.ts @@ -0,0 +1,56 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + const pos = ctx.options.getString("position"); + const query = ctx.options.getString("query"); + + if (ctx.guildId === null || query === null) + return; + + + let player = client.players.getPlayer(ctx.guildId); + + if (!player) + return; + + let state: boolean; + + if (!isNaN(Number(query))) { + await player.addTrack(query, ctx.user, Number(query) - 1); + } + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Inserted."); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + +} + +const data = { + name: "insert", + description: "Insert new track to specific position.", + options: [ + { + name: "query", + description: "Title or URL of the song.", + type: "STRING", + required: true + }, + { + name: "position", + description: "Position to insert.", + type: "STRING", + required: true + } + ] +} + +export { data } \ No newline at end of file diff --git a/commands/jump.js b/commands/jump.js new file mode 100644 index 0000000..5baeadf --- /dev/null +++ b/commands/jump.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + const query = ctx.options.getString("position"); + if (ctx.guildId === null || query === null) + return; + let player = client.players.getPlayer(ctx.guildId); + if (!player) + return; + let state; + if (!isNaN(Number(query))) { + state = await player.jump(Number(query) - 1); + } + else { + state = await player.jump(query); + } + if (state) { + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Jumped."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } +} +exports.run = run; +const data = { + name: "jump", + description: "Jump to specific track in queue.", + options: [ + { + name: "position", + description: "Position to jump to.", + type: "STRING", + required: true + } + ] +}; +exports.data = data; +//# sourceMappingURL=jump.js.map \ No newline at end of file diff --git a/commands/jump.js.map b/commands/jump.js.map new file mode 100644 index 0000000..8e57507 --- /dev/null +++ b/commands/jump.js.map @@ -0,0 +1 @@ +{"version":3,"file":"jump.js","sourceRoot":"","sources":["jump.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4F;AAKrF,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAEhD,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;QACtC,OAAO;IAGX,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM;QACP,OAAO;IAEX,IAAI,KAAc,CAAC;IAEnB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;QACvB,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;KAChD;SAAM;QACH,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;KACpC;IAED,IAAI,KAAK,EAAE;QACP,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;aAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;aACzC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAEzB,IAAI;YACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SACxC;QAAC,MAAM,GAAG;KACd;AAEL,CAAC;AA9BD,kBA8BC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,kCAAkC;IAC/C,OAAO,EAAE;QACL;YACI,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,sBAAsB;YACnC,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;SACjB;KACJ;CACJ,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/jump.ts b/commands/jump.ts new file mode 100644 index 0000000..094cff0 --- /dev/null +++ b/commands/jump.ts @@ -0,0 +1,53 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + const query = ctx.options.getString("position"); + + if (ctx.guildId === null || query === null) + return; + + + let player = client.players.getPlayer(ctx.guildId); + + if (!player) + return; + + let state: boolean; + + if (!isNaN(Number(query))) { + state = await player.jump(Number(query) - 1); + } else { + state = await player.jump(query); + } + + if (state) { + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Jumped."); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + +} + +const data = { + name: "jump", + description: "Jump to specific track in queue.", + options: [ + { + name: "position", + description: "Position to jump to.", + type: "STRING", + required: true + } + ] +} + +export { data } \ No newline at end of file diff --git a/commands/next.js b/commands/next.js new file mode 100644 index 0000000..737aa86 --- /dev/null +++ b/commands/next.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + if (ctx.guildId === null) + return; + const player = client.players.getPlayer(ctx.guildId); + if (player) + player.skip(); + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Skipped."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } +} +exports.run = run; +const data = { + name: "next", + description: "Skip current song." +}; +exports.data = data; +//# sourceMappingURL=next.js.map \ No newline at end of file diff --git a/commands/next.js.map b/commands/next.js.map new file mode 100644 index 0000000..4c92ec9 --- /dev/null +++ b/commands/next.js.map @@ -0,0 +1 @@ +{"version":3,"file":"next.js","sourceRoot":"","sources":["next.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA+E;AAKxE,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI;QACpB,OAAO;IAGX,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAErD,IAAI,MAAM;QACN,MAAM,CAAC,IAAI,EAAE,CAAC;IAElB,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;SAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;SACzC,QAAQ,CAAC,UAAU,CAAC,CAAC;IAE1B,IAAI;QACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACxC;IAAC,MAAM,GAAG;AACf,CAAC;AAjBD,kBAiBC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,oBAAoB;CACpC,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/next.ts b/commands/next.ts new file mode 100644 index 0000000..6bb6a80 --- /dev/null +++ b/commands/next.ts @@ -0,0 +1,32 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + if (ctx.guildId === null) + return; + + + const player = client.players.getPlayer(ctx.guildId); + + if (player) + player.skip(); + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Skipped."); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } +} + +const data = { + name: "next", + description: "Skip current song." +} + +export { data } \ No newline at end of file diff --git a/commands/pause.js b/commands/pause.js new file mode 100644 index 0000000..98b2a1c --- /dev/null +++ b/commands/pause.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + if (ctx.guildId === null) + return; + const player = client.players.getPlayer(ctx.guildId); + if (player) { + const state = player.pause(); + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle(`Pause is now ${state ? "on" : "off"}.`); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } +} +exports.run = run; +const data = { + name: "pause", + description: "Toggle pause.", +}; +exports.data = data; +//# sourceMappingURL=pause.js.map \ No newline at end of file diff --git a/commands/pause.js.map b/commands/pause.js.map new file mode 100644 index 0000000..ab335af --- /dev/null +++ b/commands/pause.js.map @@ -0,0 +1 @@ +{"version":3,"file":"pause.js","sourceRoot":"","sources":["pause.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4I;AAOrI,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI;QACpB,OAAO;IAEX,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAErD,IAAI,MAAM,EAAE;QACR,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC;QAE7B,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;aAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;aACzC,QAAQ,CAAC,gBAAgB,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC;QAEvD,IAAI;YACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SACxC;QAAC,MAAM,GAAG;KACd;AAGL,CAAC;AAnBD,kBAmBC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,OAAO;IACb,WAAW,EAAE,eAAe;CAC/B,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/pause.ts b/commands/pause.ts new file mode 100644 index 0000000..7f2d44e --- /dev/null +++ b/commands/pause.ts @@ -0,0 +1,36 @@ +import { design } from "../config"; + +import { ButtonInteraction, ColorResolvable, CommandInteraction, Message, MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; +import { generateQueue } from "../types/Misc"; +import { EmojiIdentifierResolvable } from "discord.js"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + if (ctx.guildId === null) + return; + + const player = client.players.getPlayer(ctx.guildId); + + if (player) { + const state = player.pause(); + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle(`Pause is now ${state ? "on" : "off"}.`); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + + +} + +const data = { + name: "pause", + description: "Toggle pause.", +} + +export { data } \ No newline at end of file diff --git a/commands/play.js b/commands/play.js new file mode 100644 index 0000000..5aa7345 --- /dev/null +++ b/commands/play.js @@ -0,0 +1,59 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + const query = ctx.options.getString("query"); + if (ctx.guildId === null || query === null) + return; + let player = client.players.getPlayer(ctx.guildId); + if (!player) + player = client.players.genPlayer(ctx.guildId); + if (!player.connection) { + const channel = ctx.member.voice.channel; + if (channel) { + await player.connect(channel); + } + else { + client.players.delPlayer(ctx.guildId); + await ctx.reply("Please connect to a voice chat."); + return; + } + } + const track = await player.addTrack(query, ctx.user); + if (!player.nowPlaying) { + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Preparing player."); + player.setMessage(await ctx.channel.send({ embeds: [embed] })); + await player.play(); + } + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle(track.title) + .setDescription("Has been pushed to queue.") + .setURL(track.url) + .setThumbnail(track.thumbnail) + .setAuthor(`@${ctx.user.tag}`, ctx.user.avatarURL()); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + console.log(`${track.title} added to ${ctx.guildId}`); +} +exports.run = run; +const data = { + name: "play", + description: "Play a song or add it to queue.", + options: [ + { + name: "query", + description: "Title or URL of the song.", + type: "STRING", + required: true + } + ] +}; +exports.data = data; +//# sourceMappingURL=play.js.map \ No newline at end of file diff --git a/commands/play.js.map b/commands/play.js.map new file mode 100644 index 0000000..0b060e7 --- /dev/null +++ b/commands/play.js.map @@ -0,0 +1 @@ +{"version":3,"file":"play.js","sourceRoot":"","sources":["play.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4F;AAKrF,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAE7C,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;QACtC,OAAO;IAGX,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM;QACP,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACpB,MAAM,OAAO,GAAI,GAAG,CAAC,MAAsB,CAAC,KAAK,CAAC,OAAO,CAAC;QAC1D,IAAI,OAAO,EAAE;YACT,MAAM,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;SACjC;aACI;YACD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACtC,MAAM,GAAG,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;YACnD,OAAO;SACV;KACJ;IAED,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;IAErD,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE;QACpB,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;aAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;aACzC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;QAEnC,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/D,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;KACvB;IAGD,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;SAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;SACzC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC;SACrB,cAAc,CAAC,2BAA2B,CAAC;SAC3C,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC;SACjB,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC;SAC7B,SAAS,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,EAAY,CAAC,CAAC;IAEnE,IAAI;QACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;KACxC;IAAC,MAAM,GAAE;IAEV,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,KAAK,aAAa,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AAE1D,CAAC;AAlDD,kBAkDC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,iCAAiC;IAC9C,OAAO,EAAE;QACL;YACI,IAAI,EAAE,OAAO;YACb,WAAW,EAAE,2BAA2B;YACxC,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;SACjB;KACJ;CACJ,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/play.ts b/commands/play.ts new file mode 100644 index 0000000..459db3f --- /dev/null +++ b/commands/play.ts @@ -0,0 +1,73 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + const query = ctx.options.getString("query"); + + if (ctx.guildId === null || query === null) + return; + + + let player = client.players.getPlayer(ctx.guildId); + + if (!player) + player = client.players.genPlayer(ctx.guildId); + + if (!player.connection) { + const channel = (ctx.member as GuildMember).voice.channel; + if (channel) { + await player.connect(channel); + } + else { + client.players.delPlayer(ctx.guildId); + await ctx.reply("Please connect to a voice chat."); + return; + } + } + + const track = await player.addTrack(query, ctx.user); + + if (!player.nowPlaying) { + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Preparing player."); + + player.setMessage(await ctx.channel.send({ embeds: [embed] })); + await player.play(); + } + + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle(track.title) + .setDescription("Has been pushed to queue.") + .setURL(track.url) + .setThumbnail(track.thumbnail) + .setAuthor(`@${ctx.user.tag}`, ctx.user.avatarURL() as string); + + try { + await ctx.reply({ embeds: [embed] }); + } catch {} + + console.log(`${track.title} added to ${ctx.guildId}`); + +} + +const data = { + name: "play", + description: "Play a song or add it to queue.", + options: [ + { + name: "query", + description: "Title or URL of the song.", + type: "STRING", + required: true + } + ] +} + +export { data } \ No newline at end of file diff --git a/commands/queue.js b/commands/queue.js new file mode 100644 index 0000000..3c3816d --- /dev/null +++ b/commands/queue.js @@ -0,0 +1,65 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +const Misc_1 = require("../types/Misc"); +async function run(client, ctx) { + if (ctx.guildId === null) + return; + const player = client.players.getPlayer(ctx.guildId); + if (player) { + const queue = player.queue; + if (queue.length === 0) { + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Queue is empty."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } + else { + let page = 0; + const maxPage = Math.floor(queue.length / 11); + const row = new discord_js_1.MessageActionRow() + .addComponents(new discord_js_1.MessageButton() + .setCustomId("QueueTop") + .setLabel("TOP") + .setStyle("SECONDARY"), new discord_js_1.MessageButton() + .setCustomId("QueueUp") + .setLabel("UP") + .setStyle("SECONDARY"), new discord_js_1.MessageButton() + .setCustomId("QueueDown") + .setLabel("DOWN") + .setStyle("SECONDARY"), new discord_js_1.MessageButton() + .setCustomId("QueueEnd") + .setLabel("END") + .setStyle("SECONDARY")); + await ctx.reply({ + content: (0, Misc_1.generateQueue)(queue, page, player.queuePosition), + components: [row] + }); + const filter = (btn) => btn.message === ctx.fetchReply(); + const collector = ctx.channel.createMessageComponentCollector({ filter, time: 15000 }); + collector.on("collect", async (btn) => { + switch (btn.customId) { + case "QueueTop": page = 0; + case "QueueUp": page = Math.max(page - 1, 0); + case "QueueDown": page = Math.min(page + 1, maxPage); + case "QueueEnd": page = maxPage; + } + await btn.update({ + content: (0, Misc_1.generateQueue)(queue, page, player.queuePosition) + }); + }); + } + } +} +exports.run = run; +const data = { + name: "queue", + description: "Send player queue.", +}; +exports.data = data; +//# sourceMappingURL=queue.js.map \ No newline at end of file diff --git a/commands/queue.js.map b/commands/queue.js.map new file mode 100644 index 0000000..2378e35 --- /dev/null +++ b/commands/queue.js.map @@ -0,0 +1 @@ +{"version":3,"file":"queue.js","sourceRoot":"","sources":["queue.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/commands/queue.ts b/commands/queue.ts new file mode 100644 index 0000000..de3df4c --- /dev/null +++ b/commands/queue.ts @@ -0,0 +1,85 @@ +import { design } from "../config"; + +import { ButtonInteraction, ColorResolvable, CommandInteraction, Message, MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; +import { generateQueue } from "../types/Misc"; +import { EmojiIdentifierResolvable } from "discord.js"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + if (ctx.guildId === null) + return; + + const player = client.players.getPlayer(ctx.guildId); + + if (player) { + const queue = player.queue; + + if (queue.length === 0) { + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Queue is empty."); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + else { + let page = 0; + const maxPage = Math.floor(queue.length / 11); + + const row = new MessageActionRow() + .addComponents( + new MessageButton() + .setCustomId("QueueTop") + .setLabel("TOP") + .setStyle("SECONDARY"), + new MessageButton() + .setCustomId("QueueUp") + .setLabel("UP") + .setStyle("SECONDARY"), + new MessageButton() + .setCustomId("QueueDown") + .setLabel("DOWN") + .setStyle("SECONDARY"), + new MessageButton() + .setCustomId("QueueEnd") + .setLabel("END") + .setStyle("SECONDARY") + ); + + await ctx.reply({ + content: generateQueue(queue, page, player.queuePosition), + components: [row] + }); + + const filter = (btn: ButtonInteraction) => btn.message === ctx.fetchReply() as unknown as Message; + + const collector = ctx.channel.createMessageComponentCollector({ filter, time: 15000 }); + + collector.on("collect", async (btn: ButtonInteraction) => { + switch (btn.customId) { + case "QueueTop": page = 0; + case "QueueUp": page = Math.max(page - 1, 0); + case "QueueDown": page = Math.min(page + 1, maxPage); + case "QueueEnd": page = maxPage; + } + + await btn.update({ + content: generateQueue(queue, page, player.queuePosition) + }); + }); + + } + } + + +} + +const data = { + name: "queue", + description: "Send player queue.", +} + +export { data } \ No newline at end of file diff --git a/commands/remove.js b/commands/remove.js new file mode 100644 index 0000000..5bd7c90 --- /dev/null +++ b/commands/remove.js @@ -0,0 +1,44 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +const config_1 = require("../config"); +const discord_js_1 = require("discord.js"); +async function run(client, ctx) { + const query = ctx.options.getString("position"); + if (ctx.guildId === null || query === null) + return; + let player = client.players.getPlayer(ctx.guildId); + if (!player) + return; + let state; + if (!isNaN(Number(query))) { + state = await player.remove(Number(query) - 1); + } + else { + state = await player.remove(query); + } + if (state) { + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle("Removed."); + try { + await ctx.reply({ embeds: [embed] }); + } + catch { } + } +} +exports.run = run; +const data = { + name: "remove", + description: "Remove specific track in queue.", + options: [ + { + name: "position", + description: "Position to remove.", + type: "STRING", + required: true + } + ] +}; +exports.data = data; +//# sourceMappingURL=remove.js.map \ No newline at end of file diff --git a/commands/remove.js.map b/commands/remove.js.map new file mode 100644 index 0000000..923551c --- /dev/null +++ b/commands/remove.js.map @@ -0,0 +1 @@ +{"version":3,"file":"remove.js","sourceRoot":"","sources":["remove.ts"],"names":[],"mappings":";;;AAAA,sCAAmC;AAEnC,2CAA4F;AAKrF,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;IAEhD,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,KAAK,KAAK,IAAI;QACtC,OAAO;IAGX,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,CAAC,MAAM;QACP,OAAO;IAEX,IAAI,KAAc,CAAC;IAEnB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE;QACvB,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;KAClD;SAAM;QACH,KAAK,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;KACtC;IAED,IAAI,KAAK,EAAE;QACP,MAAM,KAAK,GAAG,IAAI,yBAAY,EAAE;aAC3B,QAAQ,CAAC,eAAM,CAAC,KAAwB,CAAC;aACzC,QAAQ,CAAC,UAAU,CAAC,CAAC;QAE1B,IAAI;YACA,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;SACxC;QAAC,MAAM,GAAG;KACd;AAEL,CAAC;AA9BD,kBA8BC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,QAAQ;IACd,WAAW,EAAE,iCAAiC;IAC9C,OAAO,EAAE;QACL;YACI,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,qBAAqB;YAClC,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,IAAI;SACjB;KACJ;CACJ,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/remove.ts b/commands/remove.ts new file mode 100644 index 0000000..b46ae99 --- /dev/null +++ b/commands/remove.ts @@ -0,0 +1,53 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + const query = ctx.options.getString("position"); + + if (ctx.guildId === null || query === null) + return; + + + let player = client.players.getPlayer(ctx.guildId); + + if (!player) + return; + + let state: boolean; + + if (!isNaN(Number(query))) { + state = await player.remove(Number(query) - 1); + } else { + state = await player.remove(query); + } + + if (state) { + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle("Removed."); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + +} + +const data = { + name: "remove", + description: "Remove specific track in queue.", + options: [ + { + name: "position", + description: "Position to remove.", + type: "STRING", + required: true + } + ] +} + +export { data } \ No newline at end of file diff --git a/commands/seek.js b/commands/seek.js new file mode 100644 index 0000000..ca2fb27 --- /dev/null +++ b/commands/seek.js @@ -0,0 +1,26 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.data = exports.run = void 0; +async function run(client, ctx) { + const time = ctx.options.getInteger("time"); + if (ctx.guildId === null || time === null) + return; + let player = client.players.getPlayer(ctx.guildId); + if (player) + await player.seek(time); +} +exports.run = run; +const data = { + name: "seek", + description: "Fastforward to timecode.", + options: [ + { + name: "time", + description: "Timecode to seek.", + type: "INTEGER", + required: true + } + ] +}; +exports.data = data; +//# sourceMappingURL=seek.js.map \ No newline at end of file diff --git a/commands/seek.js.map b/commands/seek.js.map new file mode 100644 index 0000000..250acc3 --- /dev/null +++ b/commands/seek.js.map @@ -0,0 +1 @@ +{"version":3,"file":"seek.js","sourceRoot":"","sources":["seek.ts"],"names":[],"mappings":";;;AAOO,KAAK,UAAU,GAAG,CAAC,MAAgB,EAAE,GAAuB;IAC/D,MAAM,IAAI,GAAG,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAE5C,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI;QACrC,OAAO;IAGX,IAAI,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAEnD,IAAI,MAAM;QACN,MAAM,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAXD,kBAWC;AAED,MAAM,IAAI,GAAG;IACT,IAAI,EAAE,MAAM;IACZ,WAAW,EAAE,0BAA0B;IACvC,OAAO,EAAE;QACL;YACI,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,mBAAmB;YAChC,IAAI,EAAE,SAAS;YACf,QAAQ,EAAE,IAAI;SACjB;KACJ;CACJ,CAAA;AAEQ,oBAAI"} \ No newline at end of file diff --git a/commands/seek.ts b/commands/seek.ts new file mode 100644 index 0000000..ce2ceff --- /dev/null +++ b/commands/seek.ts @@ -0,0 +1,34 @@ +import { design } from "../config"; + +import { ColorResolvable, CommandInteraction, GuildMember, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + const time = ctx.options.getInteger("time"); + + if (ctx.guildId === null || time === null) + return; + + + let player = client.players.getPlayer(ctx.guildId); + + if (player) + await player.seek(time); +} + +const data = { + name: "seek", + description: "Fastforward to timecode.", + options: [ + { + name: "time", + description: "Timecode to seek.", + type: "INTEGER", + required: true + } + ] +} + +export { data } \ No newline at end of file diff --git a/commands/stop.ts b/commands/stop.ts new file mode 100644 index 0000000..5a006b3 --- /dev/null +++ b/commands/stop.ts @@ -0,0 +1,36 @@ +import { design } from "../config"; + +import { ButtonInteraction, ColorResolvable, CommandInteraction, Message, MessageActionRow, MessageButton, MessageEmbed } from "discord.js"; +import { MyClient } from "../types/Client"; +import { generateQueue } from "../types/Misc"; +import { EmojiIdentifierResolvable } from "discord.js"; + + + +export async function run(client: MyClient, ctx: CommandInteraction) { + if (ctx.guildId === null) + return; + + const player = client.players.getPlayer(ctx.guildId); + + if (player) { + player.destroy(); + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle(`Destroyed.`); + + try { + await ctx.reply({ embeds: [embed] }); + } catch { } + } + + +} + +const data = { + name: "pause", + description: "Toggle pause.", +} + +export { data } \ No newline at end of file diff --git a/config.js b/config.js new file mode 100644 index 0000000..fa98efe --- /dev/null +++ b/config.js @@ -0,0 +1,8 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.design = void 0; +const design = { + color: '#C4A4BE' +}; +exports.design = design; +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/config.js.map b/config.js.map new file mode 100644 index 0000000..52dcf6e --- /dev/null +++ b/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":";;;AAAA,MAAM,MAAM,GAAG;IACX,KAAK,EAAE,SAAS;CACnB,CAAA;AAEO,wBAAM"} \ No newline at end of file diff --git a/config.ts b/config.ts new file mode 100644 index 0000000..5a3d08b --- /dev/null +++ b/config.ts @@ -0,0 +1,5 @@ +const design = { + color: '#C4A4BE' +} + +export {design} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..69cd129 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,755 @@ +{ + "name": "nodejs-console-app1", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "nodejs-console-app1", + "version": "0.0.0", + "devDependencies": { + "@discordjs/voice": "0.6.0", + "@types/node": "^14.14.7", + "discord-ytdl-core": "5.0.4", + "discord.js": "13.2.0", + "typescript": "^4.0.5", + "ytsr": "3.5.3" + } + }, + "node_modules/@discordjs/builders": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz", + "integrity": "sha512-mH3Gx61LKk2CD05laCI9K5wp+a3NyASHDUGx83DGJFkqJlRlSV5WMJNY6RS37A5SjqDtGMF4wVR9jzFaqShe6Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "discord-api-types": "^0.22.0", + "ow": "^0.27.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1" + }, + "engines": { + "node": ">=14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@discordjs/collection": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz", + "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@discordjs/voice": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.6.0.tgz", + "integrity": "sha512-DF2fZAnB8gX3Qz5BEWPOUl565ptpda1uVmXJije4iK5aQrECfkqc6XcI+wzbGaNvzsH1Wb76NPzxngsEw8bblw==", + "dev": true, + "dependencies": { + "@types/ws": "^7.4.4", + "discord-api-types": "^0.22.0", + "prism-media": "^1.3.1", + "tiny-typed-emitter": "^2.0.3", + "ws": "^7.4.4" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@sapphire/async-queue": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.7.tgz", + "integrity": "sha512-EBRERa9NqK/EV6DIPBVtjjdHBsu/DSdMuYAydmoIyIPONzp0UAxf2G6JGJ52WkiONtPRx6KNuqB5Q8dm14fwyw==", + "dev": true, + "engines": { + "node": ">=v14.0.0", + "npm": ">=7.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@types/node": { + "version": "14.17.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.29.tgz", + "integrity": "sha512-sd4CHI9eTJXTH2vF3RGtGkqvWRwhsSSUFsXD4oG38GZzSZ0tNPbWikd2AbOAcKxCXhOg57fL8FPxjpfSzb2pIQ==", + "dev": true + }, + "node_modules/@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/discord-api-types": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", + "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/discord-ytdl-core": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/discord-ytdl-core/-/discord-ytdl-core-5.0.4.tgz", + "integrity": "sha512-O+G9wuCw5TERR9iHZFMYnYQbs/ZGudDc9cxa1OKSV5TdcBYrHGS1JqvE90ZvSQ6SmS4XvqtOf/Okls6yiGJ3sg==", + "dev": true, + "dependencies": { + "prism-media": "^1.2.9" + }, + "funding": { + "type": "individual", + "url": "https://paypal.me/devsnowflake" + } + }, + "node_modules/discord.js": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.2.0.tgz", + "integrity": "sha512-nyxUvL8wuQG38zx13wUMkpcA8koFszyiXdkSLwwM9opKW2LC2H5gD0cTZxImeJ6GtEnKPWT8xBiE8lLBmbNIhw==", + "dev": true, + "dependencies": { + "@discordjs/builders": "^0.6.0", + "@discordjs/collection": "^0.2.1", + "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.5", + "@types/ws": "^8.2.0", + "discord-api-types": "^0.23.1", + "node-fetch": "^2.6.1", + "ws": "^8.2.3" + }, + "engines": { + "node": ">=16.6.0", + "npm": ">=7.0.0" + } + }, + "node_modules/discord.js/node_modules/@types/ws": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.0.tgz", + "integrity": "sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/discord.js/node_modules/discord-api-types": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz", + "integrity": "sha512-igWmn+45mzXRWNEPU25I/pr8MwxHb767wAr51oy3VRLRcTlp5ADBbrBR0lq3SA1Rfw3MtM4TQu1xo3kxscfVdQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/discord.js/node_modules/ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "node_modules/mime-db": { + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", + "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", + "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "dev": true, + "dependencies": { + "mime-db": "1.50.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/miniget": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.1.tgz", + "integrity": "sha512-O/DduzDR6f+oDtVype9S/Qu5hhnx73EDYGyZKwU/qN82lehFZdfhoa4DT51SpsO+8epYrB3gcRmws56ROfTIoQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-fetch": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "dev": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/ow": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", + "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prism-media": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz", + "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==", + "dev": true, + "peerDependencies": { + "@discordjs/opus": "^0.5.0", + "ffmpeg-static": "^4.2.7 || ^3.0.0 || ^2.4.0", + "node-opus": "^0.3.3", + "opusscript": "^0.0.8" + }, + "peerDependenciesMeta": { + "@discordjs/opus": { + "optional": true + }, + "ffmpeg-static": { + "optional": true + }, + "node-opus": { + "optional": true + }, + "opusscript": { + "optional": true + } + } + }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "dev": true + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "node_modules/ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/ytsr": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/ytsr/-/ytsr-3.5.3.tgz", + "integrity": "sha512-BEyIKbQULmk27hiVUQ1cBszAqP8roPBOQTWPZpBioKxjSZBeicfgF2qPIQoY7koodQwRuo1DmCFz3DyrXjADxg==", + "dev": true, + "dependencies": { + "miniget": "^4.2.1" + }, + "engines": { + "node": ">=8" + } + } + }, + "dependencies": { + "@discordjs/builders": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.6.0.tgz", + "integrity": "sha512-mH3Gx61LKk2CD05laCI9K5wp+a3NyASHDUGx83DGJFkqJlRlSV5WMJNY6RS37A5SjqDtGMF4wVR9jzFaqShe6Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.1", + "discord-api-types": "^0.22.0", + "ow": "^0.27.0", + "ts-mixer": "^6.0.0", + "tslib": "^2.3.1" + } + }, + "@discordjs/collection": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.2.1.tgz", + "integrity": "sha512-vhxqzzM8gkomw0TYRF3tgx7SwElzUlXT/Aa41O7mOcyN6wIJfj5JmDWaO5XGKsGSsNx7F3i5oIlrucCCWV1Nog==", + "dev": true + }, + "@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, + "@discordjs/voice": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@discordjs/voice/-/voice-0.6.0.tgz", + "integrity": "sha512-DF2fZAnB8gX3Qz5BEWPOUl565ptpda1uVmXJije4iK5aQrECfkqc6XcI+wzbGaNvzsH1Wb76NPzxngsEw8bblw==", + "dev": true, + "requires": { + "@types/ws": "^7.4.4", + "discord-api-types": "^0.22.0", + "prism-media": "^1.3.1", + "tiny-typed-emitter": "^2.0.3", + "ws": "^7.4.4" + } + }, + "@sapphire/async-queue": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.1.7.tgz", + "integrity": "sha512-EBRERa9NqK/EV6DIPBVtjjdHBsu/DSdMuYAydmoIyIPONzp0UAxf2G6JGJ52WkiONtPRx6KNuqB5Q8dm14fwyw==", + "dev": true + }, + "@sindresorhus/is": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.2.0.tgz", + "integrity": "sha512-VkE3KLBmJwcCaVARtQpfuKcKv8gcBmUubrfHGF84dXuuW6jgsRYxPtzcIhPyK9WAPpRt2/xY6zkD9MnRaJzSyw==", + "dev": true + }, + "@types/node": { + "version": "14.17.29", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.29.tgz", + "integrity": "sha512-sd4CHI9eTJXTH2vF3RGtGkqvWRwhsSSUFsXD4oG38GZzSZ0tNPbWikd2AbOAcKxCXhOg57fL8FPxjpfSzb2pIQ==", + "dev": true + }, + "@types/ws": { + "version": "7.4.7", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-7.4.7.tgz", + "integrity": "sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "discord-api-types": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.22.0.tgz", + "integrity": "sha512-l8yD/2zRbZItUQpy7ZxBJwaLX/Bs2TGaCthRppk8Sw24LOIWg12t9JEreezPoYD0SQcC2htNNo27kYEpYW/Srg==", + "dev": true + }, + "discord-ytdl-core": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/discord-ytdl-core/-/discord-ytdl-core-5.0.4.tgz", + "integrity": "sha512-O+G9wuCw5TERR9iHZFMYnYQbs/ZGudDc9cxa1OKSV5TdcBYrHGS1JqvE90ZvSQ6SmS4XvqtOf/Okls6yiGJ3sg==", + "dev": true, + "requires": { + "prism-media": "^1.2.9" + } + }, + "discord.js": { + "version": "13.2.0", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.2.0.tgz", + "integrity": "sha512-nyxUvL8wuQG38zx13wUMkpcA8koFszyiXdkSLwwM9opKW2LC2H5gD0cTZxImeJ6GtEnKPWT8xBiE8lLBmbNIhw==", + "dev": true, + "requires": { + "@discordjs/builders": "^0.6.0", + "@discordjs/collection": "^0.2.1", + "@discordjs/form-data": "^3.0.1", + "@sapphire/async-queue": "^1.1.5", + "@types/ws": "^8.2.0", + "discord-api-types": "^0.23.1", + "node-fetch": "^2.6.1", + "ws": "^8.2.3" + }, + "dependencies": { + "@types/ws": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.2.0.tgz", + "integrity": "sha512-cyeefcUCgJlEk+hk2h3N+MqKKsPViQgF5boi9TTHSK+PoR9KWBb/C5ccPcDyAqgsbAYHTwulch725DV84+pSpg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "discord-api-types": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.23.1.tgz", + "integrity": "sha512-igWmn+45mzXRWNEPU25I/pr8MwxHb767wAr51oy3VRLRcTlp5ADBbrBR0lq3SA1Rfw3MtM4TQu1xo3kxscfVdQ==", + "dev": true + }, + "ws": { + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", + "dev": true, + "requires": {} + } + } + }, + "dot-prop": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-6.0.1.tgz", + "integrity": "sha512-tE7ztYzXHIeyvc7N+hR3oi7FIbf/NIjVP9hmAt3yMXzrQ072/fpjGLx2GxNxGxUl5V73MEqYzioOMoVhGMJ5cA==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, + "mime-db": { + "version": "1.50.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.50.0.tgz", + "integrity": "sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A==", + "dev": true + }, + "mime-types": { + "version": "2.1.33", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.33.tgz", + "integrity": "sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g==", + "dev": true, + "requires": { + "mime-db": "1.50.0" + } + }, + "miniget": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.1.tgz", + "integrity": "sha512-O/DduzDR6f+oDtVype9S/Qu5hhnx73EDYGyZKwU/qN82lehFZdfhoa4DT51SpsO+8epYrB3gcRmws56ROfTIoQ==", + "dev": true + }, + "node-fetch": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.5.tgz", + "integrity": "sha512-mmlIVHJEu5rnIxgEgez6b9GgWXbkZj5YZ7fx+2r94a2E+Uirsp6HsPTPlomfdHtpt/B0cdKviwkoaM6pyvUOpQ==", + "dev": true, + "requires": { + "whatwg-url": "^5.0.0" + } + }, + "ow": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/ow/-/ow-0.27.0.tgz", + "integrity": "sha512-SGnrGUbhn4VaUGdU0EJLMwZWSupPmF46hnTRII7aCLCrqixTAC5eKo8kI4/XXf1eaaI8YEVT+3FeGNJI9himAQ==", + "dev": true, + "requires": { + "@sindresorhus/is": "^4.0.1", + "callsites": "^3.1.0", + "dot-prop": "^6.0.1", + "lodash.isequal": "^4.5.0", + "type-fest": "^1.2.1", + "vali-date": "^1.0.0" + } + }, + "prism-media": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.3.2.tgz", + "integrity": "sha512-L6UsGHcT6i4wrQhFF1aPK+MNYgjRqR2tUoIqEY+CG1NqVkMjPRKzS37j9f8GiYPlD6wG9ruBj+q5Ax+bH8Ik1g==", + "dev": true, + "requires": {} + }, + "tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==", + "dev": true + }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=", + "dev": true + }, + "ts-mixer": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/ts-mixer/-/ts-mixer-6.0.0.tgz", + "integrity": "sha512-nXIb1fvdY5CBSrDIblLn73NW0qRDk5yJ0Sk1qPBF560OdJfQp9jhl+0tzcY09OZ9U+6GpeoI9RjwoIKFIoB9MQ==", + "dev": true + }, + "tslib": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", + "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==", + "dev": true + }, + "type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true + }, + "typescript": { + "version": "4.4.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.4.4.tgz", + "integrity": "sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==", + "dev": true + }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=", + "dev": true + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "dev": true, + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "ws": { + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.5.tgz", + "integrity": "sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w==", + "dev": true, + "requires": {} + }, + "ytsr": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/ytsr/-/ytsr-3.5.3.tgz", + "integrity": "sha512-BEyIKbQULmk27hiVUQ1cBszAqP8roPBOQTWPZpBioKxjSZBeicfgF2qPIQoY7koodQwRuo1DmCFz3DyrXjADxg==", + "dev": true, + "requires": { + "miniget": "^4.2.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..853a621 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "nodejs-console-app1", + "engines": { "node": "16.9.1" }, + "version": "0.0.0", + "description": "NodejsConsoleApp1", + "main": "app.js", + "author": { + "name": "" + }, + "scripts": { + "start": "node dist/index.js", + "postinstall": "tsc", + "watch-node": "nodemon dist/index.js", + "watch-ts": "tsc -w", + "deploy": "git add . && git commit -m Heroku && git push heroku master" + }, + "dependencies": { + "@types/node": "^14.14.7", + "typescript": "^4.0.5", + "discord.js": "13.2.0", + "@discordjs/voice": "0.6.0", + "discord-ytdl-core": "5.0.4", + "ytsr": "3.5.3" + + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a0f5e8d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "module": "CommonJS", + "target": "ESNext", + "esModuleInterop": true, + "moduleResolution": "Node", + "lib": ["ESNext", "DOM"], + "sourceMap": true + }, + "exclude": [ + "node_modules" + ] +} diff --git a/types/Client.js b/types/Client.js new file mode 100644 index 0000000..34c8187 --- /dev/null +++ b/types/Client.js @@ -0,0 +1,49 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.MyClient = void 0; +const discord_js_1 = require("discord.js"); +const fs_1 = require("fs"); +const Music_1 = require("./Music"); +class MyClient extends discord_js_1.Client { + commands = new Map(); + restCommands = []; + players = new Music_1.Music(); + constructor(commandsPath, eventsPath) { + super({ + intents: [ + discord_js_1.Intents.FLAGS.GUILDS, + discord_js_1.Intents.FLAGS.GUILD_MESSAGES, + discord_js_1.Intents.FLAGS.GUILD_VOICE_STATES + ] + }); + const cmdFiles = (0, fs_1.readdirSync)(commandsPath).filter(file => file.endsWith(".js")); + for (const file of cmdFiles) { + Promise.resolve().then(() => __importStar(require(`../commands/${file}`))).then((command) => { + const name = command.data.name; + this.restCommands.push(command.data); + this.commands.set(name, command); + }); + } + } +} +exports.MyClient = MyClient; +//# sourceMappingURL=Client.js.map \ No newline at end of file diff --git a/types/Client.js.map b/types/Client.js.map new file mode 100644 index 0000000..57e46de --- /dev/null +++ b/types/Client.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Client.js","sourceRoot":"","sources":["Client.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAqE;AACrE,2BAAiC;AACjC,mCAAgC;AAGhC,MAAa,QAAS,SAAQ,mBAAM;IAChC,QAAQ,GAAG,IAAI,GAAG,EAAe,CAAC;IAClC,YAAY,GAA6B,EAAE,CAAC;IAC5C,OAAO,GAAG,IAAI,aAAK,EAAE,CAAC;IAGtB,YAAY,YAAoB,EAAE,UAAkB;QAChD,KAAK,CAAC;YACF,OAAO,EAAE;gBACL,oBAAO,CAAC,KAAK,CAAC,MAAM;gBACpB,oBAAO,CAAC,KAAK,CAAC,cAAc;gBAC5B,oBAAO,CAAC,KAAK,CAAC,kBAAkB;aACnC;SACJ,CAAC,CAAC;QAEH,MAAM,QAAQ,GAAG,IAAA,gBAAW,EAAC,YAAY,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;QAEhF,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE;YACzB,kDAAO,eAAe,IAAI,EAAE,IAAE,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE;gBAC3C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC/B,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;gBACrC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YACrC,CAAC,CAAC,CAAC;SACN;IACL,CAAC;CACJ;AAzBD,4BAyBC"} \ No newline at end of file diff --git a/types/Client.ts b/types/Client.ts new file mode 100644 index 0000000..beb88a7 --- /dev/null +++ b/types/Client.ts @@ -0,0 +1,31 @@ +import { ApplicationCommandData, Client, Intents } from "discord.js"; +import { readdirSync } from "fs"; +import { Music } from "./Music"; + + +export class MyClient extends Client { + commands = new Map(); + restCommands: ApplicationCommandData[] = []; + players = new Music(); + + + constructor(commandsPath: string, eventsPath: string) { + super({ + intents: [ + Intents.FLAGS.GUILDS, + Intents.FLAGS.GUILD_MESSAGES, + Intents.FLAGS.GUILD_VOICE_STATES + ] + }); + + const cmdFiles = readdirSync(commandsPath).filter(file => file.endsWith(".js")); + + for (const file of cmdFiles) { + import(`../commands/${file}`).then((command) => { + const name = command.data.name; + this.restCommands.push(command.data); + this.commands.set(name, command); + }); + } + } +} \ No newline at end of file diff --git a/types/Misc.js b/types/Misc.js new file mode 100644 index 0000000..1ebc02e --- /dev/null +++ b/types/Misc.js @@ -0,0 +1,27 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.generateQueue = exports.random_shuffle = void 0; +function random_shuffle(array) { + let currentIndex = array.length, randomIndex; + while (currentIndex != 0) { + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]]; + } + return array; +} +exports.random_shuffle = random_shuffle; +function generateQueue(queue, page, pos) { + let response = "```ml\n"; + for (let i = page * 11; i < Math.min(queue.length, (page + 1) * 11); i++) { + const track = queue[i]; + if (i === pos) + response += `${i + 1}. Current => ${track.title.slice(0, 35).padEnd(45, " ")} ${Math.floor(parseInt(track.duration) / 60)}:${parseInt(track.duration) % 60}\n`; + else + response += `${i + 1}. ${track.title.slice(0, 35).padEnd(45, " ")} ${Math.floor(parseInt(track.duration) / 60)}:${parseInt(track.duration) % 60}\n`; + } + response += '```'; + return response; +} +exports.generateQueue = generateQueue; +//# sourceMappingURL=Misc.js.map \ No newline at end of file diff --git a/types/Misc.js.map b/types/Misc.js.map new file mode 100644 index 0000000..080db2a --- /dev/null +++ b/types/Misc.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Misc.js","sourceRoot":"","sources":["Misc.ts"],"names":[],"mappings":";;;AAEA,SAAgB,cAAc,CAAC,KAAiB;IAC5C,IAAI,YAAY,GAAG,KAAK,CAAC,MAAM,EAAG,WAAW,CAAC;IAE9C,OAAO,YAAY,IAAI,CAAC,EAAE;QACtB,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,YAAY,CAAC,CAAC;QACvD,YAAY,EAAE,CAAC;QAEf,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;KACzF;IAED,OAAO,KAAK,CAAC;AACjB,CAAC;AAXD,wCAWC;AAED,SAAgB,aAAa,CAAC,KAAc,EAAE,IAAY,EAAE,GAAW;IACnE,IAAI,QAAQ,GAAW,SAAS,CAAC;IAEjC,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QACtE,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEvB,IAAI,CAAC,KAAK,GAAG;YACT,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,gBAAgB,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;;YAE/J,QAAQ,IAAI,GAAG,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;KAE3J;IAED,QAAQ,IAAI,KAAK,CAAC;IAElB,OAAO,QAAQ,CAAC;AACpB,CAAC;AAhBD,sCAgBC"} \ No newline at end of file diff --git a/types/Misc.ts b/types/Misc.ts new file mode 100644 index 0000000..60dc900 --- /dev/null +++ b/types/Misc.ts @@ -0,0 +1,32 @@ +import { track } from "./interfaces"; + +export function random_shuffle(array: Array) { + let currentIndex = array.length, randomIndex; + + while (currentIndex != 0) { + randomIndex = Math.floor(Math.random() * currentIndex); + currentIndex--; + + [array[currentIndex], array[randomIndex]] = [array[randomIndex], array[currentIndex]]; + } + + return array; +} + +export function generateQueue(queue: track[], page: number, pos: number): string { + let response: string = "```ml\n"; + + for (let i = page * 11; i < Math.min(queue.length, (page + 1) * 11); i++) { + const track = queue[i]; + + if (i === pos) + response += `${i + 1}. Current => ${track.title.slice(0, 35).padEnd(45, " ")} ${Math.floor(parseInt(track.duration) / 60)}:${parseInt(track.duration) % 60}\n`; + else + response += `${i + 1}. ${track.title.slice(0, 35).padEnd(45, " ")} ${Math.floor(parseInt(track.duration) / 60)}:${parseInt(track.duration) % 60}\n`; + + } + + response += '```'; + + return response; +} \ No newline at end of file diff --git a/types/Music.js b/types/Music.js new file mode 100644 index 0000000..b748cf2 --- /dev/null +++ b/types/Music.js @@ -0,0 +1,201 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.Music = exports.Player = void 0; +const voice_1 = require("@discordjs/voice"); +const discord_js_1 = require("discord.js"); +const config_1 = require("../config"); +const ytdl = require("discord-ytdl-core"); +const ytsr = require("ytsr"); +const Misc_1 = require("./Misc"); +class Player { + guild; + music; + connection; + player; + message; + queue = []; + queuePosition = 0; + nowPlaying = undefined; + filters = []; + repeatMode = 0; + constructor(clientMusic, playerGuild) { + this.music = clientMusic; + this.guild = playerGuild; + } + async play(seek = 0) { + if (!this.connection || this.queue.length === 0) + return; + const track = this.queue[this.queuePosition]; + const stream = ytdl(track.url, { + opusEncoded: true, + filter: "audioonly", + highWaterMark: 1 << 25, + seek: seek + }); + const resource = (0, voice_1.createAudioResource)(stream, { + inlineVolume: true, + metadata: track + }); + this.player = await (0, voice_1.createAudioPlayer)(); + this.connection.subscribe(this.player); + await this.player.play(resource); + this.nowPlaying = resource; + if (this.message) { + const channel = this.message.channel; + try { + await this.message.delete(); + } + catch (err) { + console.log(err); + } + const embed = new discord_js_1.MessageEmbed() + .setColor(config_1.design.color) + .setTitle(track.title) + .setURL(track.url) + .setThumbnail(track.thumbnail) + .setAuthor(`@${track.requester.tag}`, track.requester.avatarURL()) + .setDescription("Is now beeing played."); + this.message = await channel.send({ embeds: [embed] }); + } + this.player.on(voice_1.AudioPlayerStatus.Idle, async () => { + this.queuePosition = (this.queuePosition + 1) % this.queue.length; + await this.play(); + }); + } + async connect(channel) { + this.connection = (0, voice_1.joinVoiceChannel)({ + channelId: channel.id, + guildId: channel.guildId, + selfDeaf: true, + adapterCreator: channel.guild.voiceAdapterCreator + }); + } + async addTrack(query, requester, index) { + let songInfo; + if (ytdl.validateURL(query)) + songInfo = await ytdl.getInfo(query); + else + songInfo = await ytdl.getInfo((await ytsr(query)).refinements[0].url); + const metadata = { + url: songInfo.videoDetails.video_url, + title: songInfo.videoDetails.title, + thumbnail: songInfo.videoDetails.thumbnails[0].url, + duration: songInfo.videoDetails.lengthSeconds, + requester: requester + }; + if (!index) + this.queue.push(metadata); + else { + this.queue.splice(index, 0, metadata); + if (this.queuePosition >= index) + this.queuePosition++; + } + return metadata; + } + clear() { + this.queue = []; + this.queuePosition = 0; + this.nowPlaying = undefined; + if (this.player) + this.player.stop(); + } + destroy() { + if (this.connection) + this.connection.disconnect(); + this.music.delPlayer(this.guild.id); + } + async jump(query) { + if (!this.player) + return false; + if (typeof query === "number" && query < this.queue.length && query >= 0) { + this.queuePosition = query; + await this.play(); + return true; + } + else { + for (let i = 0; i < this.queue.length; i++) { + const track = this.queue[i]; + if (track.title.toLowerCase().includes(String(query).toLowerCase())) { + this.queuePosition = i; + await this.play(); + return true; + } + } + } + return false; + } + remove(query) { + if (typeof query === "number" && query < this.queue.length && query >= 0) { + if (query === this.queuePosition) + this.player.stop(); + this.queue.splice(query); + return true; + } + else { + for (let i = 0; i < this.queue.length; i++) { + const track = this.queue[i]; + if (track.title.toLowerCase().includes(String(query).toLowerCase())) { + if (i === this.queuePosition) + this.player.stop(); + this.queue.splice(i); + return true; + } + } + } + return false; + } + async seek(time) { + await this.play(time); + } + pause() { + if (!this.player) + return false; + if (this.player.state.status === voice_1.AudioPlayerStatus.Paused) { + this.player.unpause(); + return false; + } + else { + this.player.pause(); + return true; + } + } + repeat(mode) { + this.repeatMode = mode; + } + volume(amount) { + if (amount > 0 && amount < Infinity && this.nowPlaying && this.nowPlaying.volume) { + this.nowPlaying.volume.setVolumeLogarithmic(amount / 100); + return true; + } + return false; + } + shuffle() { + this.queue = (0, Misc_1.random_shuffle)(this.queue); + } + skip() { + if (this.player) + this.player.stop(); + } + setMessage(message) { + this.message = message; + } +} +exports.Player = Player; +class Music { + players = new Map(); + getPlayer(guildId) { + const player = this.players.get(guildId); + if (player) + return player; + } + genPlayer(guildId) { + const player = new module.exports.Player(); + this.players.set(guildId, player); + return player; + } + delPlayer(guildId) { + this.players.delete(guildId); + } +} +exports.Music = Music; +//# sourceMappingURL=Music.js.map \ No newline at end of file diff --git a/types/Music.js.map b/types/Music.js.map new file mode 100644 index 0000000..5b9f6cb --- /dev/null +++ b/types/Music.js.map @@ -0,0 +1 @@ +{"version":3,"file":"Music.js","sourceRoot":"","sources":["Music.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/types/Music.ts b/types/Music.ts new file mode 100644 index 0000000..425b671 --- /dev/null +++ b/types/Music.ts @@ -0,0 +1,236 @@ +import { VoiceConnection, AudioPlayer, createAudioResource, AudioPlayerStatus, joinVoiceChannel, createAudioPlayer, AudioResource, DiscordGatewayAdapterCreator } from "@discordjs/voice"; +import { ColorResolvable, Guild, Message, MessageEmbed, StageChannel, User, VoiceChannel } from "discord.js"; +import { design } from "../config"; +const ytdl = require("discord-ytdl-core"); +const ytsr = require("ytsr"); +import { track, filter } from "./interfaces"; +import { random_shuffle } from "./Misc"; + +export class Player { + guild: Guild; + music: Music; + + connection: VoiceConnection | undefined; + player: AudioPlayer | undefined; + message: Message | undefined; + + queue: track[] = []; + queuePosition = 0; + nowPlaying: AudioResource | undefined = undefined; + filters: filter[] = []; + repeatMode = 0; + + constructor(clientMusic: Music, playerGuild: Guild) { + this.music = clientMusic; + this.guild = playerGuild; + } + + async play(seek = 0) { + if (!this.connection || this.queue.length === 0) + return; + + + const track = this.queue[this.queuePosition]; + + const stream = ytdl(track.url, { + opusEncoded: true, + filter: "audioonly", + highWaterMark: 1 << 25, + seek: seek + }); + + const resource = createAudioResource(stream, { + inlineVolume: true, + metadata: track + }); + + this.player = await createAudioPlayer(); + this.connection.subscribe(this.player); + + await this.player.play(resource); + this.nowPlaying = resource; + + if (this.message) { + const channel = this.message.channel; + + try { + await this.message.delete(); + } catch (err) { + console.log(err); + } + + const embed = new MessageEmbed() + .setColor(design.color as ColorResolvable) + .setTitle(track.title) + .setURL(track.url) + .setThumbnail(track.thumbnail) + .setAuthor(`@${track.requester.tag}`, track.requester.avatarURL() as string) + .setDescription("Is now beeing played."); + + this.message = await channel.send({ embeds: [embed] }); + } + + + this.player.on(AudioPlayerStatus.Idle, async () => { + this.queuePosition = (this.queuePosition + 1) % this.queue.length; + await this.play(); + }); + } + + async connect(channel: VoiceChannel | StageChannel) { + this.connection = joinVoiceChannel({ + channelId: channel.id, + guildId: channel.guildId, + selfDeaf: true, + adapterCreator: channel.guild.voiceAdapterCreator as unknown as DiscordGatewayAdapterCreator + }); + } + + async addTrack(query: string, requester: User, index?: number): Promise { + let songInfo; + + if (ytdl.validateURL(query)) + songInfo = await ytdl.getInfo(query); + else + songInfo = await ytdl.getInfo((await ytsr(query)).refinements[0].url); + + const metadata: track = { + url: songInfo.videoDetails.video_url, + title: songInfo.videoDetails.title, + thumbnail: songInfo.videoDetails.thumbnails[0].url, + duration: songInfo.videoDetails.lengthSeconds, + requester: requester + }; + + if (!index) + this.queue.push(metadata); + else { + this.queue.splice(index, 0, metadata) + if (this.queuePosition >= index) + this.queuePosition++; + } + + return metadata; + } + + clear() { + this.queue = []; + this.queuePosition = 0; + this.nowPlaying = undefined; + if (this.player) + this.player.stop(); + } + + destroy() { + if (this.connection) + this.connection.disconnect(); + this.music.delPlayer(this.guild.id); + } + + async jump(query: number | string): Promise { + if (!this.player) + return false; + + if (typeof query === "number" && query < this.queue.length && query >= 0) { + this.queuePosition = query; + await this.play(); + return true; + } + else { + for (let i = 0; i < this.queue.length; i++) { + const track = this.queue[i]; + if (track.title.toLowerCase().includes(String(query).toLowerCase())) { + this.queuePosition = i; + await this.play(); + return true; + } + } + } + return false; + } + + remove(query: number | string): boolean { + if (typeof query === "number" && query < this.queue.length && query >= 0) { + if (query === this.queuePosition) + this.player.stop(); + this.queue.splice(query); + return true; + } + else { + for (let i = 0; i < this.queue.length; i++) { + const track = this.queue[i]; + if (track.title.toLowerCase().includes(String(query).toLowerCase())) { + if (i === this.queuePosition) + this.player.stop(); + this.queue.splice(i); + return true; + } + } + } + return false; + } + + async seek(time: number) { + await this.play(time); + } + + pause(): boolean { + if (!this.player) + return false; + + if (this.player.state.status === AudioPlayerStatus.Paused) { + this.player.unpause(); + return false; + } + else { + this.player.pause(); + return true; + } + } + + repeat(mode: number) { + this.repeatMode = mode; + } + + volume(amount: number): boolean { + if (amount > 0 && amount < Infinity && this.nowPlaying && this.nowPlaying.volume) { + this.nowPlaying.volume.setVolumeLogarithmic(amount / 100); + return true; + } + return false; + } + + shuffle() { + this.queue = random_shuffle(this.queue); + } + + skip() { + if (this.player) + this.player.stop(); + } + + setMessage(message: Message) { + this.message = message; + } + +} + +export class Music { + players = new Map(); + + getPlayer(guildId: string): Player | undefined { + const player = this.players.get(guildId); + if (player) + return player; + } + + genPlayer(guildId: string): Player { + const player = new module.exports.Player(); + this.players.set(guildId, player); + return player; + } + + delPlayer(guildId: string) { + this.players.delete(guildId); + } +} \ No newline at end of file diff --git a/types/interfaces.js b/types/interfaces.js new file mode 100644 index 0000000..db91911 --- /dev/null +++ b/types/interfaces.js @@ -0,0 +1,3 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +//# sourceMappingURL=interfaces.js.map \ No newline at end of file diff --git a/types/interfaces.js.map b/types/interfaces.js.map new file mode 100644 index 0000000..0fc31ba --- /dev/null +++ b/types/interfaces.js.map @@ -0,0 +1 @@ +{"version":3,"file":"interfaces.js","sourceRoot":"","sources":["interfaces.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/types/interfaces.ts b/types/interfaces.ts new file mode 100644 index 0000000..317365e --- /dev/null +++ b/types/interfaces.ts @@ -0,0 +1,45 @@ +import { User } from "discord.js"; + +export interface track { + url: string; + title: string; + thumbnail: string; + duration: string; + requester: User; +} + +export interface filter { + bassboost_low?: boolean; + bassboost?: boolean; + bassboost_high?: boolean; + "8D"?: boolean; + vaporwave?: boolean; + nightcore?: boolean; + phaser?: boolean; + tremolo?: boolean; + vibrato?: boolean; + reverse?: boolean; + treble?: boolean; + normalizer?: boolean; + normalizer2?: boolean; + surrounding?: boolean; + pulsator?: boolean; + subboost?: boolean; + karaoke?: boolean; + flanger?: boolean; + gate?: boolean; + haas?: boolean; + mcompand?: boolean; + mono?: boolean; + mstlr?: boolean; + mstrr?: boolean; + compressor?: boolean; + expander?: boolean; + softlimiter?: boolean; + chorus?: boolean; + chorus2d?: boolean; + chorus3d?: boolean; + fadein?: boolean; + dim?: boolean; + earrape?: boolean; +} \ No newline at end of file