Refactoring, comments & overall improvements

This commit is contained in:
deytenit committed 2024-01-30 14:31:15 +03:00
1 parent d7421251ba
commit 3144dd69b7
60 files changed
+1106 -708

No files matched your search

+36
View File
@@ -0,0 +1,36 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
const amount = player.queue.tracks.length;
player.clear();
await interaction.reply(replies.cleared(amount));
}
const data = new SlashCommandBuilder()
.setName("clear")
.setDescription("Clear the player's queue.")
.setDMPermission(false);
export { data, execute };
+44
View File
@@ -0,0 +1,44 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction): Promise<void> {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
await interaction.deferReply();
const player =
controller.get(interaction.guild, interaction.channel) ??
controller.set(interaction.guild, interaction.channel);
const channel = interaction.member.voice.channel;
if (!channel) {
controller.delete(interaction.guildId);
await interaction.editReply(replies.notConnected());
return;
}
player.connect(channel);
await interaction.editReply(replies.okConnected(channel.name));
return;
}
const data = new SlashCommandBuilder()
.setName("connect")
.setDescription("Connect me explicitly to the voice channel.")
.setDMPermission(false);
export { data, execute };
+43
View File
@@ -0,0 +1,43 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import Filter from "../lib/filter.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const filter = interaction.options.getString("filter") ?? undefined;
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
const status = player.setFilter(filter);
await interaction.reply(replies.filtered(filter, status));
}
const data = new SlashCommandBuilder()
.setName("filter")
.setDescription("Apply unique filters to the playback.")
.addStringOption((option) =>
option
.setName("filter")
.setDescription("Filter to apply.")
.setChoices(...Object.values(Filter.FILTERS))
)
.setDMPermission(false);
export { data, execute };
+32
View File
@@ -0,0 +1,32 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
await interaction.reply(replies.info(player));
}
const data = new SlashCommandBuilder()
.setName("info")
.setDescription("Verbose information about player and stats.")
.setDMPermission(false);
export { data, execute };
+45
View File
@@ -0,0 +1,45 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const query = interaction.options.getString("query", true);
const pos = interaction.options.getInteger("position", true);
await interaction.deferReply();
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.editReply(replies.notExists());
return;
}
const track = await player.add(query, interaction.user, pos - 1);
await interaction.editReply(replies.appended(track));
}
const data = new SlashCommandBuilder()
.setName("insert")
.setDescription("Insert a new track to specific position in the queue.")
.addStringOption((option) =>
option.setName("query").setDescription("Title or URL of the song.").setRequired(true)
)
.addIntegerOption((option) =>
option.setName("position").setDescription("Position to insert.").setRequired(true)
)
.setDMPermission(false);
export { data, execute };
+44
View File
@@ -0,0 +1,44 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const query = interaction.options.getString("query", true);
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
const previous = player.resource?.metadata;
const position =
!isNaN(+query) && isFinite(+query) && !/e/i.test(query)
? player.jump(parseInt(query) - 1)
: player.jump(query);
await interaction.reply(replies.jumped(previous, position));
}
const data = new SlashCommandBuilder()
.setName("jump")
.setDescription("Jump to specific track in the queue.")
.addStringOption((option) =>
option.setName("query").setDescription("Position or title to jump to.").setRequired(true)
)
.setDMPermission(false);
export { data, execute };
+49
View File
@@ -0,0 +1,49 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { LoopOption } from "../lib/types.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const option = interaction.options.getString("option", true) as LoopOption;
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
player.queue.loop = option;
await interaction.reply(replies.looped(option));
}
const data = new SlashCommandBuilder()
.setName("loop")
.setDescription("Select player's loop mode.")
.addStringOption((option) =>
option
.setName("option")
.setDescription("Loop option.")
.setChoices(
{ name: "Loop queue", value: "LOOP" },
{ name: "Loop single track", value: "SONG" },
{ name: "Drop on final", value: "NONE" },
{ name: "Random", value: "AUTO" }
)
.setRequired(true)
)
.setDMPermission(false);
export { data, execute };
+34
View File
@@ -0,0 +1,34 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
player.skip();
await interaction.reply(replies.skipped());
}
const data = new SlashCommandBuilder()
.setName("next")
.setDescription("Skip current song.")
.setDMPermission(false);
export { data, execute };
+34
View File
@@ -0,0 +1,34 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
const state = player.pause();
await interaction.reply(replies.paused(state));
}
const data = new SlashCommandBuilder()
.setName("pause")
.setDescription("Toggle pause on playback.")
.setDMPermission(false);
export { data, execute };
+59
View File
@@ -0,0 +1,59 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const query = interaction.options.getString("query");
if (query) {
await interaction.reply(replies.searching());
} else {
await interaction.deferReply();
}
const player =
controller.get(interaction.guild, interaction.channel) ??
controller.set(interaction.guild, interaction.channel);
const channel = interaction.member.voice.channel;
if (!channel) {
controller.delete(interaction.guildId);
await interaction.editReply(replies.notConnected());
return;
}
player.connect(channel);
if (query) {
const track = await player.add(query, interaction.user);
await interaction.editReply(replies.appended(track));
}
if (!player.resource) {
await player.play();
}
}
const data = new SlashCommandBuilder()
.setName("play")
.setDescription("Launch player and add songs to the queue.")
.addStringOption((option) =>
option.setName("query").setDescription("Title or URL of the song.")
)
.setDMPermission(false);
export { data, execute };
+87
View File
@@ -0,0 +1,87 @@
import {
ActionRowBuilder,
ButtonBuilder,
ButtonInteraction,
ButtonStyle,
ChatInputCommandInteraction,
MessageActionRowComponentBuilder,
SlashCommandBuilder
} from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
await interaction.deferReply();
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.editReply(replies.notExists());
return;
}
if (player.queue.empty()) {
await interaction.editReply(replies.queue(player.queue));
return;
}
let position = 1;
const row = new ActionRowBuilder<MessageActionRowComponentBuilder>().addComponents(
new ButtonBuilder().setCustomId("Top").setLabel("🔼").setStyle(ButtonStyle.Primary),
new ButtonBuilder().setCustomId("Up").setLabel("🔺").setStyle(ButtonStyle.Secondary),
new ButtonBuilder().setCustomId("Down").setLabel("🔻").setStyle(ButtonStyle.Secondary),
new ButtonBuilder().setCustomId("End").setLabel("🔽").setStyle(ButtonStyle.Primary)
);
const message = await interaction.editReply({
...replies.queue(player.queue, 0, player.resource),
components: [row]
});
const collector = message.createMessageComponentCollector({ time: 30000 });
collector.on("collect", async (btn: ButtonInteraction) => {
switch (btn.customId) {
case "Top": {
position = 1;
break;
}
case "Up": {
position = Math.max(position - 10, 1);
break;
}
case "Down": {
position = Math.min(
position + 10,
Math.floor(player.queue.tracks.length / 10) * 10
);
break;
}
case "End": {
position = Math.floor(player.queue.tracks.length / 10) * 10;
}
}
await btn.update(replies.queue(player.queue, position - 1, player.resource));
});
}
const data = new SlashCommandBuilder()
.setName("queue")
.setDescription("Print interactive queue pointing to current track.")
.setDMPermission(false);
export { data, execute };
+42
View File
@@ -0,0 +1,42 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const query = interaction.options.getString("query", true);
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
const track =
!isNaN(+query) && isFinite(+query) && !/e/i.test(query)
? player.remove(parseInt(query) - 1)
: player.remove(query);
await interaction.reply(replies.removed(track));
}
const data = new SlashCommandBuilder()
.setName("remove")
.setDescription("Remove specific track in the queue.")
.addStringOption((option) =>
option.setName("query").setDescription("Position or title to remove.").setRequired(true)
)
.setDMPermission(false);
export { data, execute };
+34
View File
@@ -0,0 +1,34 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
player.shuffle();
await interaction.reply(replies.reshuffle());
}
const data = new SlashCommandBuilder()
.setName("reshuffle")
.setDescription("Reshuffle the queue. (Will change queue order)")
.setDMPermission(false);
export { data, execute };
+51
View File
@@ -0,0 +1,51 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const hours = interaction.options.getInteger("hrs") ?? 0;
const minutes = interaction.options.getInteger("mins") ?? 0;
const seconds = interaction.options.getInteger("secs") ?? 0;
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
if (!player.resource) {
await interaction.reply(replies.notPlaying());
return;
}
const prevTime = player.resource.playbackDuration / 1000;
const nextTime = hours * 3600 + minutes * 60 + seconds;
player.seek(nextTime * 1000);
await interaction.reply(replies.seeked(prevTime, nextTime));
}
const data = new SlashCommandBuilder()
.setName("seek")
.setDescription("Fast-forward/Fast-reverse by the given time.")
.addIntegerOption((option) => option.setName("hrs").setDescription("Hours to seek."))
.addIntegerOption((option) => option.setName("mins").setDescription("Minutes to seek."))
.addIntegerOption((option) => option.setName("secs").setDescription("Seconds to seek."))
.setDMPermission(false);
export { data, execute };
+34
View File
@@ -0,0 +1,34 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
player.destroy();
await interaction.reply(replies.destroyed());
}
const data = new SlashCommandBuilder()
.setName("stop")
.setDescription("Destroy the player.")
.setDMPermission(false);
export { data, execute };
+39
View File
@@ -0,0 +1,39 @@
import { ChatInputCommandInteraction, SlashCommandBuilder } from "discord.js";
import Client from "$lib/client.js";
import logger from "$lib/logger.js";
import replies from "../lib/replies.js";
import { controller } from "../module.js";
async function execute(client: Client, interaction: ChatInputCommandInteraction) {
if (!interaction.isChatInputCommand() || !interaction.inCachedGuild() || !interaction.channel) {
logger.warn("Interaction rejected.", { interaction });
return;
}
const volume = interaction.options.getInteger("volume") ?? 100;
const player = controller.get(interaction.guild, interaction.channel);
if (!player) {
await interaction.reply(replies.notExists());
return;
}
player.volume = volume;
await interaction.reply(replies.volumeSet(player.volume));
}
const data = new SlashCommandBuilder()
.setName("volume")
.setDescription("Change player's volume amount.")
.addIntegerOption((option) =>
option.setName("volume").setDescription("Volume in percents.").setRequired(true)
)
.setDMPermission(false);
export { data, execute };