Skip to content

Commit

Permalink
refactored bot.ts; extracted embed strings to json language file
Browse files Browse the repository at this point in the history
  • Loading branch information
BernardoPe committed Jan 16, 2025
1 parent 6b754b2 commit f9bb6b8
Show file tree
Hide file tree
Showing 33 changed files with 780 additions and 1,200 deletions.
987 changes: 51 additions & 936 deletions package-lock.json

Large diffs are not rendered by default.

91 changes: 60 additions & 31 deletions src/bot.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,78 @@
import { Player } from "discord-player"
import { DefaultExtractors } from "@discord-player/extractor"
import { YoutubeiExtractor } from "discord-player-youtubei"
import { Client, GatewayIntentBits } from "discord.js"
import { addEventListeners } from "./handlers/events.ts"
import { MusicBot } from "./types.ts"
import { Client, ClientEvents, GatewayIntentBits } from "discord.js"
import "dotenv/config"
import { BaseCommand } from "./types.ts"
import { getAllFiles } from "./utils/configs/json.ts"
import path from "path"
import { logger } from "./utils/logging/logger.ts"

const TOKEN = process.env.TOKEN
class MusicBot {
client: Client
player: Player
commands: { [key: string]: BaseCommand } = {}

const bot: MusicBot = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildVoiceStates,
],
}) as MusicBot
constructor(token?: string) {
this.client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildVoiceStates,
],
})
this.player = new Player(this.client, { skipFFmpeg: true })
this.registerCommands()
.then(() => this.registerExtractors())
.then(() => this.addEventListeners())
.then(() => this.client.login(token || process.env.TOKEN))
}

bot.player = new Player(bot as Client, {
skipFFmpeg: true,
})

addEventListeners(bot).then(async () => {
await bot.player.extractors.register(YoutubeiExtractor, {
overrideBridgeMode: "yt",
})
private async addEventListeners() {
const files = getAllFiles(path.join(__dirname, "listeners"))
for (const file of files) {
const module = await import(file)
const event = module.default
if (file.includes("player")) {
this.player.events.on(event.name, (...args: any) => event.execute(...args, this))
logger.info(`[LISTENER]: ${event.name} registered`)
} else {
this.client.on(event.name as keyof ClientEvents, (...args: any) => event.execute(...args, this))
logger.info(`[LISTENER]: ${event.name} registered`)
}
}
}

logger.info("Registered YoutubeiExtractor")
private async registerCommands() {
const commands: { [key: string]: BaseCommand } = {}
const commandFiles: string[] = getAllFiles(path.join(__dirname, "commands"))
for (const file of commandFiles) {
const module = await import(file)
const command: BaseCommand = module.default
command.aliases.forEach((alias) => (commands[alias] = command))
logger.info(`[COMMAND]: ${command.name} registered`)
}
this.commands = commands
}

await bot.player.extractors.loadMulti(DefaultExtractors)
private async registerExtractors() {
await this.player.extractors.register(YoutubeiExtractor, {
overrideBridgeMode: "yt",
})
logger.info("[EXTRACTORS]: Youtubei extractor registered")
await this.player.extractors.loadMulti(DefaultExtractors)
logger.info("[EXTRACTORS]: Default extractors registered")
}
}

logger.info("Registered DefaultExtractors")

await bot.login(TOKEN)
})

// generateOauthTokens() // Run this once to generate the necessary tokens

// Handle uncaught exceptions and unhandled promise rejections
process.on("uncaughtException", (error) => {
console.error("There was an uncaught error", error, error.stack)
})

process.on("unhandledRejection", (reason, promise) => {
console.error("Unhandled Rejection at:", promise)
})

export default new MusicBot()
13 changes: 8 additions & 5 deletions src/commands/player/control/cycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { sendEmbed } from "../../../utils/embeds/channels.ts"
import { PlayerCommand, QueueMetadata } from "../../../types.ts"
import { successEmbed } from "../../../utils/embeds/status.ts"
import { GuildTextBasedChannel } from "discord.js"
import langs from "../../../langs/index.ts"

