mirror of
				https://github.com/warengroup/eximiabots-radiox.git
				synced 2025-11-04 03:49:33 +00:00 
			
		
		
		
	Updated src
This commit is contained in:
		@@ -1,62 +0,0 @@
 | 
			
		||||
const { Client, Collection } = require('discord.js');
 | 
			
		||||
const Discord = require('discord.js');
 | 
			
		||||
const fs = require('fs');
 | 
			
		||||
const path = require('path');
 | 
			
		||||
const events = './events/';
 | 
			
		||||
const Datastore = require('./datastore.js');
 | 
			
		||||
 | 
			
		||||
const GatewayIntents = new Discord.Intents();
 | 
			
		||||
GatewayIntents.add(
 | 
			
		||||
    1 << 0, // GUILDS
 | 
			
		||||
    1 << 7, // GUILD_VOICE_STATES
 | 
			
		||||
    1 << 9 // GUILD_MESSAGES
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
module.exports = class extends Client {
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super({
 | 
			
		||||
            disableEveryone: true,
 | 
			
		||||
            disabledEvents: ['TYPING_START'],
 | 
			
		||||
            ws: {
 | 
			
		||||
                intents: GatewayIntents
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        this.commands = new Collection();
 | 
			
		||||
        this.commandAliases = new Collection();
 | 
			
		||||
        this.radio = new Map();
 | 
			
		||||
 | 
			
		||||
        this.funcs = {};
 | 
			
		||||
        this.funcs.check = require('./funcs/check.js');
 | 
			
		||||
        this.funcs.checkFetchStatus = require('./funcs/checkFetchStatus.js');
 | 
			
		||||
        this.funcs.isDev = require('./funcs/isDev.js');
 | 
			
		||||
        this.funcs.msToTime = require('./funcs/msToTime.js');
 | 
			
		||||
        this.funcs.statisticsUpdate = require('./funcs/statisticsUpdate.js');
 | 
			
		||||
 | 
			
		||||
        this.config = require('../config.js');
 | 
			
		||||
        this.messages = require('./messages.js');
 | 
			
		||||
 | 
			
		||||
        const commandFiles = fs.readdirSync('./client/commands/').filter(f => f.endsWith('.js'));
 | 
			
		||||
        for (const file of commandFiles) {
 | 
			
		||||
            const command = require(`./commands/${file}`);
 | 
			
		||||
            command.uses = 0;
 | 
			
		||||
            this.commands.set(command.name, command);
 | 
			
		||||
            this.commandAliases.set(command.alias, command);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.on('ready', () => {
 | 
			
		||||
            require(`${events}ready`).execute(this, Discord);
 | 
			
		||||
            this.datastore = new Datastore();
 | 
			
		||||
        });
 | 
			
		||||
        this.on('message', (msg) => {
 | 
			
		||||
            require(`${events}msg`).execute(this, msg, Discord);
 | 
			
		||||
        });
 | 
			
		||||
        this.on('voiceStateUpdate', (oldState, newState) => {
 | 
			
		||||
            require(`${events}voiceStateUpdate`).execute(this, oldState, newState);
 | 
			
		||||
        });
 | 
			
		||||
        this.on('error', (error) => {
 | 
			
		||||
            console.error(error);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.login(this.config.token).catch(err => console.log('Failed to login: ' + err));
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
@@ -1,158 +0,0 @@
 | 
			
		||||
module.exports = {
 | 
			
		||||
	name: 'play',
 | 
			
		||||
	alias: 'p',
 | 
			
		||||
	usage: '<song name>',
 | 
			
		||||
	description: 'Play some music.',
 | 
			
		||||
	permission: 'none',
 | 
			
		||||
	category: 'radio',
 | 
			
		||||
	async execute(msg, args, client, Discord, command) {
 | 
			
		||||
		let message = {};
 | 
			
		||||
		let url = args[1] ? args[1].replace(/<(.+)>/g, "$1") : "";
 | 
			
		||||
		const radio = client.radio.get(msg.guild.id);
 | 
			
		||||
		const voiceChannel = msg.member.voice.channel;
 | 
			
		||||
		if (!radio) {
 | 
			
		||||
			if (!msg.member.voice.channel) return msg.channel.send(client.messageEmojis["error"] + client.messages.noVoiceChannel);
 | 
			
		||||
		} else {
 | 
			
		||||
			if (voiceChannel !== radio.voiceChannel) return msg.channel.send(client.messageEmojis["error"] + client.messages.wrongVoiceChannel);
 | 
			
		||||
		}
 | 
			
		||||
		if(!client.stations) {
 | 
			
		||||
			message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild);
 | 
			
		||||
			return msg.channel.send(client.messageEmojis["error"] + message.errorToGetPlaylist);
 | 
			
		||||
		}
 | 
			
		||||
		if (!args[1]) return msg.channel.send(client.messages.noQuery);
 | 
			
		||||
		const permissions = voiceChannel.permissionsFor(msg.client.user);
 | 
			
		||||
		if (!permissions.has('CONNECT')) {
 | 
			
		||||
			return msg.channel.send(client.messageEmojis["error"] + client.messages.noPermsConnect);
 | 
			
		||||
		}
 | 
			
		||||
		if (!permissions.has('SPEAK')) {
 | 
			
		||||
			return msg.channel.send(client.messageEmojis["error"] + client.messages.noPermsSpeak);
 | 
			
		||||
		}
 | 
			
		||||
		let station;
 | 
			
		||||
		const number = parseInt(args[1] - 1);
 | 
			
		||||
		if (url.startsWith('http')) {
 | 
			
		||||
			return msg.channel.send(client.messageEmojis["error"] + client.messages.errorStationURL);
 | 
			
		||||
		} else if (!isNaN(number)) {
 | 
			
		||||
			if (number > client.stations.length - 1) {
 | 
			
		||||
				return msg.channel.send(client.messageEmojis["error"] + client.messages.wrongStationNumber);
 | 
			
		||||
			} else {
 | 
			
		||||
				url = client.stations[number].stream[client.stations[number].stream.default];
 | 
			
		||||
				station = client.stations[number];
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			if (args[1].length < 3) return msg.channel.send(client.messageEmojis["error"] + client.messages.tooShortSearch);
 | 
			
		||||
			const sstation = await searchStation(args.slice(1).join(' '), client);
 | 
			
		||||
			if (!sstation) return msg.channel.send(client.messageEmojis["error"] + client.messages.noSearchResults);
 | 
			
		||||
			url = sstation.stream[sstation.stream.default];
 | 
			
		||||
			station = sstation;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (radio) {
 | 
			
		||||
            
 | 
			
		||||
            client.funcs.statisticsUpdate(client, msg.guild, radio);
 | 
			
		||||
            
 | 
			
		||||
			radio.connection.dispatcher.destroy();
 | 
			
		||||
			radio.station = station;
 | 
			
		||||
			radio.textChannel = msg.channel;
 | 
			
		||||
			play(msg.guild, client, url);
 | 
			
		||||
            
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		const construct = {
 | 
			
		||||
			textChannel: msg.channel,
 | 
			
		||||
			voiceChannel: voiceChannel,
 | 
			
		||||
			connection: null,
 | 
			
		||||
			station: station,
 | 
			
		||||
			volume: 5,
 | 
			
		||||
		};
 | 
			
		||||
		client.radio.set(msg.guild.id, construct);
 | 
			
		||||
 | 
			
		||||
		try {
 | 
			
		||||
			const connection = await voiceChannel.join();
 | 
			
		||||
			construct.connection = connection;
 | 
			
		||||
            let date = new Date();
 | 
			
		||||
            construct.startTime = date.getTime();
 | 
			
		||||
			play(msg.guild, client, url);
 | 
			
		||||
            
 | 
			
		||||
            client.datastore.checkEntry(msg.guild.id);
 | 
			
		||||
            construct.currentGuild = client.datastore.getEntry(msg.guild.id);
 | 
			
		||||
            
 | 
			
		||||
            if(!construct.currentGuild.statistics[construct.station.name]){
 | 
			
		||||
                construct.currentGuild.statistics[construct.station.name] = {};
 | 
			
		||||
                construct.currentGuild.statistics[construct.station.name].time = 0;
 | 
			
		||||
                construct.currentGuild.statistics[construct.station.name].used = 0;
 | 
			
		||||
                client.datastore.updateEntry(msg.guild, construct.currentGuild);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
		} catch (error) {
 | 
			
		||||
			console.log(error);
 | 
			
		||||
			client.radio.delete(msg.guild.id);
 | 
			
		||||
			return msg.channel.send(client.messageEmojis["error"] + `An error occured: ${error}`);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
function play(guild, client, url) {
 | 
			
		||||
	let message = {};
 | 
			
		||||
	const radio = client.radio.get(guild.id);
 | 
			
		||||
 | 
			
		||||
	const dispatcher = radio.connection
 | 
			
		||||
		.play(url, { bitrate: "auto", volume: 1 })
 | 
			
		||||
		.on("finish", () => {
 | 
			
		||||
			console.log("Stream finished");
 | 
			
		||||
			client.funcs.statisticsUpdate(client, guild, radio);
 | 
			
		||||
			radio.voiceChannel.leave();
 | 
			
		||||
			client.radio.delete(guild.id);
 | 
			
		||||
			return;
 | 
			
		||||
		});
 | 
			
		||||
 | 
			
		||||
	dispatcher.on('error', error => {
 | 
			
		||||
		console.error(error);
 | 
			
		||||
		radio.voiceChannel.leave();
 | 
			
		||||
		client.radio.delete(guild.id);
 | 
			
		||||
		return radio.textChannel.send(client.messages.errorPlaying);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
	dispatcher.setVolume(radio.volume / 10);
 | 
			
		||||
 | 
			
		||||
	message.play = client.messages.play.replace("%radio.station.name%", radio.station.name);
 | 
			
		||||
	radio.textChannel.send(client.messageEmojis["play"] + message.play);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function searchStation(key, client) {
 | 
			
		||||
	if (client.stations === null) return false;
 | 
			
		||||
	let foundStations = [];
 | 
			
		||||
	if (!key) return false;
 | 
			
		||||
	if (key == 'radio') return false;
 | 
			
		||||
	if (key.startsWith("radio ")) key = key.slice(6);
 | 
			
		||||
	const probabilityIncrement = 100 / key.split(' ').length / 2;
 | 
			
		||||
	for (let i = 0; i < key.split(' ').length; i++) {
 | 
			
		||||
		client.stations.filter(x => x.name.toUpperCase().includes(key.split(' ')[i].toUpperCase()) || x === key).forEach(x => foundStations.push({ station: x, name: x.name, probability: probabilityIncrement }));
 | 
			
		||||
	}
 | 
			
		||||
	if (foundStations.length === 0) return false;
 | 
			
		||||
	for (let i = 0; i < foundStations.length; i++) {
 | 
			
		||||
		for (let j = 0; j < foundStations.length; j++) {
 | 
			
		||||
			if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	for (let i = 0; i < foundStations.length; i++) {
 | 
			
		||||
		if (foundStations[i].name.length > key.length) {
 | 
			
		||||
			foundStations[i].probability -= (foundStations[i].name.split(' ').length - key.split(' ').length) * (probabilityIncrement * 0.5);
 | 
			
		||||
		} else if (foundStations[i].name.length === key.length) {
 | 
			
		||||
			foundStations[i].probability += (probabilityIncrement * 0.9);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (let j = 0; j < key.split(' ').length; j++) {
 | 
			
		||||
			if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(' ')[j])) {
 | 
			
		||||
				foundStations[i].probability -= (probabilityIncrement * 0.5);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	let highestProbabilityStation;
 | 
			
		||||
	for (let i = 0; i < foundStations.length; i++) {
 | 
			
		||||
		if (!highestProbabilityStation || highestProbabilityStation.probability < foundStations[i].probability) highestProbabilityStation = foundStations[i];
 | 
			
		||||
		if (highestProbabilityStation && highestProbabilityStation.probability === foundStations[i].probability) {
 | 
			
		||||
			highestProbabilityStation = foundStations[i].station;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return highestProbabilityStation;
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										2
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								index.js
									
									
									
									
									
								
							@@ -1,2 +0,0 @@
 | 
			
		||||
const radioClient = require("./client/class.js");
 | 
			
		||||
const client = new radioClient();
 | 
			
		||||
							
								
								
									
										67
									
								
								src/Client.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								src/Client.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,67 @@
 | 
			
		||||
import Discord, { Client, Collection } from "discord.js";
 | 
			
		||||
import fs from "fs";
 | 
			
		||||
const events = "./client/events/";
 | 
			
		||||
import Datastore from "./client/datastore.js";
 | 
			
		||||
import { command, radio } from "./client/utils/typings.js";
 | 
			
		||||
import config from "./config.js";
 | 
			
		||||
import messages from "./client/messages.js";
 | 
			
		||||
import path from "path"
 | 
			
		||||
 | 
			
		||||
const GatewayIntents = new Discord.Intents();
 | 
			
		||||
GatewayIntents.add(
 | 
			
		||||
    1 << 0, // GUILDS
 | 
			
		||||
    1 << 7, // GUILD_VOICE_STATES
 | 
			
		||||
    1 << 9 // GUILD_MESSAGES
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
class RadioClient extends Client {
 | 
			
		||||
    readonly commands: Collection<string, command>;
 | 
			
		||||
    readonly commandAliases: Collection<string, command>;
 | 
			
		||||
    readonly radio: Map<string, radio>;
 | 
			
		||||
    public funcs: any;
 | 
			
		||||
    readonly config = config;
 | 
			
		||||
    readonly messages = messages;
 | 
			
		||||
    public datastore: Datastore | null;
 | 
			
		||||
    constructor() {
 | 
			
		||||
        super({
 | 
			
		||||
            intents: GatewayIntents
 | 
			
		||||
        });
 | 
			
		||||
        this.commands = new Collection();
 | 
			
		||||
        this.commandAliases = new Collection();
 | 
			
		||||
        this.radio = new Map();
 | 
			
		||||
        this.datastore = null;
 | 
			
		||||
 | 
			
		||||
        this.funcs = {};
 | 
			
		||||
        this.funcs.check = require("./client/funcs/check.js");
 | 
			
		||||
        this.funcs.checkFetchStatus = require("./client/funcs/checkFetchStatus.js");
 | 
			
		||||
        this.funcs.isDev = require("./client/funcs/isDev.js");
 | 
			
		||||
        this.funcs.msToTime = require("./client/funcs/msToTime.js");
 | 
			
		||||
        this.funcs.statisticsUpdate = require("./client/funcs/statisticsUpdate.js");
 | 
			
		||||
 | 
			
		||||
        const commandFiles = fs.readdirSync("D:/GitHub/eximiabots-radiox/src/client/commands/"/*path.join("./client/commands")*/).filter(f => f.endsWith(".js"));
 | 
			
		||||
        for (const file of commandFiles) {
 | 
			
		||||
            const command = require(`./client/commands/${file}`);
 | 
			
		||||
            command.uses = 0;
 | 
			
		||||
            this.commands.set(command.name, command);
 | 
			
		||||
            this.commandAliases.set(command.alias, command);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.on("ready", () => {
 | 
			
		||||
            require(`${events}ready`).execute(this, Discord);
 | 
			
		||||
            this.datastore = new Datastore();
 | 
			
		||||
        });
 | 
			
		||||
        this.on("message", msg => {
 | 
			
		||||
            require(`${events}msg`).execute(this, msg, Discord);
 | 
			
		||||
        });
 | 
			
		||||
        this.on("voiceStateUpdate", (oldState, newState) => {
 | 
			
		||||
            require(`${events}voiceStateUpdate`).execute(this, oldState, newState);
 | 
			
		||||
        });
 | 
			
		||||
        this.on("error", error => {
 | 
			
		||||
            console.error(error);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.login(this.config.token).catch(err => console.log("Failed to login: " + err));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default RadioClient
 | 
			
		||||
							
								
								
									
										206
									
								
								src/client/commands/play.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								src/client/commands/play.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,206 @@
 | 
			
		||||
const {
 | 
			
		||||
    createAudioPlayer,
 | 
			
		||||
    createAudioResource,
 | 
			
		||||
    getVoiceConnection,
 | 
			
		||||
    joinVoiceChannel
 | 
			
		||||
} = require("@discordjs/voice");
 | 
			
		||||
const { createDiscordJSAdapter } = require("../utils/adapter");
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
    name: "play",
 | 
			
		||||
    alias: "p",
 | 
			
		||||
    usage: "<song name>",
 | 
			
		||||
    description: "Play some music.",
 | 
			
		||||
    permission: "none",
 | 
			
		||||
    category: "radio",
 | 
			
		||||
    async execute(msg, args, client, Discord, command) {
 | 
			
		||||
        let message = {};
 | 
			
		||||
        let url = args[1] ? args[1].replace(/<(.+)>/g, "$1") : "";
 | 
			
		||||
        const radio = client.radio.get(msg.guild.id);
 | 
			
		||||
        const voiceChannel = msg.member.voice.channel;
 | 
			
		||||
        if (!radio) {
 | 
			
		||||
            if (!msg.member.voice.channel)
 | 
			
		||||
                return msg.channel.send(
 | 
			
		||||
                    client.messageEmojis["error"] + client.messages.noVoiceChannel
 | 
			
		||||
                );
 | 
			
		||||
        } else {
 | 
			
		||||
            if (voiceChannel !== radio.voiceChannel)
 | 
			
		||||
                return msg.channel.send(
 | 
			
		||||
                    client.messageEmojis["error"] + client.messages.wrongVoiceChannel
 | 
			
		||||
                );
 | 
			
		||||
        }
 | 
			
		||||
        if (!client.stations) {
 | 
			
		||||
            message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace(
 | 
			
		||||
                "%client.config.supportGuild%",
 | 
			
		||||
                client.config.supportGuild
 | 
			
		||||
            );
 | 
			
		||||
            return msg.channel.send(client.messageEmojis["error"] + message.errorToGetPlaylist);
 | 
			
		||||
        }
 | 
			
		||||
        if (!args[1]) return msg.channel.send(client.messages.noQuery);
 | 
			
		||||
        const permissions = voiceChannel.permissionsFor(msg.client.user);
 | 
			
		||||
        if (!permissions.has("CONNECT")) {
 | 
			
		||||
            return msg.channel.send(client.messageEmojis["error"] + client.messages.noPermsConnect);
 | 
			
		||||
        }
 | 
			
		||||
        if (!permissions.has("SPEAK")) {
 | 
			
		||||
            return msg.channel.send(client.messageEmojis["error"] + client.messages.noPermsSpeak);
 | 
			
		||||
        }
 | 
			
		||||
        let station;
 | 
			
		||||
        const number = parseInt(args[1] - 1);
 | 
			
		||||
        if (url.startsWith("http")) {
 | 
			
		||||
            return msg.channel.send(
 | 
			
		||||
                client.messageEmojis["error"] + client.messages.errorStationURL
 | 
			
		||||
            );
 | 
			
		||||
        } else if (!isNaN(number)) {
 | 
			
		||||
            if (number > client.stations.length - 1) {
 | 
			
		||||
                return msg.channel.send(
 | 
			
		||||
                    client.messageEmojis["error"] + client.messages.wrongStationNumber
 | 
			
		||||
                );
 | 
			
		||||
            } else {
 | 
			
		||||
                url = client.stations[number].stream[client.stations[number].stream.default];
 | 
			
		||||
                station = client.stations[number];
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            if (args[1].length < 3)
 | 
			
		||||
                return msg.channel.send(
 | 
			
		||||
                    client.messageEmojis["error"] + client.messages.tooShortSearch
 | 
			
		||||
                );
 | 
			
		||||
            const sstation = await searchStation(args.slice(1).join(" "), client);
 | 
			
		||||
            if (!sstation)
 | 
			
		||||
                return msg.channel.send(
 | 
			
		||||
                    client.messageEmojis["error"] + client.messages.noSearchResults
 | 
			
		||||
                );
 | 
			
		||||
            url = sstation.stream[sstation.stream.default];
 | 
			
		||||
            station = sstation;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (radio) {
 | 
			
		||||
            client.funcs.statisticsUpdate(client, msg.guild, radio);
 | 
			
		||||
 | 
			
		||||
            radio.connection.dispatcher.destroy();
 | 
			
		||||
            radio.station = station;
 | 
			
		||||
            radio.textChannel = msg.channel;
 | 
			
		||||
            play(msg.guild, client, url);
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const construct = {
 | 
			
		||||
            textChannel: msg.channel,
 | 
			
		||||
            voiceChannel: voiceChannel,
 | 
			
		||||
            connection: null,
 | 
			
		||||
            audioPlayer: createAudioPlayer(),
 | 
			
		||||
            station: station,
 | 
			
		||||
            volume: 5
 | 
			
		||||
        };
 | 
			
		||||
        client.radio.set(msg.guild.id, construct);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            const connection =
 | 
			
		||||
                getVoiceConnection(voiceChannel.guild.id) ??
 | 
			
		||||
                joinVoiceChannel({
 | 
			
		||||
                    channelId: voiceChannel.id,
 | 
			
		||||
                    guildId: voiceChannel.guild.id,
 | 
			
		||||
                    adapterCreator: createDiscordJSAdapter(voiceChannel)
 | 
			
		||||
                });
 | 
			
		||||
            construct.connection = connection;
 | 
			
		||||
            let date = new Date();
 | 
			
		||||
            construct.startTime = date.getTime();
 | 
			
		||||
            play(msg.guild, client, url);
 | 
			
		||||
 | 
			
		||||
            client.datastore.checkEntry(msg.guild.id);
 | 
			
		||||
            construct.currentGuild = client.datastore.getEntry(msg.guild.id);
 | 
			
		||||
 | 
			
		||||
            if (!construct.currentGuild.statistics[construct.station.name]) {
 | 
			
		||||
                construct.currentGuild.statistics[construct.station.name] = {};
 | 
			
		||||
                construct.currentGuild.statistics[construct.station.name].time = 0;
 | 
			
		||||
                construct.currentGuild.statistics[construct.station.name].used = 0;
 | 
			
		||||
                client.datastore.updateEntry(msg.guild, construct.currentGuild);
 | 
			
		||||
            }
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            console.log(error);
 | 
			
		||||
            client.radio.delete(msg.guild.id);
 | 
			
		||||
            return msg.channel.send(client.messageEmojis["error"] + `An error occured: ${error}`);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
function play(guild, client, url) {
 | 
			
		||||
    let message = {};
 | 
			
		||||
    const radio = client.radio.get(guild.id);
 | 
			
		||||
    const resource = createAudioResource(url);
 | 
			
		||||
    radio.connection.subscribe(radio.audioPlayer);
 | 
			
		||||
    radio.audioPlayer.play(resource);
 | 
			
		||||
    resource.playStream
 | 
			
		||||
        .on("readable", () => {
 | 
			
		||||
            console.log("Stream started");
 | 
			
		||||
        })
 | 
			
		||||
        .on("finish", () => {
 | 
			
		||||
            console.log("Stream finished");
 | 
			
		||||
            client.funcs.statisticsUpdate(client, guild, radio);
 | 
			
		||||
            radio.voiceChannel.leave();
 | 
			
		||||
            client.radio.delete(guild.id);
 | 
			
		||||
            return;
 | 
			
		||||
        })
 | 
			
		||||
        .on("error", error => {
 | 
			
		||||
            console.error(error);
 | 
			
		||||
            radio.voiceChannel.leave();
 | 
			
		||||
            client.radio.delete(guild.id);
 | 
			
		||||
            return radio.textChannel.send(client.messages.errorPlaying);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    message.play = client.messages.play.replace("%radio.station.name%", radio.station.name);
 | 
			
		||||
    radio.textChannel.send(client.messageEmojis["play"] + message.play);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function searchStation(key, client) {
 | 
			
		||||
    if (client.stations === null) return false;
 | 
			
		||||
    let foundStations = [];
 | 
			
		||||
    if (!key) return false;
 | 
			
		||||
    if (key == "radio") return false;
 | 
			
		||||
    if (key.startsWith("radio ")) key = key.slice(6);
 | 
			
		||||
    const probabilityIncrement = 100 / key.split(" ").length / 2;
 | 
			
		||||
    for (let i = 0; i < key.split(" ").length; i++) {
 | 
			
		||||
        client.stations
 | 
			
		||||
            .filter(
 | 
			
		||||
                x => x.name.toUpperCase().includes(key.split(" ")[i].toUpperCase()) || x === key
 | 
			
		||||
            )
 | 
			
		||||
            .forEach(x =>
 | 
			
		||||
                foundStations.push({ station: x, name: x.name, probability: probabilityIncrement })
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
    if (foundStations.length === 0) return false;
 | 
			
		||||
    for (let i = 0; i < foundStations.length; i++) {
 | 
			
		||||
        for (let j = 0; j < foundStations.length; j++) {
 | 
			
		||||
            if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    for (let i = 0; i < foundStations.length; i++) {
 | 
			
		||||
        if (foundStations[i].name.length > key.length) {
 | 
			
		||||
            foundStations[i].probability -=
 | 
			
		||||
                (foundStations[i].name.split(" ").length - key.split(" ").length) *
 | 
			
		||||
                (probabilityIncrement * 0.5);
 | 
			
		||||
        } else if (foundStations[i].name.length === key.length) {
 | 
			
		||||
            foundStations[i].probability += probabilityIncrement * 0.9;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (let j = 0; j < key.split(" ").length; j++) {
 | 
			
		||||
            if (!foundStations[i].name.toUpperCase().includes(key.toUpperCase().split(" ")[j])) {
 | 
			
		||||
                foundStations[i].probability -= probabilityIncrement * 0.5;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    let highestProbabilityStation;
 | 
			
		||||
    for (let i = 0; i < foundStations.length; i++) {
 | 
			
		||||
        if (
 | 
			
		||||
            !highestProbabilityStation ||
 | 
			
		||||
            highestProbabilityStation.probability < foundStations[i].probability
 | 
			
		||||
        )
 | 
			
		||||
            highestProbabilityStation = foundStations[i];
 | 
			
		||||
        if (
 | 
			
		||||
            highestProbabilityStation &&
 | 
			
		||||
            highestProbabilityStation.probability === foundStations[i].probability
 | 
			
		||||
        ) {
 | 
			
		||||
            highestProbabilityStation = foundStations[i].station;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return highestProbabilityStation;
 | 
			
		||||
}
 | 
			
		||||
@@ -9,10 +9,10 @@ module.exports = class {
 | 
			
		||||
    
 | 
			
		||||
    loadData() {
 | 
			
		||||
        //console.log("");
 | 
			
		||||
        const dataFiles = fs.readdirSync(path.join(path.dirname(__dirname), 'datastore')).filter(f => f.endsWith('.json'));
 | 
			
		||||
        const dataFiles = fs.readdirSync("D:/GitHub/eximiabots-radiox/datastore"/*path.join(path.dirname(__dirname), 'datastore')*/).filter(f => f.endsWith('.json'));
 | 
			
		||||
        for (const file of dataFiles) {
 | 
			
		||||
            try {
 | 
			
		||||
                const json = require(`../datastore/${file}`);
 | 
			
		||||
                const json = require(`../../datastore/${file}`);
 | 
			
		||||
                this.map.set(json.guild.id, json);
 | 
			
		||||
                //console.log('[LOADED] ' + file + " (" + json.guild.id + ")");
 | 
			
		||||
                //console.log(JSON.stringify(json, null, 4));
 | 
			
		||||
@@ -25,9 +25,9 @@ module.exports = {
 | 
			
		||||
 | 
			
		||||
        client.messageEmojis = {};
 | 
			
		||||
 | 
			
		||||
        for (customEmojiName in customEmojis) {
 | 
			
		||||
            customEmojiID = customEmojis[customEmojiName].replace(/[^0-9]+/g, '');
 | 
			
		||||
            customEmoji = client.emojis.cache.get(customEmojiID);
 | 
			
		||||
        for (const customEmojiName in customEmojis) {
 | 
			
		||||
            const customEmojiID = customEmojis[customEmojiName].replace(/[^0-9]+/g, '');
 | 
			
		||||
            const customEmoji = client.emojis.cache.get(customEmojiID);
 | 
			
		||||
            if (customEmoji) {
 | 
			
		||||
                client.messageEmojis[customEmojiName] = customEmojis[customEmojiName];
 | 
			
		||||
            } else {
 | 
			
		||||
@@ -10,7 +10,7 @@ module.exports = {
 | 
			
		||||
 | 
			
		||||
        client.developers = "";
 | 
			
		||||
        let user = "";
 | 
			
		||||
        for (i = 0; i < client.config.devId.length; i++) {
 | 
			
		||||
        for (let i = 0; i < client.config.devId.length; i++) {
 | 
			
		||||
            user = await client.users.fetch(client.config.devId[i]);
 | 
			
		||||
            if (i == client.config.devId.length - 1) {
 | 
			
		||||
                client.developers += user.tag;
 | 
			
		||||
							
								
								
									
										70
									
								
								src/client/utils/adapter.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/client/utils/adapter.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,70 @@
 | 
			
		||||
import { DiscordGatewayAdapterCreator, DiscordGatewayAdapterLibraryMethods } from '@discordjs/voice';
 | 
			
		||||
import { VoiceChannel, Snowflake, Client, Constants, WebSocketShard, Guild, StageChannel } from 'discord.js';
 | 
			
		||||
import { GatewayVoiceServerUpdateDispatchData, GatewayVoiceStateUpdateDispatchData } from 'discord-api-types/v8';
 | 
			
		||||
 | 
			
		||||
const adapters = new Map<Snowflake, DiscordGatewayAdapterLibraryMethods>();
 | 
			
		||||
const trackedClients = new Set<Client>();
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Tracks a Discord.js client, listening to VOICE_SERVER_UPDATE and VOICE_STATE_UPDATE events.
 | 
			
		||||
 * @param client - The Discord.js Client to track
 | 
			
		||||
 */
 | 
			
		||||
function trackClient(client: Client) {
 | 
			
		||||
	if (trackedClients.has(client)) return;
 | 
			
		||||
	trackedClients.add(client);
 | 
			
		||||
	client.ws.on(Constants.WSEvents.VOICE_SERVER_UPDATE, (payload: GatewayVoiceServerUpdateDispatchData) => {
 | 
			
		||||
		adapters.get(payload.guild_id)?.onVoiceServerUpdate(payload);
 | 
			
		||||
	});
 | 
			
		||||
	client.ws.on(Constants.WSEvents.VOICE_STATE_UPDATE, (payload: GatewayVoiceStateUpdateDispatchData) => {
 | 
			
		||||
		if (payload.guild_id && payload.session_id && payload.user_id === client.user?.id) {
 | 
			
		||||
			adapters.get(payload.guild_id)?.onVoiceStateUpdate(payload);
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const trackedGuilds = new Map<WebSocketShard, Set<Snowflake>>();
 | 
			
		||||
 | 
			
		||||
function cleanupGuilds(shard: WebSocketShard) {
 | 
			
		||||
	const guilds = trackedGuilds.get(shard);
 | 
			
		||||
	if (guilds) {
 | 
			
		||||
		for (const guildID of guilds.values()) {
 | 
			
		||||
			adapters.get(guildID)?.destroy();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function trackGuild(guild: Guild) {
 | 
			
		||||
	let guilds = trackedGuilds.get(guild.shard);
 | 
			
		||||
	if (!guilds) {
 | 
			
		||||
		const cleanup = () => cleanupGuilds(guild.shard);
 | 
			
		||||
		guild.shard.on('close', cleanup);
 | 
			
		||||
		guild.shard.on('destroyed', cleanup);
 | 
			
		||||
		guilds = new Set();
 | 
			
		||||
		trackedGuilds.set(guild.shard, guilds);
 | 
			
		||||
	}
 | 
			
		||||
	guilds.add(guild.id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Creates an adapter for a Voice Channel
 | 
			
		||||
 * @param channel - The channel to create the adapter for
 | 
			
		||||
 */
 | 
			
		||||
export function createDiscordJSAdapter(channel: VoiceChannel | StageChannel): DiscordGatewayAdapterCreator {
 | 
			
		||||
	return (methods) => {
 | 
			
		||||
		adapters.set(channel.guild.id, methods);
 | 
			
		||||
		trackClient(channel.client);
 | 
			
		||||
		trackGuild(channel.guild);
 | 
			
		||||
		return {
 | 
			
		||||
			sendPayload(data) {
 | 
			
		||||
				if (channel.guild.shard.status === Constants.Status.READY) {
 | 
			
		||||
					channel.guild.shard.send(data);
 | 
			
		||||
					return true;
 | 
			
		||||
				}
 | 
			
		||||
				return false;
 | 
			
		||||
			},
 | 
			
		||||
			destroy() {
 | 
			
		||||
				return adapters.delete(channel.guild.id);
 | 
			
		||||
			},
 | 
			
		||||
		};
 | 
			
		||||
	};
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/client/utils/typings.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/client/utils/typings.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
export interface command { }
 | 
			
		||||
 | 
			
		||||
export interface radio {}
 | 
			
		||||
							
								
								
									
										3
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/index.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
const { default: RadioClient } = require("./Client");
 | 
			
		||||
 | 
			
		||||
const client = new RadioClient();
 | 
			
		||||
		Reference in New Issue
	
	Block a user