Formatted code

This commit is contained in:
2023-03-05 14:46:25 +07:00
parent 89744dcb10
commit b44e583834
47 changed files with 1240 additions and 1162 deletions
+1 -5
View File
@@ -36,11 +36,7 @@ class Configuration {
const dir = path.join(process.cwd(), 'configs/');
if (!fs.existsSync(path.join(dir, file))) {
fs.copyFileSync(
path.join(
process.cwd(),
'configs_example/',
`${file.replace('.json', '.example.json')}`
),
path.join(process.cwd(), 'configs_example/', `${file.replace('.json', '.example.json')}`),
path.join(dir, file)
);
}
+23 -4
View File
@@ -1,4 +1,17 @@
import { Guild, Client, GuildMember, IntentsBitField, Interaction, Message, TextChannel, BaseGuildTextChannel, TextBasedChannelMixin, ChannelType, BaseGuildVoiceChannel, InteractionType } from 'discord.js';
import {
Guild,
Client,
GuildMember,
IntentsBitField,
Interaction,
Message,
TextChannel,
BaseGuildTextChannel,
TextBasedChannelMixin,
ChannelType,
BaseGuildVoiceChannel,
InteractionType
} from 'discord.js';
import Logger from '../libs/Logger';
import Environment from './Environment';
@@ -131,7 +144,11 @@ class Discord {
if (interaction.guild) {
thisModule.GuildInteractionCreate(interaction);
if (interaction.type === InteractionType.ApplicationCommand && interaction.commandName && thisModule.commandInteractionName) {
if (
interaction.type === InteractionType.ApplicationCommand &&
interaction.commandName &&
thisModule.commandInteractionName
) {
thisModule.GuildCommandInteractionCreate(interaction);
if (interaction.commandName.toLowerCase() === thisModule.commandInteractionName)
thisModule.GuildModuleCommandInteractionCreate(interaction);
@@ -164,7 +181,8 @@ class Discord {
// Handling guild commands
this.client.on('messageCreate', async (message: Message) => {
if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel)) return;
if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel))
return;
if (message.author.bot) return;
if (typeof message.guild?.id === 'undefined') return;
@@ -265,7 +283,8 @@ class Discord {
// Handling mentions
this.client.on('messageCreate', async (message: Message) => {
// TODO: Handle DMs commands soon
if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel)) return;
if (!(message.channel instanceof BaseGuildTextChannel || message.channel instanceof BaseGuildVoiceChannel))
return;
if (message.author.bot) return;
if (typeof message.guild?.id === 'undefined') return;
+52 -55
View File
@@ -67,16 +67,21 @@ let tokenObject: TokenOptions = {};
if (Environment.get().YOUTUBE_COOKIE_BASE64) {
tokenObject.youtube = {
cookie: Buffer.from(Environment.get().YOUTUBE_COOKIE_BASE64, 'base64').toString()
}
};
}
if (Environment.get().SPOTIFY_CLIENT_ID && Environment.get().SPOTIFY_CLIENT_SECRET && Environment.get().SPOTIFY_REFRESH_TOKEN && Environment.get().SPOTIFY_CLIENT_MARKET) {
if (
Environment.get().SPOTIFY_CLIENT_ID &&
Environment.get().SPOTIFY_CLIENT_SECRET &&
Environment.get().SPOTIFY_REFRESH_TOKEN &&
Environment.get().SPOTIFY_CLIENT_MARKET
) {
tokenObject.spotify = {
client_id: Environment.get().SPOTIFY_CLIENT_ID,
client_secret: Environment.get().SPOTIFY_CLIENT_SECRET,
refresh_token: Environment.get().SPOTIFY_REFRESH_TOKEN,
market: Environment.get().SPOTIFY_CLIENT_MARKET
}
};
}
playdl.setToken(tokenObject);
@@ -86,11 +91,10 @@ export class TrackUtils {
if (track instanceof YouTubeVideo) {
return track.title;
} else if (track instanceof SpotifyTrack) {
let artistNames = "";
for(let artist of track.artists)
artistNames += artist.name + " ";
let artistNames = '';
for (let artist of track.artists) artistNames += artist.name + ' ';
return `${artistNames} - ${track.name}`;;
return `${artistNames} - ${track.name}`;
} else {
throw new Error('Invalid track type');
}
@@ -99,22 +103,20 @@ export class TrackUtils {
if (track instanceof YouTubeVideo) {
return track.thumbnails;
} else if (track instanceof SpotifyTrack) {
if (track.thumbnail)
return [track.thumbnail];
if (track.thumbnail) return [track.thumbnail];
else {
// Try to find the thumbnail again
const result = await DiscordMusicPlayer_Instance.searchSpotifyBySpotifyLink(track);
if(!result) return null;
if(result.thumbnail)
return [result.thumbnail];
if (!result) return null;
if (result.thumbnail) return [result.thumbnail];
return null;
}
} else {
throw new Error('Invalid track type');
}
}
public static getHighestResolutionThumbnail(thumbnails: (YouTubeThumbnail[] | SpotifyThumbnail[] | null)) {
if(!thumbnails) return null;
public static getHighestResolutionThumbnail(thumbnails: YouTubeThumbnail[] | SpotifyThumbnail[] | null) {
if (!thumbnails) return null;
return (thumbnails as any[]).reduce((prev: any, current: any) =>
prev.height * prev.width > current.height * current.width ? prev : current
@@ -141,7 +143,7 @@ export class SpotifyLink {
public type: 'track' | 'playlist' | 'album';
public url: string;
constructor(id: string, type: ('track' | 'playlist' | 'album'), url: string) {
constructor(id: string, type: 'track' | 'playlist' | 'album', url: string) {
this.id = id;
this.type = type;
this.url = url;
@@ -237,7 +239,10 @@ export class DiscordMusicPlayerInstance {
});
}
public joinVoiceChannel(voiceChannel: VoiceChannel | StageChannel, textChannel?: BaseGuildTextChannel | BaseGuildVoiceChannel) {
public joinVoiceChannel(
voiceChannel: VoiceChannel | StageChannel,
textChannel?: BaseGuildTextChannel | BaseGuildVoiceChannel
) {
const permissions = voiceChannel.permissionsFor(DiscordProvider.client.user!);
if (!permissions || !voiceChannel.joinable || !permissions.has(PermissionsBitField.Flags.Connect))
@@ -269,7 +274,7 @@ export class DiscordMusicPlayerInstance {
(oldState: VoiceConnectionState, newState: VoiceConnectionState) => {
setTimeout(async () => {
let guild = DiscordProvider.client.guilds.cache.get(voiceChannel.guildId);
if(guild) {
if (guild) {
if (!guild?.members.me?.voice.channelId) {
this.events.emit('disconnect', new VoiceDisconnectedEvent(this));
}
@@ -314,9 +319,8 @@ export class DiscordMusicPlayerInstance {
if (!this.voiceConnection) throw new Error('No voice connection');
try {
let resource;
if(track instanceof YouTubeVideo) {
if (track instanceof YouTubeVideo) {
const stream = await playdl.stream(track.url);
resource = createAudioResource(stream.stream, {
inputType: stream.type
@@ -324,8 +328,7 @@ export class DiscordMusicPlayerInstance {
this.actualPlaybackURL = track.url;
} else {
const search = await DiscordMusicPlayer_Instance.searchYouTubeBySpotifyLink(track);
if(!search)
throw new Error('Unable to find Spotify track on YouTube');
if (!search) throw new Error('Unable to find Spotify track on YouTube');
const stream = await playdl.stream(search.url);
resource = createAudioResource(stream.stream, {
@@ -333,7 +336,7 @@ export class DiscordMusicPlayerInstance {
});
this.actualPlaybackURL = search.url;
}
this.player.play(resource);
this.voiceConnection.subscribe(this.player);
} catch (error: any) {
@@ -359,7 +362,7 @@ export class DiscordMusicPlayerInstance {
public clearQueue() {
if (!this.voiceConnection) throw new Error('No voice connection');
if(!this.queue.track || this.queue.track.length === 0) return;
if (!this.queue.track || this.queue.track.length === 0) return;
this.queue.track = [this.queue.track[0]];
}
@@ -367,17 +370,17 @@ export class DiscordMusicPlayerInstance {
if (!this.voiceConnection) throw new Error('No voice connection');
const shuffleFixedFirst = (queue: ValidTracks[]) => {
if(queue.length <= 2) return queue;
if (queue.length <= 2) return queue;
const fixedFirst = queue.shift();
if(!fixedFirst) return queue;
if (!fixedFirst) return queue;
queue.sort(() => Math.random() - 0.5);
queue.unshift(fixedFirst);
return queue;
}
};
if(!this.queue.track || this.queue.track.length === 0) return;
if (!this.queue.track || this.queue.track.length === 0) return;
this.queue.track = shuffleFixedFirst(this.queue.track);
}
@@ -410,7 +413,7 @@ export class DiscordMusicPlayerInstance {
return true;
}
public isPaused() {
return this.paused;
}
@@ -475,32 +478,31 @@ class DiscordMusicPlayer {
}
public async searchYouTubeBySpotifyLink(spotifyLink: SpotifyLink) {
const track = await this.searchSpotifyBySpotifyLink(spotifyLink);
if(!track) return;
if (!track) return;
let artistNames = "";
for(let artist of track.artists)
artistNames += artist.name + " ";
let artistNames = '';
for (let artist of track.artists) artistNames += artist.name + ' ';
const ytSearchResult = await this.searchYouTubeByQuery(`${artistNames} ${track.name}`);
if(!ytSearchResult) return null;
if (!ytSearchResult) return null;
return ytSearchResult[0];
}
public async searchSpotifyBySpotifyLink(spotifyLink: SpotifyLink) {
if(playdl.is_expired())
await playdl.refreshToken();
if(spotifyLink.type != 'track') return;
if (playdl.is_expired()) await playdl.refreshToken();
if (spotifyLink.type != 'track') return;
// Fetch data from spotify
const searched: Spotify = await playdl.spotify("https://open.spotify.com/track/" + spotifyLink.id).catch((err) => {
Logger.error(err.message);
throw new Error('Error while searching on Spotify');
});
if(!(searched instanceof SpotifyTrack)) return;
const searched: Spotify = await playdl
.spotify('https://open.spotify.com/track/' + spotifyLink.id)
.catch((err) => {
Logger.error(err.message);
throw new Error('Error while searching on Spotify');
});
if (!(searched instanceof SpotifyTrack)) return;
if (!searched) return null;
const track = searched as unknown as SpotifyTrack;
@@ -570,16 +572,14 @@ class DiscordMusicPlayer {
}
public async getSpotifySongsInPlayList(spotifyLink: string) {
if(playdl.is_expired())
await playdl.refreshToken();
if (playdl.is_expired()) await playdl.refreshToken();
const result = await playdl.spotify(spotifyLink).catch((err) => {
Logger.error(err.message);
throw new Error('Error while searching on Spotify');
});
if(!(result.type == 'playlist' || result.type == 'album'))
throw new Error("Not a spotify playlist");
if (!(result.type == 'playlist' || result.type == 'album')) throw new Error('Not a spotify playlist');
return result as unknown as SpotifyPlaylist;
}
@@ -647,24 +647,21 @@ class DiscordMusicPlayer {
type: 'track',
url: query.split(/[?#]/)[0]
};
}
else if (query.startsWith('https://open.spotify.com/album/')) {
} else if (query.startsWith('https://open.spotify.com/album/')) {
let id = query.split('/')[4].split(/[?#]/)[0];
return {
id: id,
type: 'album',
url: query.split(/[?#]/)[0]
};
}
else if (query.startsWith('https://open.spotify.com/playlist/')) {
} else if (query.startsWith('https://open.spotify.com/playlist/')) {
let id = query.split('/')[4].split(/[?#]/)[0];
return {
id: id,
type: 'playlist',
url: query.split(/[?#]/)[0]
};
}
else {
} else {
throw new Error('Spotify link is invalid');
}
}
+10 -6
View File
@@ -33,13 +33,17 @@ class Environment {
// PRIVATE_BOT Checks
if (this.get().PRIVATE_BOT.toLowerCase() != 'true' && this.get().PRIVATE_BOT.toLowerCase() != 'false')
throw new Error('.env PRIVATE_BOT must be either "true" or "false"');
// SUPPORT_URL Checks
if (this.get().SUPPORT_URL && !validator.isURL(this.get().SUPPORT_URL))
throw new Error('.env SUPPORT_URL is not a valid URL');
// WEB_HOST Checks
if (this.get().WEB_HOST && this.get().WEB_HOST.toLowerCase() != 'localhost' && !validator.isIP(this.get().WEB_HOST))
if (
this.get().WEB_HOST &&
this.get().WEB_HOST.toLowerCase() != 'localhost' &&
!validator.isIP(this.get().WEB_HOST)
)
throw new Error('.env WEB_HOST must be either localhost or a valid IP address');
// WEB_PORT Checks
@@ -68,10 +72,10 @@ class Environment {
const YOUTUBE_COOKIE_BASE64 = process.env.YOUTUBE_COOKIE_BASE64;
const SPOTIFY_CLIENT_ID = process.env.SPOTIFY_CLIENT_ID;
const SPOTIFY_CLIENT_SECRET= process.env.SPOTIFY_CLIENT_SECRET;
const SPOTIFY_REFRESH_TOKEN= process.env.SPOTIFY_REFRESH_TOKEN;
const SPOTIFY_CLIENT_MARKET= process.env.SPOTIFY_CLIENT_MARKET;
const SPOTIFY_CLIENT_SECRET = process.env.SPOTIFY_CLIENT_SECRET;
const SPOTIFY_REFRESH_TOKEN = process.env.SPOTIFY_REFRESH_TOKEN;
const SPOTIFY_CLIENT_MARKET = process.env.SPOTIFY_CLIENT_MARKET;
return {
NODE_ENV,
+15 -18
View File
@@ -1,53 +1,50 @@
import express from 'express';
import cors from 'cors';
import Logger from "../libs/Logger";
import Environment from "./Environment";
import Logger from '../libs/Logger';
import Environment from './Environment';
import ExpressException from '../exception/ExpressException';
import Routes from './Routes';
class Express {
public server: any;
public express: express.Application;
constructor () {
constructor() {
this.server = null;
this.express = express();
}
public init(): void {
this.mountMiddlewares();
this.mountRoutes();
this.mountRoutes();
this.express = this.express.use(ExpressException.errorLogger);
this.server = this.express.listen(Environment.get().WEB_PORT, Environment.get().WEB_HOST, () => {
Logger.log('info', `Express Webserver listening at ${Environment.get().WEB_HOST}:${Environment.get().WEB_PORT}`);
Logger.log(
'info',
`Express Webserver listening at ${Environment.get().WEB_HOST}:${Environment.get().WEB_PORT}`
);
});
}
public end(): void {
if(this.server)
this.server.close();
if (this.server) this.server.close();
}
private mountRoutes (): void {
private mountRoutes(): void {
this.express = Routes.mountAPI(this.express);
this.express = Routes.mountWeb(this.express);
}
private mountMiddlewares (): void {
this.express = Routes.mountWeb(this.express);
}
private mountMiddlewares(): void {
//this.express = RateLimit.init(this.express);
this.express = this.express.use(cors());
//This always have to be at the bottom!
this.express = this.express.use(express.json());
}
}
}
export default new Express();
export default new Express();
+1 -3
View File
@@ -3,7 +3,6 @@ import Logger from '../libs/Logger';
import apiv1Router from '../routes/API/v1';
class Routes {
public mountWeb(_express: express.Application): Application {
Logger.log('info', 'Mounting Web routes');
return _express;
@@ -16,7 +15,6 @@ class Routes {
return _express;
}
}
export default new Routes;
export default new Routes();