class CycleCommand implements PlayerCommand {
public aliases = ["cycle"]
Expand All @@ -20,19 +21,19 @@ class CycleCommand implements PlayerCommand {
switch (args[1]) {
case "off":
serverQueue.setRepeatMode(QueueRepeatMode.OFF)
mode = "Turned off loop mode."
mode = langs.en.commands.cycle.loop_mode_off
break
case "track":
serverQueue.setRepeatMode(QueueRepeatMode.TRACK)
mode = "Repeating track activated"
mode = langs.en.commands.cycle.repeat_mode_on
break
case "queue":
serverQueue.setRepeatMode(QueueRepeatMode.QUEUE)
mode = "Looping queue enabled."
mode = langs.en.commands.cycle.looping_queue_on
break
case "autoplay":
serverQueue.setRepeatMode(QueueRepeatMode.AUTOPLAY)
mode = "Autoplay mode activated."
mode = langs.en.commands.cycle.autoplay_on
break
default:
if (serverQueue.repeatMode === QueueRepeatMode.AUTOPLAY) {
Expand All @@ -45,7 +46,9 @@ class CycleCommand implements PlayerCommand {
md = "off"
}
}
const embed = mode ? successEmbed(null, mode) : successEmbed(null, `Current mode: ${md}`)
const embed = mode
? successEmbed(null, mode)
: successEmbed(null, langs.en.commands.cycle.current_mode.replace("{mode}", md))
sendEmbed(channel, { embeds: [embed] }, 20000)
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/commands/player/control/pause.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { sendEmbed } from "../../../utils/embeds/channels.ts"
import { QueueMetadata, PlayerCommand } from "../../../types.ts"
import { GuildQueue } from "discord-player"
import { errorEmbed, successEmbed } from "../../../utils/embeds/status.ts"
import langs from "../../../langs/index.ts"

class PauseCommand implements PlayerCommand {
public aliases = ["pause"]
Expand All @@ -15,11 +16,11 @@ class PauseCommand implements PlayerCommand {
public execute(serverQueue: GuildQueue<QueueMetadata>) {
const channel = serverQueue.metadata.textChannel!
if (serverQueue.dispatcher!.paused) {
const embed = errorEmbed(null, "The player is already paused")
const embed = errorEmbed(null, langs.en.commands.pause.already_paused)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
const embed = successEmbed(null, "Paused the player")
const embed = successEmbed(null, langs.en.commands.pause.paused)
serverQueue.dispatcher!.pause()
sendEmbed(channel, { embeds: [embed] }, 20000)
return
Expand Down
7 changes: 4 additions & 3 deletions src/commands/player/control/resume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { PlayerCommand, QueueMetadata } from "../../../types.ts"
import { GuildQueue } from "discord-player"
import { sendEmbed } from "../../../utils/embeds/channels.ts"
import { errorEmbed, successEmbed } from "../../../utils/embeds/status.ts"
import langs from "../../../langs"

class ResumeCommand implements PlayerCommand {
aliases = ["resume"]
Expand All @@ -14,14 +15,14 @@ class ResumeCommand implements PlayerCommand {

execute(serverQueue: GuildQueue<QueueMetadata>) {
const channel = serverQueue.metadata.textChannel!
if (serverQueue.dispatcher && !serverQueue.dispatcher.isPaused()) {
const embed = errorEmbed(null, "The player is not paused")
if (serverQueue.dispatcher && serverQueue.dispatcher.isPlaying()) {
const embed = errorEmbed(null, langs.en.commands.resume.already_playing)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
if (serverQueue.dispatcher && serverQueue.dispatcher.isPaused()) {
serverQueue.dispatcher.resume()
const embed = successEmbed(null, "Resumed the player")
const embed = successEmbed(null, langs.en.commands.resume.resumed)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
Expand Down
13 changes: 4 additions & 9 deletions src/commands/player/control/seek.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { QueueMetadata, PlayerCommand } from "../../../types.ts"
import { GuildQueue } from "discord-player"
import { GuildTextBasedChannel } from "discord.js"
import { successEmbed } from "../../../utils/embeds/status.ts"
import langs from "../../../langs"

class SeekCommand implements PlayerCommand {
public aliases = ["seek"]
Expand All @@ -18,19 +19,13 @@ class SeekCommand implements PlayerCommand {
const time = validateTimestamp(args[1], serverQueue.node.totalDuration)

if (time === false) {
const embed = successEmbed(
null,
"**" + args[1] + "** is not a valid timestamp format, correct format should be **hh:mm:ss**."
)
const embed = successEmbed(null, langs.en.commands.seek.invalid_time_format.replace("{time}", args[1]))
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}

if (time === -1) {
const embed = successEmbed(
null,
"**" + args[1] + "** is not a valid timestamp in this track, check this song's total duration."
)
const embed = successEmbed(null, langs.en.commands.seek.invalid_time.replace("{time}", args[1]))
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
Expand All @@ -41,7 +36,7 @@ class SeekCommand implements PlayerCommand {

const timestamp = millisecondsToTimestamp(time as number)

const embed = successEmbed(null, "Track playback time set to **" + timestamp + "/" + dur + "**")
const embed = successEmbed(null, langs.en.commands.seek.seeked.replace("{time}", timestamp + "/" + dur))

sendEmbed(channel, { embeds: [embed] }, 20000)
}
Expand Down
9 changes: 5 additions & 4 deletions src/commands/player/filters/filter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { GuildQueue } from "discord-player"
import { sendEmbed } from "../../../utils/embeds/channels.ts"
import { GuildTextBasedChannel } from "discord.js"
import { errorEmbed, successEmbed } from "../../../utils/embeds/status.ts"
import langs from "../../../langs"

class FilterCommand implements PlayerCommand {
public adminCommand: boolean = false
Expand All @@ -22,26 +23,26 @@ class FilterCommand implements PlayerCommand {

if (filter === "disableall") {
await serverQueue.filters.ffmpeg.setFilters(false)
const embed = successEmbed(null, "Disabled all filters")
const embed = successEmbed(null, langs.en.commands.filter.disabled_all)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}

if (!serverQueue.filters.ffmpeg.isValidFilter(filter)) {
const embed = errorEmbed(null, "Invalid filter")
const embed = errorEmbed(null, langs.en.commands.filter.invalid_filter)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}

await serverQueue.filters.ffmpeg.toggle([filter])

if (serverQueue.filters.ffmpeg.isEnabled(filter)) {
const embed = successEmbed(null, `Enabled ${filter} filter`)
const embed = successEmbed(null, langs.en.commands.filter.enabled_single.replace("{filter}", filter))
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}

const embed = successEmbed(null, `Disabled ${filter} filter`)
const embed = successEmbed(null, langs.en.commands.filter.disabled_single.replace("{filter}", filter))
sendEmbed(channel, { embeds: [embed] }, 20000)
}
}
Expand Down
13 changes: 7 additions & 6 deletions src/commands/player/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { GuildQueue, SearchQueryType } from "discord-player"
import { GuildTextBasedChannel, VoiceBasedChannel } from "discord.js"
import { logger } from "../../utils/logging/logger.ts"
import { errorEmbed } from "../../utils/embeds/status.ts"
import langs from "../../langs"

class PlayCommand implements BotCommand {
adminCommand: boolean = false
Expand All @@ -25,23 +26,23 @@ class PlayCommand implements BotCommand {
const { channel } = msg

if (args.length === 1) {
const embed = errorEmbed(null, "Please provide a search query")
const embed = errorEmbed(null, langs.en.commands.play.provide_search)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}

const voiceChannel = msg.member!.voice.channel

if (!voiceChannel) {
const embed = errorEmbed(null, "You need to be in a voice channel to play music")
const embed = errorEmbed(null, langs.en.commands.play.need_to_be_in_voice)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}

const permissions = voiceChannel.permissionsFor(msg.client.user)!

if (!permissions.has("Connect") || !permissions.has("Speak")) {
const embed = errorEmbed(null, "I need the permissions to join and speak in your voice channel")
const embed = errorEmbed(null, langs.en.commands.play.need_permissions)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
Expand All @@ -50,7 +51,7 @@ class PlayCommand implements BotCommand {
bot.player.queues.get(msg.guild.id) || this.createQueue(bot, channel, voiceChannel)

if (queue.connection && queue.channel !== msg.member!.voice.channel) {
const embed = errorEmbed(null, "Already connected to a different voice channel")
const embed = errorEmbed(null, langs.en.commands.play.already_connected)
sendEmbed(msg.channel, { embeds: [embed] }, 20000)
return
}
Expand Down Expand Up @@ -82,7 +83,7 @@ class PlayCommand implements BotCommand {
const song = result.tracks[0]

if (result.tracks.length === 0) {
const embed = errorEmbed(null, "No results found")
const embed = errorEmbed(null, langs.en.commands.play.no_results)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
Expand All @@ -96,7 +97,7 @@ class PlayCommand implements BotCommand {
}
} catch (e) {
logger.error(e)
const embed = errorEmbed(null, "An error occurred while playing the song")
const embed = errorEmbed(null, langs.en.commands.play.error)
sendEmbed(channel, { embeds: [embed] }, 20000)
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/commands/player/queue/clear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { GuildQueue } from "discord-player"
import { GuildTextBasedChannel } from "discord.js"
import { errorEmbed, successEmbed } from "../../../utils/embeds/status.ts"
import { updatePlayer } from "../../../utils/embeds/player/playing.ts"
import langs from "../../../langs"

class ClearCommand implements PlayerCommand {
aliases = ["clear"]
Expand All @@ -16,13 +17,13 @@ class ClearCommand implements PlayerCommand {

execute(serverQueue: GuildQueue<QueueMetadata>, channel: GuildTextBasedChannel) {
if (serverQueue.tracks.size === 0) {
const embed = errorEmbed(null, "There are no songs in the queue")
const embed = errorEmbed(null, langs.en.commands.clear.empty_queue)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
serverQueue.tracks.clear()
updatePlayer(serverQueue)
const embed = successEmbed(null, "Cleared the queue")
const embed = successEmbed(null, langs.en.commands.clear.cleared)
sendEmbed(channel, { embeds: [embed] }, 20000)
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/commands/player/queue/jump.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { QueueMetadata, PlayerCommand } from "../../../types.ts"
import { GuildQueue } from "discord-player"
import { GuildTextBasedChannel } from "discord.js"
import { errorEmbed } from "../../../utils/embeds/status.ts"
import langs from "../../../langs"

class JumpCommand implements PlayerCommand {
public aliases = ["jump"]
Expand All @@ -17,7 +18,7 @@ class JumpCommand implements PlayerCommand {
const jumpPosition = parseInt(args[1])

if (isNaN(jumpPosition) || jumpPosition < 1 || jumpPosition > serverQueue.tracks.size) {
const embed = errorEmbed(null, "Invalid position")
const embed = errorEmbed(null, langs.en.commands.jump.invalid_index)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
Expand Down
3 changes: 2 additions & 1 deletion src/commands/player/queue/queue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { GuildQueue } from "discord-player"
import { GuildTextBasedChannel } from "discord.js"
import { createQueueEmbed } from "../../../utils/embeds/player/queue.ts"
import { errorEmbed } from "../../../utils/embeds/status.ts"
import langs from "../../../langs"

class QueueCommand implements QueueCommand {
public aliases = ["queue"]
Expand All @@ -17,7 +18,7 @@ class QueueCommand implements QueueCommand {

public execute(serverQueue: GuildQueue<QueueMetadata>, channel: GuildTextBasedChannel) {
if (serverQueue.isEmpty()) {
const embed = errorEmbed(null, "The queue is empty")
const embed = errorEmbed(null, langs.en.commands.shared.empty_queue)
sendEmbed(channel, { embeds: [embed] }, 20000)
return
}
Expand Down
Loading

0 comments on commit f9bb6b8

Please sign in to comment.