mirror of
				https://github.com/warengroup/eximiabots-radiox.git
				synced 2025-11-04 03:09:32 +00:00 
			
		
		
		
	
							
								
								
									
										2
									
								
								.github/workflows/docker-build.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/docker-build.yml
									
									
									
									
										vendored
									
									
								
							@@ -14,7 +14,7 @@ jobs:
 | 
				
			|||||||
    - name: Checkout
 | 
					    - name: Checkout
 | 
				
			||||||
      uses: actions/checkout@v3
 | 
					      uses: actions/checkout@v3
 | 
				
			||||||
    - name: Setup Docker Buildx
 | 
					    - name: Setup Docker Buildx
 | 
				
			||||||
      uses: docker/setup-buildx-action@v2.5.0
 | 
					      uses: docker/setup-buildx-action@v2.6.0
 | 
				
			||||||
      id: buildx
 | 
					      id: buildx
 | 
				
			||||||
      with:
 | 
					      with:
 | 
				
			||||||
        install: true
 | 
					        install: true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
FROM node:16-alpine
 | 
					FROM node:18-alpine
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#Dependencies
 | 
					#Dependencies
 | 
				
			||||||
RUN apk add --virtual .build-deps python3 make g++ gcc git
 | 
					RUN apk add --virtual .build-deps python3 make g++ gcc git
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
| Version | Supported          |
 | 
					| Version | Supported          |
 | 
				
			||||||
| ------- | ------------------ |
 | 
					| ------- | ------------------ |
 | 
				
			||||||
 | 
					| 0.5.x   | :white_check_mark: |
 | 
				
			||||||
| 0.4.x   | :white_check_mark: |
 | 
					| 0.4.x   | :white_check_mark: |
 | 
				
			||||||
| 0.3.x   | :x:                |
 | 
					| 0.3.x   | :x:                |
 | 
				
			||||||
| 0.2.x   | :x:                |
 | 
					| 0.2.x   | :x:                |
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2477
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2477
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										13
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								package.json
									
									
									
									
									
								
							@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "eximiabots-radiox",
 | 
					  "name": "eximiabots-radiox",
 | 
				
			||||||
  "version": "0.4.3",
 | 
					  "version": "0.5.0",
 | 
				
			||||||
  "description": "Internet Radio to your Discord guild",
 | 
					  "description": "Internet Radio to your Discord guild",
 | 
				
			||||||
  "main": "index.js",
 | 
					  "main": "index.js",
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
@@ -24,16 +24,15 @@
 | 
				
			|||||||
    "@discordjs/voice": "^0.16.0",
 | 
					    "@discordjs/voice": "^0.16.0",
 | 
				
			||||||
    "discord-api-types": "^0.37.43",
 | 
					    "discord-api-types": "^0.37.43",
 | 
				
			||||||
    "discord.js": "^14.11.0",
 | 
					    "discord.js": "^14.11.0",
 | 
				
			||||||
    "dotenv": "^16.1.3",
 | 
					    "dotenv": "^16.1.4",
 | 
				
			||||||
    "libsodium-wrappers": "^0.7.11",
 | 
					    "libsodium-wrappers": "^0.7.11",
 | 
				
			||||||
    "node-fetch": "^3.3.1",
 | 
					 | 
				
			||||||
    "path": "^0.12.7"
 | 
					    "path": "^0.12.7"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
    "@types/node": "^20.2.5",
 | 
					    "@types/node": "^20.2.5",
 | 
				
			||||||
    "@types/ws": "^8.5.4",
 | 
					    "@types/ws": "^8.5.4",
 | 
				
			||||||
    "@typescript-eslint/eslint-plugin": "^5.59.8",
 | 
					    "@typescript-eslint/eslint-plugin": "^5.59.9",
 | 
				
			||||||
    "@typescript-eslint/parser": "^5.59.8",
 | 
					    "@typescript-eslint/parser": "^5.59.9",
 | 
				
			||||||
    "eslint": "^8.41.0",
 | 
					    "eslint": "^8.41.0",
 | 
				
			||||||
    "eslint-config-prettier": "^8.8.0",
 | 
					    "eslint-config-prettier": "^8.8.0",
 | 
				
			||||||
    "eslint-plugin-prettier": "^4.2.1",
 | 
					    "eslint-plugin-prettier": "^4.2.1",
 | 
				
			||||||
@@ -44,7 +43,7 @@
 | 
				
			|||||||
    "typescript": "^5.1.3"
 | 
					    "typescript": "^5.1.3"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "engines": {
 | 
					  "engines": {
 | 
				
			||||||
      "node": ">=16.9.1",
 | 
					      "node": ">=18.16.0",
 | 
				
			||||||
      "npm": ">=7.0.0"
 | 
					      "npm": ">=8.0.0"
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,15 @@
 | 
				
			|||||||
import { Client, Collection, IntentsBitField } from "discord.js";
 | 
					import { Client, Collection, IntentsBitField } from "discord.js";
 | 
				
			||||||
import Datastore from "./client/classes/Datastore.js";
 | 
					import Datastore from "./client/classes/Datastore";
 | 
				
			||||||
import Radio from "./client/classes/Radio.js";
 | 
					import Radio from "./client/classes/Radio";
 | 
				
			||||||
import Stations from "./client/classes/Stations.js";
 | 
					import Stations from "./client/classes/Stations";
 | 
				
			||||||
import Streamer from "./client/classes/Streamer.js";
 | 
					import Streamer from "./client/classes/Streamer";
 | 
				
			||||||
import Statistics from "./client/classes/Statistics.js";
 | 
					import Statistics from "./client/classes/Statistics";
 | 
				
			||||||
import fs from "fs";
 | 
					import { command } from "./client/commands";
 | 
				
			||||||
import { command, radio } from "./client/utils/typings.js";
 | 
					import config from "./config";
 | 
				
			||||||
import config from "./config.js";
 | 
					import events from "./client/events"
 | 
				
			||||||
import messages from "./client/messages.js";
 | 
					import { funcs } from "./client/funcs";
 | 
				
			||||||
import path from "path";
 | 
					import { messages } from "./client/messages";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const events = "./client/events/";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const GatewayIntents = new IntentsBitField();
 | 
					const GatewayIntents = new IntentsBitField();
 | 
				
			||||||
GatewayIntents.add(
 | 
					GatewayIntents.add(
 | 
				
			||||||
@@ -19,9 +18,9 @@ GatewayIntents.add(
 | 
				
			|||||||
    1 << 9 // GUILD_MESSAGES
 | 
					    1 << 9 // GUILD_MESSAGES
 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class RadioClient extends Client {
 | 
					export default class RadioClient extends Client {
 | 
				
			||||||
    readonly commands: Collection<string, command>;
 | 
					    readonly commands: Collection<string, command>;
 | 
				
			||||||
    public funcs: any;
 | 
					    readonly funcs = funcs;
 | 
				
			||||||
    readonly config = config;
 | 
					    readonly config = config;
 | 
				
			||||||
    readonly messages = messages;
 | 
					    readonly messages = messages;
 | 
				
			||||||
    public datastore: Datastore | null;
 | 
					    public datastore: Datastore | null;
 | 
				
			||||||
@@ -29,6 +28,7 @@ class RadioClient extends Client {
 | 
				
			|||||||
    public streamer: Streamer | null;
 | 
					    public streamer: Streamer | null;
 | 
				
			||||||
    public statistics: Statistics | null;
 | 
					    public statistics: Statistics | null;
 | 
				
			||||||
    public radio: Radio | null;
 | 
					    public radio: Radio | null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super({
 | 
					        super({
 | 
				
			||||||
            intents: GatewayIntents
 | 
					            intents: GatewayIntents
 | 
				
			||||||
@@ -40,16 +40,6 @@ class RadioClient extends Client {
 | 
				
			|||||||
        this.statistics = null;
 | 
					        this.statistics = null;
 | 
				
			||||||
        this.radio = null;
 | 
					        this.radio = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.funcs = {};
 | 
					 | 
				
			||||||
        this.funcs.check = require("./client/funcs/check.js");
 | 
					 | 
				
			||||||
        this.funcs.isDev = require("./client/funcs/isDev.js");
 | 
					 | 
				
			||||||
        this.funcs.logger = require("./client/funcs/logger.js");
 | 
					 | 
				
			||||||
        this.funcs.msToTime = require("./client/funcs/msToTime.js");
 | 
					 | 
				
			||||||
        this.funcs.saveState = require("./client/funcs/saveState.js");
 | 
					 | 
				
			||||||
        this.funcs.loadState = require("./client/funcs/loadState.js");
 | 
					 | 
				
			||||||
        this.funcs.play = require("./client/funcs/play.js");
 | 
					 | 
				
			||||||
        this.funcs.listStations = require("./client/funcs/listStations.js");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        console.log('RadioX ' + this.config.version);
 | 
					        console.log('RadioX ' + this.config.version);
 | 
				
			||||||
        console.log('Internet Radio to your Discord guild');
 | 
					        console.log('Internet Radio to your Discord guild');
 | 
				
			||||||
        console.log('(c)2020-2022 EximiaBots by Warén Group');
 | 
					        console.log('(c)2020-2022 EximiaBots by Warén Group');
 | 
				
			||||||
@@ -60,58 +50,12 @@ class RadioClient extends Client {
 | 
				
			|||||||
        this.funcs.logger("Maintenance Mode", "Enabled");
 | 
					        this.funcs.logger("Maintenance Mode", "Enabled");
 | 
				
			||||||
        this.config.maintenanceMode = true;
 | 
					        this.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.on("ready", () => {
 | 
					        events(this);
 | 
				
			||||||
            require(`${events}ready`).execute(this);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.on("messageCreate", msg => {
 | 
					 | 
				
			||||||
            require(`${events}messageCreate`).execute(this, msg);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.on("messageDelete", msg => {
 | 
					 | 
				
			||||||
            require(`${events}messageDelete`).execute(this, msg);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.on("interactionCreate", interaction => {
 | 
					 | 
				
			||||||
            require(`${events}interactionCreate`).execute(this, interaction);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.on("voiceStateUpdate", (oldState, newState) => {
 | 
					 | 
				
			||||||
            require(`${events}voiceStateUpdate`).execute(this, oldState, newState);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.on("error", error => {
 | 
					 | 
				
			||||||
            this.funcs.logger("Discord Client / Error");
 | 
					 | 
				
			||||||
            console.error(error);
 | 
					 | 
				
			||||||
            console.log('');
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        process.on('SIGINT', () => {
 | 
					 | 
				
			||||||
            require(`${events}SIGINT`).execute(this);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        process.on('SIGTERM', () => {
 | 
					 | 
				
			||||||
            require(`${events}SIGTERM`).execute(this);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        process.on('uncaughtException', (error) => {
 | 
					 | 
				
			||||||
            require(`${events}uncaughtException`).execute(this, error);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        process.on('exit', () => {
 | 
					 | 
				
			||||||
            this.funcs.logger("Bot", "Stopping");
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        process.on('warning', (warning) => {
 | 
					 | 
				
			||||||
            require(`${events}warning`).execute(this, warning);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.login(this.config.token).catch((err) => {
 | 
					        this.login(this.config.token).catch((err) => {
 | 
				
			||||||
            this.funcs.logger("Discord Client / Error");
 | 
					            this.funcs.logger("Discord Client", "Login Error");
 | 
				
			||||||
            console.log(err);
 | 
					            console.log(err);
 | 
				
			||||||
            console.log('');
 | 
					            console.log('');
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
export default RadioClient
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,21 @@
 | 
				
			|||||||
const fs = require('fs');
 | 
					import { Guild } from 'discord.js';
 | 
				
			||||||
const path = require('path');
 | 
					import fs from 'fs';
 | 
				
			||||||
 | 
					import path from 'path';
 | 
				
			||||||
 | 
					import { state } from './Radio';
 | 
				
			||||||
 | 
					import { statistics } from './Statistics';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = class {
 | 
					export interface datastore {
 | 
				
			||||||
 | 
					    guild: {
 | 
				
			||||||
 | 
					        id: string,
 | 
				
			||||||
 | 
					        name?: string
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    statistics: statistics,
 | 
				
			||||||
 | 
					    state: state | null,
 | 
				
			||||||
 | 
					    updated?: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Datastore {
 | 
				
			||||||
 | 
					    map: Map<string, datastore>;
 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        this.map = new Map();
 | 
					        this.map = new Map();
 | 
				
			||||||
        this.loadData();
 | 
					        this.loadData();
 | 
				
			||||||
@@ -13,7 +27,7 @@ module.exports = class {
 | 
				
			|||||||
            fs.mkdirSync(dir);
 | 
					            fs.mkdirSync(dir);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        //console.log("");
 | 
					        //console.log("");
 | 
				
			||||||
        const dataFiles = fs.readdirSync(path.join(path.dirname(__dirname), '../../datastore')).filter(f => f.endsWith('.json'));
 | 
					        const dataFiles = fs.readdirSync(path.join(path.dirname(__dirname), '../../datastore')).filter((f: string) => f.endsWith('.json'));
 | 
				
			||||||
        for (const file of dataFiles) {
 | 
					        for (const file of dataFiles) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                const json = require(`../../../datastore/${file}`);
 | 
					                const json = require(`../../../datastore/${file}`);
 | 
				
			||||||
@@ -27,7 +41,8 @@ module.exports = class {
 | 
				
			|||||||
        //console.log("");
 | 
					        //console.log("");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    checkEntry(id){
 | 
					    checkEntry(id: string | undefined){
 | 
				
			||||||
 | 
					        if(!id) return;
 | 
				
			||||||
        this.loadEntry(id);
 | 
					        this.loadEntry(id);
 | 
				
			||||||
        if(!this.map.has(id)){
 | 
					        if(!this.map.has(id)){
 | 
				
			||||||
            this.createEntry(id);
 | 
					            this.createEntry(id);
 | 
				
			||||||
@@ -37,17 +52,19 @@ module.exports = class {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    createEntry(id){
 | 
					    createEntry(id: string){
 | 
				
			||||||
        let newData = {};
 | 
					        let newData: datastore = {
 | 
				
			||||||
        newData.guild = {};
 | 
					            guild: {
 | 
				
			||||||
        newData.guild.id = id;
 | 
					                id: id,
 | 
				
			||||||
        newData.statistics = {};
 | 
					            },
 | 
				
			||||||
        newData.state = {};
 | 
					            statistics: {},
 | 
				
			||||||
 | 
					            state: null
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
        this.map.set(id, newData);
 | 
					        this.map.set(id, newData);
 | 
				
			||||||
        this.saveEntry(id, newData);
 | 
					        this.saveEntry(id, newData);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    loadEntry(id){
 | 
					    loadEntry(id: string){
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            const json = require(`../../../datastore/` + id + '.json');
 | 
					            const json = require(`../../../datastore/` + id + '.json');
 | 
				
			||||||
            this.map.set(id, json);
 | 
					            this.map.set(id, json);
 | 
				
			||||||
@@ -55,11 +72,11 @@ module.exports = class {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getEntry(id){
 | 
					    getEntry(id: string){
 | 
				
			||||||
        return this.map.get(id);
 | 
					        return this.map.get(id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    updateEntry(guild, newData) {
 | 
					    updateEntry(guild: Guild | { id: string, name: string }, newData: datastore) {
 | 
				
			||||||
        newData.guild.name = guild.name;
 | 
					        newData.guild.name = guild.name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let date = new Date();
 | 
					        let date = new Date();
 | 
				
			||||||
@@ -70,36 +87,14 @@ module.exports = class {
 | 
				
			|||||||
        //this.showEntry(this.getEntry(guild.id));
 | 
					        //this.showEntry(this.getEntry(guild.id));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    showEntry(data){
 | 
					    showEntry(data : datastore){
 | 
				
			||||||
        console.log(data);
 | 
					        console.log(data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    createTestFile () {
 | 
					    saveEntry(file: string, data: datastore) {
 | 
				
			||||||
        let newData = {
 | 
					        fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", JSON.stringify(data, null, 4), 'utf8', function(err: NodeJS.ErrnoException | null) {
 | 
				
			||||||
            "guild": {
 | 
					 | 
				
			||||||
                "id": "test",
 | 
					 | 
				
			||||||
                "name": "Test"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            "statistics": {
 | 
					 | 
				
			||||||
                "test": {
 | 
					 | 
				
			||||||
                    "time": 0,
 | 
					 | 
				
			||||||
                    "used": 0
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            "state": {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        this.updateEntry(newData.guild, newData);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    saveEntry(file, data) {
 | 
					 | 
				
			||||||
        data = JSON.stringify(data, null, 4);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        fs.writeFile(path.join(path.dirname(__dirname), '../../datastore') + "/" + file + ".json", data, 'utf8', function(err) {
 | 
					 | 
				
			||||||
            if (err) {
 | 
					            if (err) {
 | 
				
			||||||
                //console.log(err);
 | 
					
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -1,78 +0,0 @@
 | 
				
			|||||||
const {
 | 
					 | 
				
			||||||
    getVoiceConnection,
 | 
					 | 
				
			||||||
    joinVoiceChannel
 | 
					 | 
				
			||||||
} = require("@discordjs/voice");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = class Radio extends Map {
 | 
					 | 
				
			||||||
    constructor() {
 | 
					 | 
				
			||||||
        super();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    save(client) {
 | 
					 | 
				
			||||||
        let currentRadios = this.keys();
 | 
					 | 
				
			||||||
        let radio = currentRadios.next();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while (!radio.done) {
 | 
					 | 
				
			||||||
            let currentRadio = this.get(radio.value);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (currentRadio) {
 | 
					 | 
				
			||||||
                currentRadio.guild = client.datastore.getEntry(radio.value).guild;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                client.statistics.update(client, currentRadio.guild, currentRadio);
 | 
					 | 
				
			||||||
                client.funcs.saveState(client, currentRadio.guild, currentRadio);
 | 
					 | 
				
			||||||
                currentRadio.connection?.destroy();
 | 
					 | 
				
			||||||
                currentRadio.message?.delete();
 | 
					 | 
				
			||||||
                this.delete(radio.value);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            radio = currentRadios.next();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    restore(client, guilds) {
 | 
					 | 
				
			||||||
        if(!client.stations) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        guilds.forEach(async guild => {
 | 
					 | 
				
			||||||
            let state = client.funcs.loadState(client, guild);
 | 
					 | 
				
			||||||
            if(!state) return;
 | 
					 | 
				
			||||||
            if(!state.station || !state.channels.voice || !state.channels.text) return;
 | 
					 | 
				
			||||||
            let voiceChannel = client.channels.cache.get(state.channels.voice);
 | 
					 | 
				
			||||||
            if(!voiceChannel) return;
 | 
					 | 
				
			||||||
            if(voiceChannel.members.filter(member => !member.user.bot).size === 0) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const sstation = await client.stations.search(state.station.name, "direct");
 | 
					 | 
				
			||||||
            let station = sstation;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(!station) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const construct = {
 | 
					 | 
				
			||||||
                textChannel: client.channels.cache.get(state.channels.text),
 | 
					 | 
				
			||||||
                voiceChannel: client.channels.cache.get(state.channels.voice),
 | 
					 | 
				
			||||||
                connection: null,
 | 
					 | 
				
			||||||
                message: null,
 | 
					 | 
				
			||||||
                station: station
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
            this.set(guild.id, construct);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                const connection =
 | 
					 | 
				
			||||||
                    getVoiceConnection(guild.id) ??
 | 
					 | 
				
			||||||
                    joinVoiceChannel({
 | 
					 | 
				
			||||||
                        channelId: voiceChannel.id,
 | 
					 | 
				
			||||||
                        guildId: voiceChannel.guild.id,
 | 
					 | 
				
			||||||
                        adapterCreator: voiceChannel.guild.voiceAdapterCreator
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                construct.connection = connection;
 | 
					 | 
				
			||||||
                let date = new Date();
 | 
					 | 
				
			||||||
                construct.startTime = date.getTime();
 | 
					 | 
				
			||||||
                client.datastore.checkEntry(guild.id);
 | 
					 | 
				
			||||||
                client.funcs.play(client, null, guild, station);
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                console.log(error);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										108
									
								
								src/client/classes/Radio.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								src/client/classes/Radio.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,108 @@
 | 
				
			|||||||
 | 
					import { Channel, Collection, GuildMember, OAuth2Guild, TextBasedChannel, VoiceBasedChannel, VoiceChannel } from "discord.js";
 | 
				
			||||||
 | 
					import { getVoiceConnection, joinVoiceChannel, VoiceConnection } from "@discordjs/voice";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { station } from "./Stations";
 | 
				
			||||||
 | 
					import { datastore } from "./Datastore";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface radio {
 | 
				
			||||||
 | 
					    textChannel: Channel | TextBasedChannel | undefined | null,
 | 
				
			||||||
 | 
					    voiceChannel: Channel | VoiceBasedChannel | undefined,
 | 
				
			||||||
 | 
					    connection: VoiceConnection | null,
 | 
				
			||||||
 | 
					    message: null,
 | 
				
			||||||
 | 
					    station: station,
 | 
				
			||||||
 | 
					    datastore?: datastore,
 | 
				
			||||||
 | 
					    currentTime?: number,
 | 
				
			||||||
 | 
					    startTime: number,
 | 
				
			||||||
 | 
					    playTime?: number,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface state {
 | 
				
			||||||
 | 
					    channels: {
 | 
				
			||||||
 | 
					        "text": string | undefined,
 | 
				
			||||||
 | 
					        "voice": string | undefined
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    date: string,
 | 
				
			||||||
 | 
					    station: {
 | 
				
			||||||
 | 
					        name: string,
 | 
				
			||||||
 | 
					        owner: string
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Radio extends Map {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        super();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    save(client: RadioClient): void {
 | 
				
			||||||
 | 
					        let currentRadios = this.keys();
 | 
				
			||||||
 | 
					        let radio = currentRadios.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (!radio.done) {
 | 
				
			||||||
 | 
					            let currentRadio = this.get(radio.value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (currentRadio) {
 | 
				
			||||||
 | 
					                currentRadio.guild = client.datastore?.getEntry(radio.value)?.guild;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                client.statistics?.update(client, currentRadio.guild, currentRadio);
 | 
				
			||||||
 | 
					                client.funcs.saveState(client, currentRadio.guild, currentRadio);
 | 
				
			||||||
 | 
					                currentRadio.connection?.destroy();
 | 
				
			||||||
 | 
					                currentRadio.message?.delete();
 | 
				
			||||||
 | 
					                this.delete(radio.value);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            radio = currentRadios.next();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    restore(client: RadioClient, guilds: Collection<string, OAuth2Guild>): void {
 | 
				
			||||||
 | 
					        if(!client.stations) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        guilds.forEach(async (guild: OAuth2Guild) => {
 | 
				
			||||||
 | 
					            let state = client.funcs.loadState(client, guild);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!state) return;
 | 
				
			||||||
 | 
					            if(state.channels?.text === undefined || state.channels?.voice === undefined) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let voiceChannel = client.channels.cache.get(state.channels.voice);
 | 
				
			||||||
 | 
					            if(!voiceChannel || !(voiceChannel instanceof VoiceChannel)) return;
 | 
				
			||||||
 | 
					            if(voiceChannel.members.filter((member: GuildMember) => !member.user.bot).size === 0) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const sstation = client.stations?.search(state.station.name, "direct");
 | 
				
			||||||
 | 
					            let station = sstation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!station) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let date = new Date();
 | 
				
			||||||
 | 
					            const construct: radio = {
 | 
				
			||||||
 | 
					                textChannel: client.channels.cache.get(state.channels.text),
 | 
				
			||||||
 | 
					                voiceChannel: client.channels.cache.get(state.channels.voice),
 | 
				
			||||||
 | 
					                connection: null,
 | 
				
			||||||
 | 
					                message: null,
 | 
				
			||||||
 | 
					                station: station,
 | 
				
			||||||
 | 
					                startTime: date.getTime()
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            this.set(guild.id, construct);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                const connection =
 | 
				
			||||||
 | 
					                    getVoiceConnection(guild.id) ??
 | 
				
			||||||
 | 
					                    joinVoiceChannel({
 | 
				
			||||||
 | 
					                        channelId: voiceChannel.id,
 | 
				
			||||||
 | 
					                        guildId: voiceChannel.guild.id,
 | 
				
			||||||
 | 
					                        adapterCreator: voiceChannel.guild.voiceAdapterCreator
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                construct.connection = connection;
 | 
				
			||||||
 | 
					                let date = new Date();
 | 
				
			||||||
 | 
					                construct.startTime = date.getTime();
 | 
				
			||||||
 | 
					                client.datastore?.checkEntry(guild.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                client.funcs.play(client, null, guild, station);
 | 
				
			||||||
 | 
					            } catch (error) {
 | 
				
			||||||
 | 
					                console.log(error);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,80 +1,59 @@
 | 
				
			|||||||
const _importDynamic = new Function('modulePath', 'return import(modulePath)');
 | 
					import logger from "../funcs/logger";
 | 
				
			||||||
const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args));
 | 
					
 | 
				
			||||||
 | 
					export interface station {
 | 
				
			||||||
 | 
					    name: string,
 | 
				
			||||||
 | 
					    owner: string,
 | 
				
			||||||
 | 
					    logo: string,
 | 
				
			||||||
 | 
					    stream: {
 | 
				
			||||||
 | 
					        [key: string]: string
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Stations extends Array {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = class Stations extends Array {
 | 
					 | 
				
			||||||
    constructor() {
 | 
					    constructor() {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        this.logger = require("../funcs/logger.js");
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fetch(options){
 | 
					    async fetch(options: { url: string, show?: boolean}){
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            this.logger('Stations', 'Started fetching list – ' + options.url);
 | 
					            logger('Stations', 'Started fetching list - ' + options.url);
 | 
				
			||||||
            let list = await fetch(options.url)
 | 
					            let stations: station[] = await fetch(options.url)
 | 
				
			||||||
                .then(this.checkFetchStatus)
 | 
					                .then(this.checkFetchStatus)
 | 
				
			||||||
                .then(response => response.json());
 | 
					                .then((response: Response) => response.json());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(list){
 | 
					            for(const station of stations){
 | 
				
			||||||
                this.length = 0;
 | 
					                this.push(station);
 | 
				
			||||||
                list.forEach(station => {
 | 
					                if(options.show) logger('Stations', station.name);
 | 
				
			||||||
                    try {
 | 
					 | 
				
			||||||
                        this.push(station);
 | 
					 | 
				
			||||||
                    } catch (error) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(options.show){
 | 
					 | 
				
			||||||
                    list.forEach(station => {
 | 
					 | 
				
			||||||
                        this.logger('Stations', station.name);
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                list.forEach(async station => {
 | 
					 | 
				
			||||||
                    try {
 | 
					 | 
				
			||||||
                        let stationTest = await fetch(station.stream[station.stream.default]);
 | 
					 | 
				
			||||||
                        if(stationTest.ok === true) return;
 | 
					 | 
				
			||||||
                        this.splice(this.indexOf(station),1);
 | 
					 | 
				
			||||||
                    } catch (error) {
 | 
					 | 
				
			||||||
                        this.splice(this.indexOf(station),1);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.logger('Stations', 'Successfully fetched list');
 | 
					            logger('Stations', 'Successfully fetched list');
 | 
				
			||||||
        } catch (error) {
 | 
					        } catch (error) {
 | 
				
			||||||
            this.logger('Stations', 'Fetching list failed');
 | 
					            logger('Stations', 'Fetching list failed');
 | 
				
			||||||
            console.error(error + "\n");
 | 
					            console.error(error + "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(this.length == 0) this.fetch(options);
 | 
					            if(this.length == 0) setTimeout( () => {
 | 
				
			||||||
 | 
					                this.fetch(options)
 | 
				
			||||||
 | 
					            }, 150 );
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    checkFetchStatus(response) {
 | 
					    checkFetchStatus(response: Response) {
 | 
				
			||||||
        if (response.ok) { // res.status >= 200 && res.status < 300
 | 
					        if (response.ok) {
 | 
				
			||||||
            return response;
 | 
					            return response;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            throw new Error(response.status + " " + response.statusText);
 | 
					            throw new Error(response.status + " " + response.statusText);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    search(key, type) {
 | 
					    search(key: string, type: string) {
 | 
				
			||||||
        if (this === null) return false;
 | 
					        if (this === null || !key || !type) return null;
 | 
				
			||||||
        if (!key) return false;
 | 
					 | 
				
			||||||
        if (!type) return false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(type == "direct"){
 | 
					        if(type == "direct"){
 | 
				
			||||||
            let foundStation;
 | 
					            return this.find(station => station.name === key);
 | 
				
			||||||
            this.forEach(station => {
 | 
					 | 
				
			||||||
                if(station.name != key) return false;
 | 
					 | 
				
			||||||
                foundStation = station;
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return foundStation;
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
 | 
					            let foundStations : { station: string, name: string, probability: number }[] = [];
 | 
				
			||||||
            let foundStations = [];
 | 
					            if (key == "radio") return null;
 | 
				
			||||||
            if (key == "radio") return false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this
 | 
					            this
 | 
				
			||||||
                .filter(
 | 
					                .filter(
 | 
				
			||||||
@@ -95,7 +74,7 @@ module.exports = class Stations extends Array {
 | 
				
			|||||||
                        foundStations.push({ station: x, name: x.name, probability: probabilityIncrement })
 | 
					                        foundStations.push({ station: x, name: x.name, probability: probabilityIncrement })
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (foundStations.length === 0) return false;
 | 
					            if (foundStations.length === 0) return null;
 | 
				
			||||||
            for (let i = 0; i < foundStations.length; i++) {
 | 
					            for (let i = 0; i < foundStations.length; i++) {
 | 
				
			||||||
                for (let j = 0; j < foundStations.length; j++) {
 | 
					                for (let j = 0; j < foundStations.length; j++) {
 | 
				
			||||||
                    if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1);
 | 
					                    if (foundStations[i] === foundStations[j] && i !== j) foundStations.splice(i, 1);
 | 
				
			||||||
@@ -116,7 +95,9 @@ module.exports = class Stations extends Array {
 | 
				
			|||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            let highestProbabilityStation;
 | 
					            let highestProbabilityStation : { station: string, name: string, probability: number } | undefined;
 | 
				
			||||||
 | 
					            let stationName = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            for (let i = 0; i < foundStations.length; i++) {
 | 
					            for (let i = 0; i < foundStations.length; i++) {
 | 
				
			||||||
                if (
 | 
					                if (
 | 
				
			||||||
                    !highestProbabilityStation ||
 | 
					                    !highestProbabilityStation ||
 | 
				
			||||||
@@ -127,10 +108,10 @@ module.exports = class Stations extends Array {
 | 
				
			|||||||
                    highestProbabilityStation &&
 | 
					                    highestProbabilityStation &&
 | 
				
			||||||
                    highestProbabilityStation.probability === foundStations[i].probability
 | 
					                    highestProbabilityStation.probability === foundStations[i].probability
 | 
				
			||||||
                ) {
 | 
					                ) {
 | 
				
			||||||
                    highestProbabilityStation = foundStations[i].station;
 | 
					                    stationName = foundStations[i].station;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return highestProbabilityStation;
 | 
					            return stationName;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -1,70 +0,0 @@
 | 
				
			|||||||
module.exports = class {
 | 
					 | 
				
			||||||
    constructor() {
 | 
					 | 
				
			||||||
        this.map = new Map();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    update(client, guild, radio) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.datastore.checkEntry(guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        radio.datastore = client.datastore.getEntry(guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(!radio.datastore.statistics[radio.station.name]){
 | 
					 | 
				
			||||||
            radio.datastore.statistics[radio.station.name] = {};
 | 
					 | 
				
			||||||
            radio.datastore.statistics[radio.station.name].time = 0;
 | 
					 | 
				
			||||||
            radio.datastore.statistics[radio.station.name].used = 0;
 | 
					 | 
				
			||||||
            client.datastore.updateEntry(guild, radio.datastore);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let date = new Date();
 | 
					 | 
				
			||||||
        radio.currentTime = date.getTime();
 | 
					 | 
				
			||||||
        radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime);
 | 
					 | 
				
			||||||
        radio.datastore.statistics[radio.station.name].time = parseInt(radio.datastore.statistics[radio.station.name].time)+parseInt(radio.playTime);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        radio.datastore.statistics[radio.station.name].used = parseInt(radio.datastore.statistics[radio.station.name].used)+1;
 | 
					 | 
				
			||||||
        client.datastore.updateEntry(guild, radio.datastore);
 | 
					 | 
				
			||||||
        this.calculateGlobal(client);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    calculateGlobal(client){
 | 
					 | 
				
			||||||
        if(!client.stations) return;
 | 
					 | 
				
			||||||
        if(!client.datastore.map) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let guilds = client.datastore.map.keys();
 | 
					 | 
				
			||||||
        let stations = client.stations;
 | 
					 | 
				
			||||||
        let statistics = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(!client.stations) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let calculation = guilds.next();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        while (!calculation.done) {
 | 
					 | 
				
			||||||
            let currentGuild = client.datastore.getEntry(calculation.value);
 | 
					 | 
				
			||||||
            if(calculation.value != 'global'){
 | 
					 | 
				
			||||||
                if(stations){
 | 
					 | 
				
			||||||
                    Object.keys(stations).forEach(function(station) {
 | 
					 | 
				
			||||||
                        if(currentGuild.statistics[stations[station].name] && currentGuild.statistics[stations[station].name].time && parseInt(currentGuild.statistics[stations[station].name].time) != 0  && currentGuild.statistics[stations[station].name].used && parseInt(currentGuild.statistics[stations[station].name].used) != 0){
 | 
					 | 
				
			||||||
                            if(!statistics[stations[station].name]){
 | 
					 | 
				
			||||||
                                statistics[stations[station].name] = {};
 | 
					 | 
				
			||||||
                                statistics[stations[station].name].time = 0;
 | 
					 | 
				
			||||||
                                statistics[stations[station].name].used = 0;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            statistics[stations[station].name].time = parseInt(statistics[stations[station].name].time)+parseInt(currentGuild.statistics[stations[station].name].time);
 | 
					 | 
				
			||||||
                            statistics[stations[station].name].used = parseInt(statistics[stations[station].name].used)+parseInt(currentGuild.statistics[stations[station].name].used);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            calculation = guilds.next();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let newData = {};
 | 
					 | 
				
			||||||
        newData.guild = {};
 | 
					 | 
				
			||||||
        newData.guild.id = "global";
 | 
					 | 
				
			||||||
        newData.guild.name = "global";
 | 
					 | 
				
			||||||
        newData.statistics = statistics;
 | 
					 | 
				
			||||||
        client.datastore.updateEntry(newData.guild, newData);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										95
									
								
								src/client/classes/Statistics.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								src/client/classes/Statistics.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					import { Guild } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { radio } from "./Radio";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface statistics {
 | 
				
			||||||
 | 
					    [key: string]: statistic
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					interface statistic {
 | 
				
			||||||
 | 
					    "time": number,
 | 
				
			||||||
 | 
					    "used": number
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Statistics {
 | 
				
			||||||
 | 
					    map: Map<string, statistics>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        this.map = new Map();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    update(client: RadioClient, guild: Guild | null, radio: radio) {
 | 
				
			||||||
 | 
					        if(!guild) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        client.datastore?.checkEntry(guild.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        radio.datastore = client.datastore?.getEntry(guild.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(radio.datastore === undefined) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!radio.datastore.statistics[radio.station.name]){
 | 
				
			||||||
 | 
					            radio.datastore.statistics[radio.station.name] = {
 | 
				
			||||||
 | 
					                time: 0,
 | 
				
			||||||
 | 
					                used: 0
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            client.datastore?.updateEntry(guild, radio.datastore);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let date = new Date();
 | 
				
			||||||
 | 
					        radio.currentTime = date.getTime();
 | 
				
			||||||
 | 
					        radio.playTime = radio.currentTime - radio.startTime;
 | 
				
			||||||
 | 
					        radio.datastore.statistics[radio.station.name] = {
 | 
				
			||||||
 | 
					            time: radio.datastore.statistics[radio.station.name].time + radio.playTime,
 | 
				
			||||||
 | 
					            used: radio.datastore.statistics[radio.station.name].used + 1
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        client.datastore?.updateEntry(guild, radio.datastore);
 | 
				
			||||||
 | 
					        this.calculateGlobal(client);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    calculateGlobal(client: RadioClient){
 | 
				
			||||||
 | 
					        if(!client.datastore?.map) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let guilds = client.datastore.map.keys();
 | 
				
			||||||
 | 
					        let statistics : statistics = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!client.stations) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let calculation = guilds.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        while (!calculation.done) {
 | 
				
			||||||
 | 
					            let currentGuild = client.datastore.getEntry(calculation.value);
 | 
				
			||||||
 | 
					            if(calculation.value != 'global'){
 | 
				
			||||||
 | 
					                if(client.stations){
 | 
				
			||||||
 | 
					                    for(const station of client.stations) {
 | 
				
			||||||
 | 
					                        if(!currentGuild) return;
 | 
				
			||||||
 | 
					                        if(currentGuild.statistics[station.name] && currentGuild.statistics[station.name]?.time && currentGuild.statistics[station.name].time != 0  && currentGuild.statistics[station.name].used && currentGuild.statistics[station.name].used != 0){
 | 
				
			||||||
 | 
					                            if(!statistics[station.name]){
 | 
				
			||||||
 | 
					                                statistics[station.name] = {
 | 
				
			||||||
 | 
					                                    time: 0,
 | 
				
			||||||
 | 
					                                    used: 0
 | 
				
			||||||
 | 
					                                };
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                            statistics[station.name] = {
 | 
				
			||||||
 | 
					                                time: statistics[station.name].time + currentGuild.statistics[station.name].time,
 | 
				
			||||||
 | 
					                                used: statistics[station.name].used + currentGuild.statistics[station.name].used
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            calculation = guilds.next();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let newData = {
 | 
				
			||||||
 | 
					            guild: {
 | 
				
			||||||
 | 
					                id: "global",
 | 
				
			||||||
 | 
					                name: "global"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            statistics: statistics,
 | 
				
			||||||
 | 
					            state: null
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        client.datastore.updateEntry(newData.guild, newData);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,120 +0,0 @@
 | 
				
			|||||||
const {
 | 
					 | 
				
			||||||
    createAudioPlayer,
 | 
					 | 
				
			||||||
    createAudioResource,
 | 
					 | 
				
			||||||
    AudioPlayerStatus,
 | 
					 | 
				
			||||||
    NoSubscriberBehavior
 | 
					 | 
				
			||||||
} = require("@discordjs/voice");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = class {
 | 
					 | 
				
			||||||
    constructor() {
 | 
					 | 
				
			||||||
        this.map = new Map();
 | 
					 | 
				
			||||||
        this.mode = null;
 | 
					 | 
				
			||||||
        this.logger = require("../funcs/logger.js");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    init(client){
 | 
					 | 
				
			||||||
        if(!client.config.streamerMode) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch(client.config.streamerMode){
 | 
					 | 
				
			||||||
            case "manual":
 | 
					 | 
				
			||||||
                this.mode = "manual";
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "auto":
 | 
					 | 
				
			||||||
                this.mode = "auto";
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                this.mode = "manual";
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(this.mode == "auto"){
 | 
					 | 
				
			||||||
            if(!client.stations) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            client.stations.forEach(station => {
 | 
					 | 
				
			||||||
                this.play(station);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    refresh(client){
 | 
					 | 
				
			||||||
        this.init(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let streamers = this.map.keys();
 | 
					 | 
				
			||||||
        streamers.forEach(streamer => {
 | 
					 | 
				
			||||||
            if(client.stations.findIndex(station => station.name == streamer) == -1){
 | 
					 | 
				
			||||||
                this.stop(streamer);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    play(station) {
 | 
					 | 
				
			||||||
        let audioPlayer = this.map.get(station.name);
 | 
					 | 
				
			||||||
        if(!audioPlayer) {
 | 
					 | 
				
			||||||
            if(this.mode == "auto"){
 | 
					 | 
				
			||||||
                audioPlayer = createAudioPlayer({
 | 
					 | 
				
			||||||
                    behaviors: {
 | 
					 | 
				
			||||||
                        noSubscriber: NoSubscriberBehavior.Play,
 | 
					 | 
				
			||||||
                        maxMissedFrames: Math.round(5000 / 20),
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(this.mode == "manual"){
 | 
					 | 
				
			||||||
                audioPlayer = createAudioPlayer({
 | 
					 | 
				
			||||||
                    behaviors: {
 | 
					 | 
				
			||||||
                        noSubscriber: NoSubscriberBehavior.Stop,
 | 
					 | 
				
			||||||
                        maxMissedFrames: Math.round(5000 / 20),
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            this.map.set(station.name, audioPlayer);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        const url = station.stream[station.stream.default];
 | 
					 | 
				
			||||||
        const resource = createAudioResource(url);
 | 
					 | 
				
			||||||
        audioPlayer.play(resource);
 | 
					 | 
				
			||||||
        audioPlayer
 | 
					 | 
				
			||||||
            .on('playing', () => {
 | 
					 | 
				
			||||||
	            this.logger('Streamer', station.name + " / " + "Playing");
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .on('idle', () => {
 | 
					 | 
				
			||||||
                this.logger('Streamer', station.name + " / " + "Idle");
 | 
					 | 
				
			||||||
                audioPlayer.removeAllListeners();
 | 
					 | 
				
			||||||
                if(this.mode == "manual" && audioPlayer.subscribers.length == 0) return;
 | 
					 | 
				
			||||||
                this.play(station);
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .on('paused', () => {
 | 
					 | 
				
			||||||
                this.logger('Streamer', station.name + " / " + "Paused");
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .on('buffering', () => {
 | 
					 | 
				
			||||||
                this.logger('Streamer', station.name + " / " + "Buffering");
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .on('autopaused', () => {
 | 
					 | 
				
			||||||
                this.logger('Streamer', station.name + " / " + "AutoPaused");
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .on('error', error => {
 | 
					 | 
				
			||||||
                this.logger('Streamer', station.name + " / " + "Error" + "\n" + error);
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        return audioPlayer;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    stop(station){
 | 
					 | 
				
			||||||
        let audioPlayer = this.map.get(station.name);
 | 
					 | 
				
			||||||
        if(audioPlayer){
 | 
					 | 
				
			||||||
            this.logger('Streamer', station.name + " / " + "Stop");
 | 
					 | 
				
			||||||
            audioPlayer.removeAllListeners();
 | 
					 | 
				
			||||||
            audioPlayer.stop();
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.map.delete(station.name);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    listen(station) {
 | 
					 | 
				
			||||||
        let audioPlayer = this.map.get(station.name);
 | 
					 | 
				
			||||||
        if(!audioPlayer || this.mode == "manual" && audioPlayer.subscribers.length == 0) audioPlayer = this.play(station);
 | 
					 | 
				
			||||||
        return audioPlayer;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    leave(client) {
 | 
					 | 
				
			||||||
        if(!client.stations) return;
 | 
					 | 
				
			||||||
        client.stations.forEach(station => {
 | 
					 | 
				
			||||||
            this.stop(station);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										116
									
								
								src/client/classes/Streamer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/client/classes/Streamer.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,116 @@
 | 
				
			|||||||
 | 
					import logger from "../funcs/logger";
 | 
				
			||||||
 | 
					import { AudioPlayer, AudioPlayerStatus, createAudioPlayer, createAudioResource, NoSubscriberBehavior } from "@discordjs/voice";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { station } from "./Stations";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default class Streamer {
 | 
				
			||||||
 | 
					    map: Map<string, AudioPlayer>;
 | 
				
			||||||
 | 
					    mode: "auto" | "manual";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        this.map = new Map();
 | 
				
			||||||
 | 
					        this.mode = "manual";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    init(client: RadioClient){
 | 
				
			||||||
 | 
					        if(!client.config.streamerMode) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch(client.config.streamerMode){
 | 
				
			||||||
 | 
					            case "manual":
 | 
				
			||||||
 | 
					                this.mode = "manual";
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "auto":
 | 
				
			||||||
 | 
					                this.mode = "auto";
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					                this.mode = "manual";
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(this.mode == "auto"){
 | 
				
			||||||
 | 
					            if(!client.stations) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for(const station of client.stations){
 | 
				
			||||||
 | 
					                this.play(station);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    refresh(client: RadioClient){
 | 
				
			||||||
 | 
					        this.init(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (const streamer of this.map.keys()){
 | 
				
			||||||
 | 
					            if(client.stations?.findIndex((station: station) => station.name == streamer) == -1){
 | 
				
			||||||
 | 
					                this.stop(streamer);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    play(station: station) {
 | 
				
			||||||
 | 
					        let audioPlayer = this.map.get(station.name);
 | 
				
			||||||
 | 
					        if(!audioPlayer) {
 | 
				
			||||||
 | 
					            if(this.mode == "auto"){
 | 
				
			||||||
 | 
					                audioPlayer = createAudioPlayer({
 | 
				
			||||||
 | 
					                    behaviors: {
 | 
				
			||||||
 | 
					                        noSubscriber: NoSubscriberBehavior.Play,
 | 
				
			||||||
 | 
					                        maxMissedFrames: Math.round(5000 / 20),
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                audioPlayer = createAudioPlayer({
 | 
				
			||||||
 | 
					                    behaviors: {
 | 
				
			||||||
 | 
					                        noSubscriber: NoSubscriberBehavior.Stop,
 | 
				
			||||||
 | 
					                        maxMissedFrames: Math.round(5000 / 20),
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            audioPlayer
 | 
				
			||||||
 | 
					                .on(AudioPlayerStatus.Playing, () => {
 | 
				
			||||||
 | 
					                    logger('Streamer', station.name + " / " + "Playing");
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .on(AudioPlayerStatus.Idle, () => {
 | 
				
			||||||
 | 
					                    logger('Streamer', station.name + " / " + "Idle");
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .on(AudioPlayerStatus.Paused, () => {
 | 
				
			||||||
 | 
					                    logger('Streamer', station.name + " / " + "Paused");
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .on(AudioPlayerStatus.Buffering, () => {
 | 
				
			||||||
 | 
					                    logger('Streamer', station.name + " / " + "Buffering");
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					                .on(AudioPlayerStatus.AutoPaused, () => {
 | 
				
			||||||
 | 
					                    logger('Streamer', station.name + " / " + "AutoPaused");
 | 
				
			||||||
 | 
					                })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            this.map.set(station.name, audioPlayer);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const url = station.stream[station.stream.default];
 | 
				
			||||||
 | 
					        const resource = createAudioResource(url);
 | 
				
			||||||
 | 
					        audioPlayer.play(resource);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return audioPlayer;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    stop(streamer: string){
 | 
				
			||||||
 | 
					        let audioPlayer = this.map.get(streamer);
 | 
				
			||||||
 | 
					        if(audioPlayer){
 | 
				
			||||||
 | 
					            logger('Streamer', streamer + " / " + "Stop");
 | 
				
			||||||
 | 
					            audioPlayer.removeAllListeners();
 | 
				
			||||||
 | 
					            audioPlayer.stop();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        this.map.delete(streamer);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    listen(station: station) {
 | 
				
			||||||
 | 
					        let audioPlayer = this.map.get(station.name);
 | 
				
			||||||
 | 
					        if(!audioPlayer) audioPlayer = this.play(station);
 | 
				
			||||||
 | 
					        return audioPlayer;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    leave(client: RadioClient) {
 | 
				
			||||||
 | 
					        if(!client.stations) return;
 | 
				
			||||||
 | 
					        for(const station of client.stations){
 | 
				
			||||||
 | 
					            this.stop(station.name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,83 +0,0 @@
 | 
				
			|||||||
const { SlashCommandBuilder } = require('@discordjs/builders');
 | 
					 | 
				
			||||||
const { REST } = require('@discordjs/rest');
 | 
					 | 
				
			||||||
const { Routes } = require('discord-api-types/v9');
 | 
					 | 
				
			||||||
const fs = require('fs');
 | 
					 | 
				
			||||||
const path = require ('path');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    async execute(client) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const commands = [];
 | 
					 | 
				
			||||||
        const commandFiles = fs.readdirSync(path.join("./src/client/commands")).filter(f => f.endsWith(".js"));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (const file of commandFiles) {
 | 
					 | 
				
			||||||
            const command = require(`./commands/${file}`);
 | 
					 | 
				
			||||||
            client.commands.set(command.name, command);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            command.data = new SlashCommandBuilder()
 | 
					 | 
				
			||||||
                .setName(command.name)
 | 
					 | 
				
			||||||
                .setDescription(command.description);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            command.data = command.data.toJSON();
 | 
					 | 
				
			||||||
            if(command.options) {
 | 
					 | 
				
			||||||
                command.options.forEach(function(option) {
 | 
					 | 
				
			||||||
                    if(option.type == "STRING") option.type = 3;
 | 
					 | 
				
			||||||
                    if(option.type == "NUMBER") option.type = 10;
 | 
					 | 
				
			||||||
                    command.data.options.push(option);
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            commands.push(command.data);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const rest = new REST({ version: '9' }).setToken(client.config.token);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        (async () => {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                client.funcs.logger('Slash Commands', 'Started refreshing application (/) commands.');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if(client.config.devMode){
 | 
					 | 
				
			||||||
                    await rest.put(
 | 
					 | 
				
			||||||
                        Routes.applicationCommands(client.user.id),
 | 
					 | 
				
			||||||
                        { body: [] },
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    let guilds = await client.guilds.fetch();
 | 
					 | 
				
			||||||
                    guilds.forEach(async guild => {
 | 
					 | 
				
			||||||
                        try {
 | 
					 | 
				
			||||||
                            await rest.put(
 | 
					 | 
				
			||||||
                                Routes.applicationGuildCommands(client.user.id, guild.id),
 | 
					 | 
				
			||||||
                                { body: commands }
 | 
					 | 
				
			||||||
                            );
 | 
					 | 
				
			||||||
                            client.funcs.logger('Slash Commands', 'Guild Applications – Successful' + "\n" + guild.id + " / " + guild.name);
 | 
					 | 
				
			||||||
                        } catch (DiscordAPIError) {
 | 
					 | 
				
			||||||
                            client.funcs.logger('Slash Commands', 'Guild Applications – Failed' + "\n" + guild.id + " / " + guild.name);
 | 
					 | 
				
			||||||
                            if(DiscordAPIError.name != "DiscordAPIError[50001]") console.error(DiscordAPIError.message + "\n\n");
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    await rest.put(
 | 
					 | 
				
			||||||
                        Routes.applicationCommands(client.user.id),
 | 
					 | 
				
			||||||
                        { body: commands }
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    let guilds = await client.guilds.fetch();
 | 
					 | 
				
			||||||
                    guilds.forEach(async guild => {
 | 
					 | 
				
			||||||
                        try {
 | 
					 | 
				
			||||||
                            await rest.put(
 | 
					 | 
				
			||||||
                                Routes.applicationGuildCommands(client.user.id, guild.id),
 | 
					 | 
				
			||||||
                                { body: [] }
 | 
					 | 
				
			||||||
                            );
 | 
					 | 
				
			||||||
                        } catch (DiscordAPIError) {
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                client.funcs.logger('Slash Commands', 'Successfully reloaded application (/) commands.' + "\n");
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                client.funcs.logger('Slash Commands', 'Reloading application (/) commands failed.' + "\n");
 | 
					 | 
				
			||||||
                console.error(error);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        })();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										72
									
								
								src/client/commands.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/client/commands.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,72 @@
 | 
				
			|||||||
 | 
					import { Snowflake } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../Client";
 | 
				
			||||||
 | 
					import bug from "./commands/bug";
 | 
				
			||||||
 | 
					import help from "./commands/help";
 | 
				
			||||||
 | 
					import invite from "./commands/invite";
 | 
				
			||||||
 | 
					import list from "./commands/list";
 | 
				
			||||||
 | 
					import maintenance from "./commands/maintenance";
 | 
				
			||||||
 | 
					import next from "./commands/next";
 | 
				
			||||||
 | 
					import nowplaying from "./commands/nowplaying";
 | 
				
			||||||
 | 
					import play from "./commands/play";
 | 
				
			||||||
 | 
					import prev from "./commands/prev";
 | 
				
			||||||
 | 
					import statistics from "./commands/statistics";
 | 
				
			||||||
 | 
					import status from "./commands/status";
 | 
				
			||||||
 | 
					import stop from "./commands/stop";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface command {
 | 
				
			||||||
 | 
					    name: string,
 | 
				
			||||||
 | 
					    description: string,
 | 
				
			||||||
 | 
					    category: string,
 | 
				
			||||||
 | 
					    options?: [],
 | 
				
			||||||
 | 
					    execute: Function
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function commands(client: RadioClient) {
 | 
				
			||||||
 | 
					    const commands : command[] = [ bug, help, invite, list, maintenance, next, nowplaying, play, prev, statistics, status, stop ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(const command of commands){
 | 
				
			||||||
 | 
					        client.commands.set(command.name, command);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!client.application) return;
 | 
				
			||||||
 | 
					    client.funcs.logger('Application Commands', 'Started refreshing application (/) commands.');
 | 
				
			||||||
 | 
					    if(client.config.devMode){
 | 
				
			||||||
 | 
					        client.application.commands.set([]);
 | 
				
			||||||
 | 
					        for(const command of commands){
 | 
				
			||||||
 | 
					            let guilds = await client.guilds.fetch();
 | 
				
			||||||
 | 
					            guilds.forEach(async (guild: { id: Snowflake; name: string; }) => {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    if(!client.application) return;
 | 
				
			||||||
 | 
					                    await client.application.commands.create({
 | 
				
			||||||
 | 
					                        name: command.name,
 | 
				
			||||||
 | 
					                        description: command.description,
 | 
				
			||||||
 | 
					                        options: command.options || []
 | 
				
			||||||
 | 
					                    }, guild.id);
 | 
				
			||||||
 | 
					                    client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") \n" + 'Command: ' + command.name);
 | 
				
			||||||
 | 
					                } catch(DiscordAPIError) {
 | 
				
			||||||
 | 
					                    client.funcs.logger('Application Commands', 'Guild: ' + guild.id + " (" + guild.name + ") [FAILED] \n" + 'Command: ' + command.name);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        for(const command of commands){
 | 
				
			||||||
 | 
					            await client.application.commands.create({
 | 
				
			||||||
 | 
					                name: command.name,
 | 
				
			||||||
 | 
					                description: command.description,
 | 
				
			||||||
 | 
					                options: command.options || []
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            client.funcs.logger('Application Commands', 'Command: ' + command.name);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let guilds = await client.guilds.fetch();
 | 
				
			||||||
 | 
					        guilds.forEach(async (guild: { id: Snowflake; }) => {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                if(!client.application) return;
 | 
				
			||||||
 | 
					                await client.application.commands.set([], guild.id);
 | 
				
			||||||
 | 
					            } catch (DiscordAPIError){
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    client.funcs.logger('Application Commands', 'Successfully reloaded application (/) commands.' + "\n");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,29 +0,0 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'bug',
 | 
					 | 
				
			||||||
    description: 'Report a bug',
 | 
					 | 
				
			||||||
    category: 'info',
 | 
					 | 
				
			||||||
    async execute(interaction, client) {
 | 
					 | 
				
			||||||
        let message = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        message.bugTitle = client.messages.bugTitle.replace("%client.user.username%", client.user.username);
 | 
					 | 
				
			||||||
        message.bugDescription = client.messages.bugDescription.replace("%client.config.supportGuild%", client.config.supportGuild);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const embed = new EmbedBuilder()
 | 
					 | 
				
			||||||
            .setTitle(message.bugTitle)
 | 
					 | 
				
			||||||
            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, ''))
 | 
					 | 
				
			||||||
            .setColor(client.config.embedColor)
 | 
					 | 
				
			||||||
            .setDescription(message.bugDescription)
 | 
					 | 
				
			||||||
            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					 | 
				
			||||||
            .setFooter({
 | 
					 | 
				
			||||||
                text: client.messages.footerText,
 | 
					 | 
				
			||||||
                iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            embeds: [embed],
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										34
									
								
								src/client/commands/bug.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/client/commands/bug.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: 'bug',
 | 
				
			||||||
 | 
					    description: 'Report a bug',
 | 
				
			||||||
 | 
					    category: 'info',
 | 
				
			||||||
 | 
					    async execute(interaction: ChatInputCommandInteraction, client: RadioClient) {
 | 
				
			||||||
 | 
					        if(!client.user) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const embed = new EmbedBuilder()
 | 
				
			||||||
 | 
					            .setTitle(client.messages.replace(client.messages.bugTitle, {
 | 
				
			||||||
 | 
					                "%client.user.username%": client.user.username
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, ''))
 | 
				
			||||||
 | 
					            .setColor(client.config.embedColor)
 | 
				
			||||||
 | 
					            .setDescription(client.messages.replace(client.messages.bugDescription, {
 | 
				
			||||||
 | 
					                    "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
 | 
					            .setFooter({
 | 
				
			||||||
 | 
					                text: client.messages.footerText,
 | 
				
			||||||
 | 
					                iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        interaction.reply({
 | 
				
			||||||
 | 
					            embeds: [embed],
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,38 +0,0 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'help',
 | 
					 | 
				
			||||||
    description: 'Get help using bot',
 | 
					 | 
				
			||||||
    category: 'info',
 | 
					 | 
				
			||||||
    execute(interaction, client) {
 | 
					 | 
				
			||||||
        let message = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const categories = [];
 | 
					 | 
				
			||||||
        for (let i = 0; i < client.commands.size; i++) {
 | 
					 | 
				
			||||||
            if (!categories.includes([...client.commands.values()][i].category)) categories.push([...client.commands.values()][i].category);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        let commands = '';
 | 
					 | 
				
			||||||
        for (let i = 0; i < categories.length; i++) {
 | 
					 | 
				
			||||||
            commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i] && !x.omitFromHelp).map(x => `\`${x.name}\``).join(', ')}\n`;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        message.helpTitle = client.messages.helpTitle.replace("%client.user.username%", client.user.username);
 | 
					 | 
				
			||||||
        message.helpDescription = client.messages.helpDescription.replace("%commands%", commands);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const embed = new EmbedBuilder()
 | 
					 | 
				
			||||||
            .setTitle(message.helpTitle)
 | 
					 | 
				
			||||||
            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, ''))
 | 
					 | 
				
			||||||
            .setColor(client.config.embedColor)
 | 
					 | 
				
			||||||
            .setDescription(message.helpDescription)
 | 
					 | 
				
			||||||
            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					 | 
				
			||||||
            .setFooter({
 | 
					 | 
				
			||||||
                text: client.messages.footerText,
 | 
					 | 
				
			||||||
                iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            embeds: [embed],
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										45
									
								
								src/client/commands/help.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/client/commands/help.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { command } from "../commands";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: 'help',
 | 
				
			||||||
 | 
					    description: 'Get help using bot',
 | 
				
			||||||
 | 
					    category: 'info',
 | 
				
			||||||
 | 
					    execute(interaction: ChatInputCommandInteraction, client: RadioClient) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!client.user) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const categories: string[] = [];
 | 
				
			||||||
 | 
					        for (let i = 0; i < client.commands.size; i++) {
 | 
				
			||||||
 | 
					            if (!categories.includes([...client.commands.values()][i].category)) categories.push([...client.commands.values()][i].category);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let commands = '';
 | 
				
			||||||
 | 
					        for (let i = 0; i < categories.length; i++) {
 | 
				
			||||||
 | 
					            commands += `**» ${categories[i].toUpperCase()}**\n${client.commands.filter(x => x.category === categories[i]).map((x: command) => `\`${x.name}\``).join(', ')}\n`;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const embed = new EmbedBuilder()
 | 
				
			||||||
 | 
					            .setTitle(client.messages.replace(client.messages.helpTitle, {
 | 
				
			||||||
 | 
					                "%client.user.username%": client.user.username
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, ''))
 | 
				
			||||||
 | 
					            .setColor(client.config.embedColor)
 | 
				
			||||||
 | 
					            .setDescription(client.messages.replace(client.messages.helpDescription, {
 | 
				
			||||||
 | 
					                "%commands%": commands
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
 | 
					            .setFooter({
 | 
				
			||||||
 | 
					                text: client.messages.footerText,
 | 
				
			||||||
 | 
					                iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        interaction.reply({
 | 
				
			||||||
 | 
					            embeds: [embed],
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,20 +1,27 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					export default {
 | 
				
			||||||
    name: 'invite',
 | 
					    name: 'invite',
 | 
				
			||||||
    description: 'Invite Bot',
 | 
					    description: 'Invite Bot',
 | 
				
			||||||
    category: 'info',
 | 
					    category: 'info',
 | 
				
			||||||
    execute(interaction, client) {
 | 
					    execute(interaction: ChatInputCommandInteraction, client: RadioClient) {
 | 
				
			||||||
        let message = {};
 | 
					
 | 
				
			||||||
        message.inviteTitle = client.messages.inviteTitle.replace("%client.user.username%", client.user.username);
 | 
					        if(!client.user) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const embed = new EmbedBuilder()
 | 
					        const embed = new EmbedBuilder()
 | 
				
			||||||
            .setTitle(message.inviteTitle)
 | 
					            .setTitle(client.messages.replace(client.messages.inviteTitle, {
 | 
				
			||||||
 | 
					                "%client.user.username%": client.user.username
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
            .setColor(client.config.embedColor)
 | 
					            .setColor(client.config.embedColor)
 | 
				
			||||||
            .setURL("https://discord.com/api/oauth2/authorize?client_id=" + client.user.id + "&permissions=2184465408&scope=applications.commands%20bot") //View Channels, Send Messages, Embed Links, Use External Emojis, Use Slash Commands, Connect, Speak, Use Voice Activity
 | 
					            .setURL("https://discord.com/api/oauth2/authorize?client_id=" + client.user.id + "&permissions=2184465408&scope=applications.commands%20bot") //View Channels, Send Messages, Embed Links, Use External Emojis, Use Slash Commands, Connect, Speak, Use Voice Activity
 | 
				
			||||||
            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
            .setFooter({
 | 
					            .setFooter({
 | 
				
			||||||
                text: client.messages.footerText,
 | 
					                text: client.messages.footerText,
 | 
				
			||||||
                iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					                iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        interaction.reply({
 | 
					        interaction.reply({
 | 
				
			||||||
@@ -1,26 +1,35 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { station } from "../classes/Stations";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					export default {
 | 
				
			||||||
    name: 'list',
 | 
					    name: 'list',
 | 
				
			||||||
    description: 'List radio stations',
 | 
					    description: 'List radio stations',
 | 
				
			||||||
    category: 'radio',
 | 
					    category: 'radio',
 | 
				
			||||||
    execute(interaction, client) {
 | 
					    execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) {
 | 
				
			||||||
        let message = {};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!client.stations) {
 | 
					        if(client.config.maintenanceMode){
 | 
				
			||||||
            message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild);
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					            return interaction.reply({
 | 
				
			||||||
                content: client.messageEmojis["error"] + message.errorToGetPlaylist,
 | 
					                content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
                ephemeral: true
 | 
					                ephemeral: true
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const radio = client.radio.get(interaction.guild.id);
 | 
					        if(!client.stations) {
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, {
 | 
				
			||||||
 | 
					                    "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(radio && !client.config.maintenanceMode){
 | 
					        if(radio && !client.config.maintenanceMode){
 | 
				
			||||||
            client.funcs.listStations(client, interaction);
 | 
					            client.funcs.listStations(client, interaction);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            let stations = `${client.stations.map(s => `**#** ${s.name}`).join('\n')}`
 | 
					            let stations = `${client.stations.map((s: station) => `**#** ${s.name}`).join('\n')}`
 | 
				
			||||||
            const hashs = stations.split('**#**').length;
 | 
					            const hashs = stations.split('**#**').length;
 | 
				
			||||||
            for (let i = 0; i < hashs; i++) {
 | 
					            for (let i = 0; i < hashs; i++) {
 | 
				
			||||||
                stations = stations.replace('**#**', `**${i + 1}.**`);
 | 
					                stations = stations.replace('**#**', `**${i + 1}.**`);
 | 
				
			||||||
@@ -28,13 +37,13 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            let embed = new EmbedBuilder()
 | 
					            let embed = new EmbedBuilder()
 | 
				
			||||||
                .setTitle(client.messages.listTitle)
 | 
					                .setTitle(client.messages.listTitle)
 | 
				
			||||||
                .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["list"].replace(/[^0-9]+/g, ''))
 | 
					                .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["list"].replace(/[^0-9]+/g, ''))
 | 
				
			||||||
                .setColor(client.config.embedColor)
 | 
					                .setColor(client.config.embedColor)
 | 
				
			||||||
                .setDescription(stations)
 | 
					                .setDescription(stations)
 | 
				
			||||||
                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
                .setFooter({
 | 
					                .setFooter({
 | 
				
			||||||
                    text: client.messages.footerText,
 | 
					                    text: client.messages.footerText,
 | 
				
			||||||
                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            interaction.reply({
 | 
					            interaction.reply({
 | 
				
			||||||
@@ -1,200 +0,0 @@
 | 
				
			|||||||
import { ActionRowBuilder, EmbedBuilder, StringSelectMenuBuilder } from "discord.js";
 | 
					 | 
				
			||||||
import Streamer from "../classes/Streamer.js";
 | 
					 | 
				
			||||||
const _importDynamic = new Function('modulePath', 'return import(modulePath)');
 | 
					 | 
				
			||||||
const fetch = (...args) => _importDynamic('node-fetch').then(({default: fetch}) => fetch(...args));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'maintenance',
 | 
					 | 
				
			||||||
    description: 'Bot Maintenance',
 | 
					 | 
				
			||||||
    category: 'info',
 | 
					 | 
				
			||||||
    async execute(interaction, client) {
 | 
					 | 
				
			||||||
        let message = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(!client.funcs.isDev(client.config.devId, interaction.user.id)) return interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + client.messages.notAllowed,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        let action = interaction.options?.getNumber("action") ?? interaction.values?.[0];
 | 
					 | 
				
			||||||
        const options = new Array(
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "🌀",
 | 
					 | 
				
			||||||
                label: "Restart Bot",
 | 
					 | 
				
			||||||
                value: "0"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "<:RadioXStop:688541155377414168>",
 | 
					 | 
				
			||||||
                label: "Save Radios",
 | 
					 | 
				
			||||||
                value: "4"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "<:RadioXPlay:688541155712827458>",
 | 
					 | 
				
			||||||
                label: "Restore Radios",
 | 
					 | 
				
			||||||
                value: "5"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "#️⃣",
 | 
					 | 
				
			||||||
                label: "Reload Commands",
 | 
					 | 
				
			||||||
                value: "6"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "<:RadioXList:688541155519889482>",
 | 
					 | 
				
			||||||
                label: "Reload Stations",
 | 
					 | 
				
			||||||
                value: "7"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "<:dnd:746069698139127831>",
 | 
					 | 
				
			||||||
                label: "Enable Maintenance Mode",
 | 
					 | 
				
			||||||
                value: "8"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "<:online:746069731836035098>",
 | 
					 | 
				
			||||||
                label: "Disable Maintenance Mode",
 | 
					 | 
				
			||||||
                value: "9"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "💤",
 | 
					 | 
				
			||||||
                label: "Streamer Mode – Manual",
 | 
					 | 
				
			||||||
                value: "10"
 | 
					 | 
				
			||||||
            },
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                emoji: "📡",
 | 
					 | 
				
			||||||
                label: "Streamer Mode – Auto",
 | 
					 | 
				
			||||||
                value: "11"
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const menu = new ActionRowBuilder()
 | 
					 | 
				
			||||||
        .addComponents(
 | 
					 | 
				
			||||||
            new StringSelectMenuBuilder()
 | 
					 | 
				
			||||||
                .setCustomId('maintenance')
 | 
					 | 
				
			||||||
                .setPlaceholder('Select action')
 | 
					 | 
				
			||||||
                .addOptions(options)
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(!action){
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: "**" + client.messages.maintenanceTitle + "**",
 | 
					 | 
				
			||||||
                components: [menu],
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.funcs.logger('Maintenance', options.find(option => option.value == action).label);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const embed = new EmbedBuilder()
 | 
					 | 
				
			||||||
            .setTitle(client.messages.maintenanceTitle)
 | 
					 | 
				
			||||||
            .setColor(client.config.embedColor)
 | 
					 | 
				
			||||||
            .setDescription(options.find(option => option.value == action).label)
 | 
					 | 
				
			||||||
            .setFooter({
 | 
					 | 
				
			||||||
                text: client.messages.footerText,
 | 
					 | 
				
			||||||
                iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            embeds: [embed],
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let guilds = await client.guilds.fetch();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        switch(action){
 | 
					 | 
				
			||||||
            case "0":
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
                process.emit('SIGINT');
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "4":
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
                client.user.setStatus('idle');
 | 
					 | 
				
			||||||
                client.radio.save(client);
 | 
					 | 
				
			||||||
                client.user.setStatus('online');
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "5":
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
                client.user.setStatus('idle');
 | 
					 | 
				
			||||||
                client.radio.restore(client, guilds);
 | 
					 | 
				
			||||||
                client.user.setStatus('online');
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "6":
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
                client.user.setStatus('idle');
 | 
					 | 
				
			||||||
                require(`../commands.js`).execute(client);
 | 
					 | 
				
			||||||
                client.user.setStatus('online');
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "7":
 | 
					 | 
				
			||||||
                try {
 | 
					 | 
				
			||||||
                    client.stations.fetch({
 | 
					 | 
				
			||||||
                        url: client.config.stationslistUrl
 | 
					 | 
				
			||||||
                    });
 | 
					 | 
				
			||||||
                    client.streamer.refresh(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                } catch (error) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "8":
 | 
					 | 
				
			||||||
                client.user.setStatus('dnd');
 | 
					 | 
				
			||||||
                client.funcs.logger("Maintenance Mode", "Enabled");
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "9":
 | 
					 | 
				
			||||||
                client.user.setStatus('online');
 | 
					 | 
				
			||||||
                client.funcs.logger("Maintenance Mode", "Disabled");
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "10":
 | 
					 | 
				
			||||||
                client.config.streamerMode = "manual";
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                client.user.setStatus('idle');
 | 
					 | 
				
			||||||
                client.radio.save(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                setInterval(() => {
 | 
					 | 
				
			||||||
                    if(client.radio.size == 0 && client.config.streamerMode == "manual" && client.config.maintenanceMode){
 | 
					 | 
				
			||||||
                        client.streamer.leave(client);
 | 
					 | 
				
			||||||
                        client.streamer = new Streamer();
 | 
					 | 
				
			||||||
                        client.streamer.init(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        client.radio.restore(client, guilds);
 | 
					 | 
				
			||||||
                        client.user.setStatus('online');
 | 
					 | 
				
			||||||
                        client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if(!client.config.maintenanceMode){
 | 
					 | 
				
			||||||
                        clearInterval();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }, 500);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            case "11":
 | 
					 | 
				
			||||||
                client.config.streamerMode = "auto";
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                client.user.setStatus('idle');
 | 
					 | 
				
			||||||
                client.radio.save(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                setInterval(() => {
 | 
					 | 
				
			||||||
                    if(client.radio.size == 0 && client.config.streamerMode == "auto" && client.config.maintenanceMode){
 | 
					 | 
				
			||||||
                        client.streamer.leave(client);
 | 
					 | 
				
			||||||
                        client.streamer = new Streamer();
 | 
					 | 
				
			||||||
                        client.streamer.init(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        client.radio.restore(client, guilds);
 | 
					 | 
				
			||||||
                        client.user.setStatus('online');
 | 
					 | 
				
			||||||
                        client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if(!client.config.maintenanceMode){
 | 
					 | 
				
			||||||
                        clearInterval();
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }, 500);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										232
									
								
								src/client/commands/maintenance.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								src/client/commands/maintenance.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,232 @@
 | 
				
			|||||||
 | 
					import { ActionRowBuilder, APISelectMenuOption, ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import Streamer from "../classes/Streamer";
 | 
				
			||||||
 | 
					import commands from "../commands";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: 'maintenance',
 | 
				
			||||||
 | 
					    description: 'Bot Maintenance',
 | 
				
			||||||
 | 
					    category: 'info',
 | 
				
			||||||
 | 
					    async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!client.funcs.isDev(client.config.devIDs, interaction.user.id)) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.notAllowed,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let action : number | string | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(interaction.isChatInputCommand()){
 | 
				
			||||||
 | 
					            action = interaction.options?.getNumber("action");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(interaction.isStringSelectMenu()){
 | 
				
			||||||
 | 
					            action = interaction.values?.[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const options: APISelectMenuOption[] = new Array(
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    "name": "🌀",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Restart Bot",
 | 
				
			||||||
 | 
					                value: "0"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    id: "688541155377414168",
 | 
				
			||||||
 | 
					                    name: "RadioXStop",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Save Radios",
 | 
				
			||||||
 | 
					                value: "4"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    id: "688541155712827458",
 | 
				
			||||||
 | 
					                    name: "RadioXPlay",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Restore Radios",
 | 
				
			||||||
 | 
					                value: "5"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    name: "#️⃣",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Reload Commands",
 | 
				
			||||||
 | 
					                value: "6"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    id: "688541155519889482",
 | 
				
			||||||
 | 
					                    name: "RadioXList",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Reload Stations",
 | 
				
			||||||
 | 
					                value: "7"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    id: "746069698139127831",
 | 
				
			||||||
 | 
					                    name: "dnd",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Enable Maintenance Mode",
 | 
				
			||||||
 | 
					                value: "8"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    id: "746069731836035098",
 | 
				
			||||||
 | 
					                    name: "online",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Disable Maintenance Mode",
 | 
				
			||||||
 | 
					                value: "9"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    name: "💤",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Streamer Mode - Manual",
 | 
				
			||||||
 | 
					                value: "10"
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                emoji: {
 | 
				
			||||||
 | 
					                    name: "📡",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                label: "Streamer Mode - Auto",
 | 
				
			||||||
 | 
					                value: "11"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const menu = new ActionRowBuilder<StringSelectMenuBuilder>()
 | 
				
			||||||
 | 
					            .addComponents(
 | 
				
			||||||
 | 
					                new StringSelectMenuBuilder()
 | 
				
			||||||
 | 
					                    .setCustomId('maintenance')
 | 
				
			||||||
 | 
					                    .setPlaceholder('Select action')
 | 
				
			||||||
 | 
					                    .addOptions(options)
 | 
				
			||||||
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!action){
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: "**" + client.messages.maintenanceTitle + "**",
 | 
				
			||||||
 | 
					                components: [menu],
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        client.funcs.logger('Maintenance', options.find((option: APISelectMenuOption) => option.value == action)?.label);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const embed = new EmbedBuilder()
 | 
				
			||||||
 | 
					            .setTitle(client.messages.maintenanceTitle)
 | 
				
			||||||
 | 
					            .setColor(client.config.embedColor)
 | 
				
			||||||
 | 
					            .setDescription(options.find((option: APISelectMenuOption) => option.value == action)?.label || "-")
 | 
				
			||||||
 | 
					            .setFooter({
 | 
				
			||||||
 | 
					                text: client.messages.footerText,
 | 
				
			||||||
 | 
					                iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        interaction.reply({
 | 
				
			||||||
 | 
					            embeds: [embed],
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let guilds = await client.guilds.fetch();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        switch(action){
 | 
				
			||||||
 | 
					            case "0":
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					                process.emit('SIGINT');
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "4":
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					                client.user?.setStatus('idle');
 | 
				
			||||||
 | 
					                client.radio?.save(client);
 | 
				
			||||||
 | 
					                client.user?.setStatus('online');
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "5":
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					                client.user?.setStatus('idle');
 | 
				
			||||||
 | 
					                client.radio?.restore(client, guilds);
 | 
				
			||||||
 | 
					                client.user?.setStatus('online');
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "6":
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					                client.user?.setStatus('idle');
 | 
				
			||||||
 | 
					                commands(client);
 | 
				
			||||||
 | 
					                client.user?.setStatus('online');
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "7":
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    client.stations?.fetch({
 | 
				
			||||||
 | 
					                        url: client.config.stationslistUrl
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                    client.streamer?.refresh(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                } catch (error) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "8":
 | 
				
			||||||
 | 
					                client.user?.setStatus('dnd');
 | 
				
			||||||
 | 
					                client.funcs.logger("Maintenance Mode", "Enabled");
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "9":
 | 
				
			||||||
 | 
					                client.user?.setStatus('online');
 | 
				
			||||||
 | 
					                client.funcs.logger("Maintenance Mode", "Disabled");
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "10":
 | 
				
			||||||
 | 
					                client.config.streamerMode = "manual";
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                client.user?.setStatus('idle');
 | 
				
			||||||
 | 
					                client.radio?.save(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                setInterval(() => {
 | 
				
			||||||
 | 
					                    if(client.radio?.size == 0 && client.config.streamerMode == "manual" && client.config.maintenanceMode){
 | 
				
			||||||
 | 
					                        client.streamer?.leave(client);
 | 
				
			||||||
 | 
					                        client.streamer = new Streamer();
 | 
				
			||||||
 | 
					                        client.streamer.init(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        client.radio?.restore(client, guilds);
 | 
				
			||||||
 | 
					                        client.user?.setStatus('online');
 | 
				
			||||||
 | 
					                        client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(!client.config.maintenanceMode){
 | 
				
			||||||
 | 
					                        clearInterval(undefined);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }, 500);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            case "11":
 | 
				
			||||||
 | 
					                client.config.streamerMode = "auto";
 | 
				
			||||||
 | 
					                client.config.maintenanceMode = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                client.user?.setStatus('idle');
 | 
				
			||||||
 | 
					                client.radio?.save(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                setInterval(() => {
 | 
				
			||||||
 | 
					                    if(client.radio?.size == 0 && client.config.streamerMode == "auto" && client.config.maintenanceMode){
 | 
				
			||||||
 | 
					                        client.streamer?.leave(client);
 | 
				
			||||||
 | 
					                        client.streamer = new Streamer();
 | 
				
			||||||
 | 
					                        client.streamer.init(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        client.radio.restore(client, guilds);
 | 
				
			||||||
 | 
					                        client.user?.setStatus('online');
 | 
				
			||||||
 | 
					                        client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    if(!client.config.maintenanceMode){
 | 
				
			||||||
 | 
					                        clearInterval(undefined);
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }, 500);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            default:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'next',
 | 
					 | 
				
			||||||
    description: 'Next Station',
 | 
					 | 
				
			||||||
    category: 'radio',
 | 
					 | 
				
			||||||
    async execute(interaction, client, command) {
 | 
					 | 
				
			||||||
        if (client.funcs.check(client, interaction, command)) {
 | 
					 | 
				
			||||||
            const radio = client.radio.get(interaction.guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let index = client.stations.findIndex(station => station.name == radio.station.name) + 1;
 | 
					 | 
				
			||||||
            if(index == client.stations.length) index = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let station = client.stations[index];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(!station) return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.noSearchResults,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            client.statistics.update(client, interaction.guild, radio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let date = new Date();
 | 
					 | 
				
			||||||
            radio.station = station;
 | 
					 | 
				
			||||||
            radio.textChannel = interaction.channel;
 | 
					 | 
				
			||||||
            radio.startTime = date.getTime();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(interaction.isChatInputCommand()) {
 | 
					 | 
				
			||||||
                client.funcs.play(client, interaction, interaction.guild, station);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(interaction.isButton()) {
 | 
					 | 
				
			||||||
                interaction.deferUpdate();
 | 
					 | 
				
			||||||
                client.funcs.play(client, null, interaction.guild, station);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										56
									
								
								src/client/commands/next.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/client/commands/next.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { station } from "../classes/Stations"
 | 
				
			||||||
 | 
					import { command } from "../commands";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: 'next',
 | 
				
			||||||
 | 
					    description: 'Next Station',
 | 
				
			||||||
 | 
					    category: 'radio',
 | 
				
			||||||
 | 
					    async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) {
 | 
				
			||||||
 | 
					        if (client.funcs.check(client, interaction, command)) {
 | 
				
			||||||
 | 
					            const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(client.config.maintenanceMode){
 | 
				
			||||||
 | 
					                return interaction.reply({
 | 
				
			||||||
 | 
					                    content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					                    ephemeral: true
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!client.stations) {
 | 
				
			||||||
 | 
					                return interaction.reply({
 | 
				
			||||||
 | 
					                    content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, {
 | 
				
			||||||
 | 
					                        "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    ephemeral: true
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let index: number = client.stations.findIndex((station: station) => station.name == radio.station.name) + 1;
 | 
				
			||||||
 | 
					            if(index == client.stations?.length) index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let station = client.stations[index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!station) return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.noSearchResults,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            client.statistics?.update(client, interaction.guild, radio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let date = new Date();
 | 
				
			||||||
 | 
					            radio.station = station;
 | 
				
			||||||
 | 
					            radio.textChannel = interaction.channel;
 | 
				
			||||||
 | 
					            radio.startTime = date.getTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(interaction.isChatInputCommand()) {
 | 
				
			||||||
 | 
					                client.funcs.play(client, interaction, interaction.guild, station);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if(interaction.isButton()) {
 | 
				
			||||||
 | 
					                interaction.deferUpdate();
 | 
				
			||||||
 | 
					                client.funcs.play(client, null, interaction.guild, station);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,38 +0,0 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'nowplaying',
 | 
					 | 
				
			||||||
    description: 'Current Radio Station',
 | 
					 | 
				
			||||||
    category: 'radio',
 | 
					 | 
				
			||||||
    async execute(interaction, client, command) {
 | 
					 | 
				
			||||||
        if (client.funcs.check(client, interaction, command)) {
 | 
					 | 
				
			||||||
            let message = {};
 | 
					 | 
				
			||||||
            const radio = client.radio.get(interaction.guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let date = new Date();
 | 
					 | 
				
			||||||
            radio.currentTime = date.getTime();
 | 
					 | 
				
			||||||
            radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime);
 | 
					 | 
				
			||||||
            const completed = (radio.playTime);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name);
 | 
					 | 
				
			||||||
            message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%" + "\n", radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "");
 | 
					 | 
				
			||||||
            message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", client.funcs.msToTime(completed));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const embed = new EmbedBuilder()
 | 
					 | 
				
			||||||
                .setTitle(client.messages.nowplayingTitle)
 | 
					 | 
				
			||||||
                .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, '')))
 | 
					 | 
				
			||||||
                .setColor(client.config.embedColor)
 | 
					 | 
				
			||||||
                .setDescription(message.nowplayingDescription)
 | 
					 | 
				
			||||||
                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					 | 
				
			||||||
                .setFooter({
 | 
					 | 
				
			||||||
                    text: client.messages.footerText,
 | 
					 | 
				
			||||||
                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            interaction.reply({
 | 
					 | 
				
			||||||
                embeds: [embed],
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										40
									
								
								src/client/commands/nowplaying.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/client/commands/nowplaying.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,40 @@
 | 
				
			|||||||
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { command } from "../commands";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: 'nowplaying',
 | 
				
			||||||
 | 
					    description: 'Current Radio Station',
 | 
				
			||||||
 | 
					    category: 'radio',
 | 
				
			||||||
 | 
					    async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) {
 | 
				
			||||||
 | 
					        if(client.funcs.check(client, interaction, command)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let date = new Date();
 | 
				
			||||||
 | 
					            radio.currentTime = date.getTime();
 | 
				
			||||||
 | 
					            radio.playTime = parseInt(radio.currentTime)-parseInt(radio.startTime);
 | 
				
			||||||
 | 
					            const completed = (radio.playTime);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const embed = new EmbedBuilder()
 | 
				
			||||||
 | 
					                .setTitle(client.messages.nowplayingTitle)
 | 
				
			||||||
 | 
					                .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, '')))
 | 
				
			||||||
 | 
					                .setColor(client.config.embedColor)
 | 
				
			||||||
 | 
					                .setDescription(client.messages.replace(client.messages.nowplayingDescription, {
 | 
				
			||||||
 | 
					                    "%radio.station.name%": radio.station.name,
 | 
				
			||||||
 | 
					                    "%radio.station.owner%\n": radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "",
 | 
				
			||||||
 | 
					                    "%client.funcs.msToTime(completed)%": client.funcs.msToTime(completed)
 | 
				
			||||||
 | 
					                }))
 | 
				
			||||||
 | 
					                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
 | 
					                .setFooter({
 | 
				
			||||||
 | 
					                    text: client.messages.footerText,
 | 
				
			||||||
 | 
					                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            interaction.reply({
 | 
				
			||||||
 | 
					                embeds: [embed],
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,148 +0,0 @@
 | 
				
			|||||||
import { PermissionFlagsBits } from "discord.js";
 | 
					 | 
				
			||||||
const {
 | 
					 | 
				
			||||||
    getVoiceConnection,
 | 
					 | 
				
			||||||
    joinVoiceChannel
 | 
					 | 
				
			||||||
} = require("@discordjs/voice");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: "play",
 | 
					 | 
				
			||||||
    usage: "<song name>",
 | 
					 | 
				
			||||||
    description: "Play radio",
 | 
					 | 
				
			||||||
    options: [
 | 
					 | 
				
			||||||
        { type: "STRING", name: "query", description: "Select station", required: false}
 | 
					 | 
				
			||||||
    ],
 | 
					 | 
				
			||||||
    category: "radio",
 | 
					 | 
				
			||||||
    async execute(interaction, client) {
 | 
					 | 
				
			||||||
        let message = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(client.config.maintenanceMode){
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.maintenance,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(!client.stations) {
 | 
					 | 
				
			||||||
            message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild);
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + message.errorToGetPlaylist,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let query = interaction.options?.getString("query") ?? interaction.values?.[0];
 | 
					 | 
				
			||||||
        if(!query){
 | 
					 | 
				
			||||||
            return client.funcs.listStations(client, interaction);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        let url = query ? query.replace(/<(.+)>/g, "$1") : "";
 | 
					 | 
				
			||||||
        const radio = client.radio.get(interaction.guild.id);
 | 
					 | 
				
			||||||
        const voiceChannel = interaction.member.voice.channel;
 | 
					 | 
				
			||||||
        if (!voiceChannel) return interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + client.messages.noVoiceChannel,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        if (radio) {
 | 
					 | 
				
			||||||
            if (voiceChannel !== radio.voiceChannel) return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.wrongVoiceChannel,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (!query) return interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messages.noQuery,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        const permissions = voiceChannel.permissionsFor(interaction.client.user);
 | 
					 | 
				
			||||||
        if (!permissions.has(PermissionFlagsBits.Connect)) {
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.noPermsConnect,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if (!permissions.has(PermissionFlagsBits.Speak)) {
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.noPermsSpeak,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        let station;
 | 
					 | 
				
			||||||
        const number = parseInt(query - 1);
 | 
					 | 
				
			||||||
        if (url.startsWith("http")) {
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.errorStationURL,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        } else if (!isNaN(number)) {
 | 
					 | 
				
			||||||
            if (number > client.stations.length - 1) {
 | 
					 | 
				
			||||||
                return interaction.reply({
 | 
					 | 
				
			||||||
                    content: client.messageEmojis["error"] + client.messages.wrongStationNumber,
 | 
					 | 
				
			||||||
                    ephemeral: true
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                station = client.stations[number];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            if (query.length < 3) return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.tooShortSearch,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let type = "";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(interaction.values?.[0]){
 | 
					 | 
				
			||||||
                type = "direct";
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                type = "text";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const sstation = await client.stations.search(query, type);
 | 
					 | 
				
			||||||
            if (!sstation) return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.noSearchResults,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            station = sstation;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (radio) {
 | 
					 | 
				
			||||||
            client.statistics.update(client, interaction.guild, radio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let date = new Date();
 | 
					 | 
				
			||||||
            radio.station = station;
 | 
					 | 
				
			||||||
            radio.textChannel = interaction.channel;
 | 
					 | 
				
			||||||
            radio.startTime = date.getTime();
 | 
					 | 
				
			||||||
            client.funcs.play(client, interaction, interaction.guild, station);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const construct = {
 | 
					 | 
				
			||||||
            textChannel: interaction.channel,
 | 
					 | 
				
			||||||
            voiceChannel: voiceChannel,
 | 
					 | 
				
			||||||
            connection: null,
 | 
					 | 
				
			||||||
            message: null,
 | 
					 | 
				
			||||||
            station: station
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        client.radio.set(interaction.guild.id, construct);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            const connection =
 | 
					 | 
				
			||||||
                getVoiceConnection(voiceChannel.guild.id) ??
 | 
					 | 
				
			||||||
                joinVoiceChannel({
 | 
					 | 
				
			||||||
                    channelId: voiceChannel.id,
 | 
					 | 
				
			||||||
                    guildId: voiceChannel.guild.id,
 | 
					 | 
				
			||||||
                    adapterCreator: voiceChannel.guild.voiceAdapterCreator
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            construct.connection = connection;
 | 
					 | 
				
			||||||
            let date = new Date();
 | 
					 | 
				
			||||||
            construct.startTime = date.getTime();
 | 
					 | 
				
			||||||
            client.datastore.checkEntry(interaction.guild.id);
 | 
					 | 
				
			||||||
            client.funcs.play(client, interaction, interaction.guild, station);
 | 
					 | 
				
			||||||
        } catch (error) {
 | 
					 | 
				
			||||||
            console.log(error);
 | 
					 | 
				
			||||||
            client.radio.delete(interaction.guild.id);
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + `An error occured: ${error}`,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										159
									
								
								src/client/commands/play.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								src/client/commands/play.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,159 @@
 | 
				
			|||||||
 | 
					import { ApplicationCommandOptionType, ChatInputCommandInteraction, GuildMember, PermissionFlagsBits, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import { getVoiceConnection, joinVoiceChannel } from "@discordjs/voice";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { radio } from "../classes/Radio"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: "play",
 | 
				
			||||||
 | 
					    usage: "<song name>",
 | 
				
			||||||
 | 
					    description: "Play radio",
 | 
				
			||||||
 | 
					    options: [
 | 
				
			||||||
 | 
					        { type: ApplicationCommandOptionType.String, name: "query", description: "Select station", required: false}
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    category: "radio",
 | 
				
			||||||
 | 
					    async execute(interaction: ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(client.config.maintenanceMode){
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!client.stations) {
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, {
 | 
				
			||||||
 | 
					                    "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let query: string | null = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(interaction.isChatInputCommand()){
 | 
				
			||||||
 | 
					            query = interaction.options?.getString("query");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(interaction.isStringSelectMenu()){
 | 
				
			||||||
 | 
					            query = interaction.values?.[0];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!query){
 | 
				
			||||||
 | 
					            return client.funcs.listStations(client, interaction);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!(interaction.member instanceof GuildMember)) return;
 | 
				
			||||||
 | 
					        const voiceChannel = interaction.member?.voice.channel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!voiceChannel) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.noVoiceChannel,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (radio) {
 | 
				
			||||||
 | 
					            if (voiceChannel !== radio.voiceChannel) return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!query) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.noQuery,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const permissions = voiceChannel.permissionsFor(interaction.client.user);
 | 
				
			||||||
 | 
					        if (!permissions?.has(PermissionFlagsBits.Connect)) {
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.noPermsConnect,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (!permissions?.has(PermissionFlagsBits.Speak)) {
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.noPermsSpeak,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let station;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(!isNaN(parseInt(query) - 1)){
 | 
				
			||||||
 | 
					            let number = parseInt(query) - 1;
 | 
				
			||||||
 | 
					            if(number > client.stations.length - 1) {
 | 
				
			||||||
 | 
					                return interaction.reply({
 | 
				
			||||||
 | 
					                    content: client.messages.emojis["error"] + client.messages.wrongStationNumber,
 | 
				
			||||||
 | 
					                    ephemeral: true
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                station = client.stations[number];
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(query.length < 3) return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.tooShortSearch,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let type = "text";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(interaction.isStringSelectMenu() && interaction.values?.[0]){
 | 
				
			||||||
 | 
					                type = "direct";
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            const sstation = client.stations.search(query, type);
 | 
				
			||||||
 | 
					            if (!sstation) return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.noSearchResults,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            station = sstation;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (radio) {
 | 
				
			||||||
 | 
					            client.statistics?.update(client, interaction.guild, radio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let date = new Date();
 | 
				
			||||||
 | 
					            radio.station = station;
 | 
				
			||||||
 | 
					            radio.textChannel = interaction.channel;
 | 
				
			||||||
 | 
					            radio.startTime = date.getTime();
 | 
				
			||||||
 | 
					            client.funcs.play(client, interaction, interaction.guild, station);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let date = new Date();
 | 
				
			||||||
 | 
					        const construct: radio = {
 | 
				
			||||||
 | 
					            textChannel: interaction.channel,
 | 
				
			||||||
 | 
					            voiceChannel: voiceChannel,
 | 
				
			||||||
 | 
					            connection: null,
 | 
				
			||||||
 | 
					            message: null,
 | 
				
			||||||
 | 
					            station: station,
 | 
				
			||||||
 | 
					            startTime: date.getTime()
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        client.radio?.set(interaction.guild?.id, construct);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            const connection =
 | 
				
			||||||
 | 
					                getVoiceConnection(voiceChannel.guild.id) ??
 | 
				
			||||||
 | 
					                joinVoiceChannel({
 | 
				
			||||||
 | 
					                    channelId: voiceChannel.id,
 | 
				
			||||||
 | 
					                    guildId: voiceChannel.guild.id,
 | 
				
			||||||
 | 
					                    adapterCreator: voiceChannel.guild.voiceAdapterCreator
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            construct.connection = connection;
 | 
				
			||||||
 | 
					            let date = new Date();
 | 
				
			||||||
 | 
					            construct.startTime = date.getTime();
 | 
				
			||||||
 | 
					            client.datastore?.checkEntry(interaction.guild?.id);
 | 
				
			||||||
 | 
					            client.funcs.play(client, interaction, interaction.guild, station);
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            console.log(error);
 | 
				
			||||||
 | 
					            client.radio?.delete(interaction.guild?.id);
 | 
				
			||||||
 | 
					            return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + `An error occured: ${error}`,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,36 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'prev',
 | 
					 | 
				
			||||||
    description: 'Previous Station',
 | 
					 | 
				
			||||||
    category: 'radio',
 | 
					 | 
				
			||||||
    async execute(interaction, client, command) {
 | 
					 | 
				
			||||||
        if (client.funcs.check(client, interaction, command)) {
 | 
					 | 
				
			||||||
            const radio = client.radio.get(interaction.guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let index = client.stations.findIndex(station => station.name == radio.station.name) - 1;
 | 
					 | 
				
			||||||
            if(index == -1) index = client.stations.length - 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let station = client.stations[index];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(!station) return interaction.reply({
 | 
					 | 
				
			||||||
                content: client.messageEmojis["error"] + client.messages.noSearchResults,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            client.statistics.update(client, interaction.guild, radio);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let date = new Date();
 | 
					 | 
				
			||||||
            radio.station = station;
 | 
					 | 
				
			||||||
            radio.textChannel = interaction.channel;
 | 
					 | 
				
			||||||
            radio.startTime = date.getTime();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if(interaction.isChatInputCommand()) {
 | 
					 | 
				
			||||||
                client.funcs.play(client, interaction, interaction.guild, station);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if(interaction.isButton()) {
 | 
					 | 
				
			||||||
                interaction.deferUpdate();
 | 
					 | 
				
			||||||
                client.funcs.play(client, null, interaction.guild, station);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										57
									
								
								src/client/commands/prev.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/client/commands/prev.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { command } from "../commands";
 | 
				
			||||||
 | 
					import { station } from "../classes/Stations"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
					    name: 'prev',
 | 
				
			||||||
 | 
					    description: 'Previous Station',
 | 
				
			||||||
 | 
					    category: 'radio',
 | 
				
			||||||
 | 
					    async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) {
 | 
				
			||||||
 | 
					        if (client.funcs.check(client, interaction, command)) {
 | 
				
			||||||
 | 
					            const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(client.config.maintenanceMode){
 | 
				
			||||||
 | 
					                return interaction.reply({
 | 
				
			||||||
 | 
					                    content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					                    ephemeral: true
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!client.stations) {
 | 
				
			||||||
 | 
					                return interaction.reply({
 | 
				
			||||||
 | 
					                    content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, {
 | 
				
			||||||
 | 
					                        "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					                    }),
 | 
				
			||||||
 | 
					                    ephemeral: true
 | 
				
			||||||
 | 
					                });
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let index = client.stations.findIndex((station: station) => station.name == radio.station.name) - 1;
 | 
				
			||||||
 | 
					            if(index == -1) index = client.stations.length - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let station = client.stations[index];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(!station) return interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.noSearchResults,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            client.statistics?.update(client, interaction.guild, radio);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let date = new Date();
 | 
				
			||||||
 | 
					            radio.station = station;
 | 
				
			||||||
 | 
					            radio.textChannel = interaction.channel;
 | 
				
			||||||
 | 
					            radio.startTime = date.getTime();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if(interaction.isChatInputCommand()) {
 | 
				
			||||||
 | 
					                client.funcs.play(client, interaction, interaction.guild, station);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if(interaction.isButton()) {
 | 
				
			||||||
 | 
					                interaction.deferUpdate();
 | 
				
			||||||
 | 
					                client.funcs.play(client, null, interaction.guild, station);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,21 +1,27 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					export default {
 | 
				
			||||||
    name: 'statistics',
 | 
					    name: 'statistics',
 | 
				
			||||||
    description: 'Show statistics',
 | 
					    description: 'Show statistics',
 | 
				
			||||||
    category: 'info',
 | 
					    category: 'info',
 | 
				
			||||||
    execute(interaction, client) {
 | 
					    execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient) {
 | 
				
			||||||
        let message = {};
 | 
					
 | 
				
			||||||
        let stations = client.stations;
 | 
					        if(!interaction.guild) return interaction.reply({
 | 
				
			||||||
        let currentGuild = client.datastore.getEntry(interaction.guild.id);
 | 
					            content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
        let global = client.datastore.getEntry("global");
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let currentGuild = client.datastore?.getEntry(interaction.guild.id);
 | 
				
			||||||
 | 
					        let global = client.datastore?.getEntry("global");
 | 
				
			||||||
        let statistics = "";
 | 
					        let statistics = "";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!client.stations) {
 | 
					        if(!client.stations) {
 | 
				
			||||||
            message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild);
 | 
					 | 
				
			||||||
            return interaction.reply({
 | 
					            return interaction.reply({
 | 
				
			||||||
                content: client.messageEmojis["error"] + message.errorToGetPlaylist,
 | 
					                content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, {
 | 
				
			||||||
 | 
					                    "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					                }),
 | 
				
			||||||
                ephemeral: true
 | 
					                ephemeral: true
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -28,13 +34,13 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const embed = new EmbedBuilder()
 | 
					        const embed = new EmbedBuilder()
 | 
				
			||||||
            .setTitle(client.messages.statisticsTitle)
 | 
					            .setTitle(client.messages.statisticsTitle)
 | 
				
			||||||
            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["statistics"].replace(/[^0-9]+/g, ''))
 | 
					            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["statistics"].replace(/[^0-9]+/g, ''))
 | 
				
			||||||
            .setColor(client.config.embedColor)
 | 
					            .setColor(client.config.embedColor)
 | 
				
			||||||
            .setDescription(statistics)
 | 
					            .setDescription(statistics)
 | 
				
			||||||
            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
            .setFooter({
 | 
					            .setFooter({
 | 
				
			||||||
                text: client.messages.footerText,
 | 
					                text: client.messages.footerText,
 | 
				
			||||||
                iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					                iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        interaction.reply({
 | 
					        interaction.reply({
 | 
				
			||||||
@@ -1,30 +1,36 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					import { ChatInputCommandInteraction, EmbedBuilder } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					export default {
 | 
				
			||||||
    name: 'status',
 | 
					    name: 'status',
 | 
				
			||||||
    description: 'Bot Status',
 | 
					    description: 'Bot Status',
 | 
				
			||||||
    category: 'info',
 | 
					    category: 'info',
 | 
				
			||||||
    async execute(interaction, client) {
 | 
					    async execute(interaction: ChatInputCommandInteraction, client: RadioClient) {
 | 
				
			||||||
        let message = {};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        message.statusTitle = client.messages.statusTitle.replace("%client.user.username%", client.user.username);
 | 
					        if(!client.user) return interaction.reply({
 | 
				
			||||||
        let uptime = client.funcs.msToTime(client.uptime);
 | 
					            content: client.messages.emojis["error"] + client.messages.maintenance,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let uptime = client.funcs.msToTime(client.uptime || 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const embed = new EmbedBuilder()
 | 
					        const embed = new EmbedBuilder()
 | 
				
			||||||
            .setTitle(message.statusTitle)
 | 
					            .setTitle(client.messages.replace(client.messages.statusTitle, {
 | 
				
			||||||
            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, ''))
 | 
					                "%client.user.username%": client.user.username
 | 
				
			||||||
 | 
					            }))
 | 
				
			||||||
 | 
					            .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["logo"].replace(/[^0-9]+/g, ''))
 | 
				
			||||||
            .setColor(client.config.embedColor)
 | 
					            .setColor(client.config.embedColor)
 | 
				
			||||||
            .addFields(
 | 
					            .addFields([
 | 
				
			||||||
                { name: client.messages.statusField1, value: uptime },
 | 
					                { name: client.messages.statusField1, value: uptime },
 | 
				
			||||||
                { name: client.messages.statusField2, value: client.config.version },
 | 
					                { name: client.messages.statusField2, value: client.config.version },
 | 
				
			||||||
                { name: client.messages.statusField3, value: Date.now() - interaction.createdTimestamp + "ms" },
 | 
					                { name: client.messages.statusField3, value: Date.now() - interaction.createdTimestamp + "ms" },
 | 
				
			||||||
                { name: client.messages.statusField4, value: client.ws.ping.toString() },
 | 
					                { name: client.messages.statusField4, value: client.ws.ping.toString() },
 | 
				
			||||||
                { name: client.messages.statusField5, value: client.config.hostedBy }
 | 
					                { name: client.messages.statusField5, value: client.config.hostedBy }
 | 
				
			||||||
            )
 | 
					            ])
 | 
				
			||||||
            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					            .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
            .setFooter({
 | 
					            .setFooter({
 | 
				
			||||||
                text: client.messages.footerText,
 | 
					                text: client.messages.footerText,
 | 
				
			||||||
                iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					                iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        interaction.reply({
 | 
					        interaction.reply({
 | 
				
			||||||
@@ -1,19 +1,21 @@
 | 
				
			|||||||
import { EmbedBuilder } from "discord.js";
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, EmbedBuilder, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { command } from "../commands";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					export default {
 | 
				
			||||||
    name: 'stop',
 | 
					    name: 'stop',
 | 
				
			||||||
    description: 'Stop radio',
 | 
					    description: 'Stop radio',
 | 
				
			||||||
    category: 'radio',
 | 
					    category: 'radio',
 | 
				
			||||||
    async execute(interaction, client, command) {
 | 
					    async execute(interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, client: RadioClient, command: command) {
 | 
				
			||||||
        if (client.funcs.check(client, interaction, command)) {
 | 
					        if (client.funcs.check(client, interaction, command)) {
 | 
				
			||||||
            const radio = client.radio.get(interaction.guild.id);
 | 
					            const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
            client.statistics.update(client, interaction.guild, radio);
 | 
					            client.statistics?.update(client, interaction.guild, radio);
 | 
				
			||||||
            radio.connection?.destroy();
 | 
					            radio.connection?.destroy();
 | 
				
			||||||
            client.funcs.logger('Radio', interaction.guild.id + " / " + 'Stop');
 | 
					            client.funcs.logger('Radio', interaction.guild?.id + " / " + 'Stop');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const embed = new EmbedBuilder()
 | 
					            const embed = new EmbedBuilder()
 | 
				
			||||||
                .setTitle(client.user.username)
 | 
					                .setTitle(client.user?.username || "-")
 | 
				
			||||||
                .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["stop"].replace(/[^0-9]+/g, ''))
 | 
					                .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messages.emojis["stop"].replace(/[^0-9]+/g, ''))
 | 
				
			||||||
                .setColor(client.config.embedColor)
 | 
					                .setColor(client.config.embedColor)
 | 
				
			||||||
                .addFields({
 | 
					                .addFields({
 | 
				
			||||||
                    name: client.messages.nowplayingTitle,
 | 
					                    name: client.messages.nowplayingTitle,
 | 
				
			||||||
@@ -22,7 +24,7 @@ module.exports = {
 | 
				
			|||||||
                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
                .setFooter({
 | 
					                .setFooter({
 | 
				
			||||||
                    text: client.messages.footerText,
 | 
					                    text: client.messages.footerText,
 | 
				
			||||||
                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
                });
 | 
					                });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!radio.message){
 | 
					            if(!radio.message){
 | 
				
			||||||
@@ -39,10 +41,10 @@ module.exports = {
 | 
				
			|||||||
                await radio.message?.delete();
 | 
					                await radio.message?.delete();
 | 
				
			||||||
            }, 5000);
 | 
					            }, 5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            client.radio.delete(interaction.guild.id);
 | 
					            client.radio?.delete(interaction.guild?.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            interaction.reply({
 | 
					            interaction.reply({
 | 
				
			||||||
                content: client.messageEmojis["stop"] + client.messages.stop,
 | 
					                content: client.messages.emojis["stop"] + client.messages.stop,
 | 
				
			||||||
                ephemeral: true
 | 
					                ephemeral: true
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@@ -1,42 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'emojis',
 | 
					 | 
				
			||||||
    async execute(client) {
 | 
					 | 
				
			||||||
        let customEmojis = {
 | 
					 | 
				
			||||||
            logo: "<:RadioX:688765708808487072>",
 | 
					 | 
				
			||||||
            eximiabots: "<:EximiaBots:693277919929303132>",
 | 
					 | 
				
			||||||
            list: "<:RadioXList:688541155519889482>",
 | 
					 | 
				
			||||||
            play: "<:RadioXPlay:688541155712827458>",
 | 
					 | 
				
			||||||
            stop: "<:RadioXStop:688541155377414168>",
 | 
					 | 
				
			||||||
            statistics: "<:RadioXStatistics:694954485507686421>",
 | 
					 | 
				
			||||||
            maintenance: "<:RadioXMaintenance:695043843057254493>",
 | 
					 | 
				
			||||||
            error: "<:RadioXError:688541155792781320>",
 | 
					 | 
				
			||||||
            prev: "<:RadioXPrev:882153637370023957>",
 | 
					 | 
				
			||||||
            next: "<:RadioXNext:882153637474893834>"
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let fallbackEmojis = {
 | 
					 | 
				
			||||||
            logo: "RadioX",
 | 
					 | 
				
			||||||
            eximiabots: "EximiaBots",
 | 
					 | 
				
			||||||
            list: "📜",
 | 
					 | 
				
			||||||
            play: "▶️",
 | 
					 | 
				
			||||||
            stop: "⏹️",
 | 
					 | 
				
			||||||
            statistics: "📊",
 | 
					 | 
				
			||||||
            maintenance: "🛠️",
 | 
					 | 
				
			||||||
            error: "❌",
 | 
					 | 
				
			||||||
            prev: "⏪",
 | 
					 | 
				
			||||||
            next: "⏩"
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.messageEmojis = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        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 {
 | 
					 | 
				
			||||||
                client.messageEmojis[customEmojiName] = fallbackEmojis[customEmojiName];
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										53
									
								
								src/client/events.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/client/events.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					import RadioClient from "../Client"
 | 
				
			||||||
 | 
					import interactionCreate from "./events/interactionCreate"
 | 
				
			||||||
 | 
					import messageDelete from "./events/messageDelete"
 | 
				
			||||||
 | 
					import ready from "./events/ready"
 | 
				
			||||||
 | 
					import SIGINT from "./events/SIGINT"
 | 
				
			||||||
 | 
					import SIGTERM from "./events/SIGTERM"
 | 
				
			||||||
 | 
					import uncaughtException from "./events/uncaughtException"
 | 
				
			||||||
 | 
					import voiceStateUpdate from "./events/voiceStateUpdate"
 | 
				
			||||||
 | 
					import warning from "./events/warning"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function events(client: RadioClient) {
 | 
				
			||||||
 | 
					    client.on("ready", () => {
 | 
				
			||||||
 | 
					        ready(client);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.on("messageDelete", msg => {
 | 
				
			||||||
 | 
					        messageDelete(client, msg);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.on("interactionCreate", interaction => {
 | 
				
			||||||
 | 
					        interactionCreate(client, interaction);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.on("voiceStateUpdate", (oldState, newState) => {
 | 
				
			||||||
 | 
					        voiceStateUpdate(client, oldState, newState);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.on("error", error => {
 | 
				
			||||||
 | 
					        client.funcs.logger("Discord Client", "Error");
 | 
				
			||||||
 | 
					        console.error(error);
 | 
				
			||||||
 | 
					        console.log('');
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.on('SIGINT', () => {
 | 
				
			||||||
 | 
					        SIGINT(client);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.on('SIGTERM', () => {
 | 
				
			||||||
 | 
					        SIGTERM(client);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.on('uncaughtException', (error) => {
 | 
				
			||||||
 | 
					        uncaughtException(client, error);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.on('exit', () => {
 | 
				
			||||||
 | 
					        client.funcs.logger("Bot", "Stopping");
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    process.on('warning', (error) => {
 | 
				
			||||||
 | 
					        warning(client, error);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,15 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'SIGINT',
 | 
					 | 
				
			||||||
    execute(client) {
 | 
					 | 
				
			||||||
        client.user.setStatus('dnd');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.streamer.leave(client);
 | 
					 | 
				
			||||||
        client.radio.save(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        setInterval(() => {
 | 
					 | 
				
			||||||
            if(client.radio.size == 0){
 | 
					 | 
				
			||||||
                process.exit();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }, 500);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										14
									
								
								src/client/events/SIGINT.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/client/events/SIGINT.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function SIGINT(client: RadioClient) {
 | 
				
			||||||
 | 
					    client.user?.setStatus('dnd');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.streamer?.leave(client);
 | 
				
			||||||
 | 
					    client.radio?.save(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setInterval(() => {
 | 
				
			||||||
 | 
					        if(client.radio?.size == 0){
 | 
				
			||||||
 | 
					            process.exit();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, 500);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'SIGTERM',
 | 
					 | 
				
			||||||
    execute(client) {
 | 
					 | 
				
			||||||
        process.emit('SIGINT');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										5
									
								
								src/client/events/SIGTERM.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/client/events/SIGTERM.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function SIGTERM(client: RadioClient) {
 | 
				
			||||||
 | 
					    process.emit('SIGINT');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,45 +0,0 @@
 | 
				
			|||||||
import { PermissionFlagsBits } from "discord.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'interactionCreate',
 | 
					 | 
				
			||||||
    async execute(client, interaction) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const permissions = interaction.channel.permissionsFor(interaction.client.user);
 | 
					 | 
				
			||||||
        if (!permissions.has(PermissionFlagsBits.ViewChannel)) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + client.messages.noPermsEmbed,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(interaction.isChatInputCommand()){
 | 
					 | 
				
			||||||
            const commandName = interaction.commandName;
 | 
					 | 
				
			||||||
            const command = client.commands.get(commandName);
 | 
					 | 
				
			||||||
            if (!command) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                command.execute(interaction, client);
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                interaction.reply({
 | 
					 | 
				
			||||||
                    content: client.messageEmojis["error"] + client.messages.runningCommandFailed,
 | 
					 | 
				
			||||||
                    ephemeral: true
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                console.error(error);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else if (interaction.isStringSelectMenu() || interaction.isButton()){
 | 
					 | 
				
			||||||
            const commandName = interaction.customId;
 | 
					 | 
				
			||||||
            const command = client.commands.get(commandName);
 | 
					 | 
				
			||||||
            if (!command) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                command.execute(interaction, client, command);
 | 
					 | 
				
			||||||
            } catch (error) {
 | 
					 | 
				
			||||||
                interaction.reply({
 | 
					 | 
				
			||||||
                    content: client.messageEmojis["error"] + client.messages.runningCommandFailed,
 | 
					 | 
				
			||||||
                    ephemeral: true
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
                console.error(error);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										46
									
								
								src/client/events/interactionCreate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/client/events/interactionCreate.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
				
			|||||||
 | 
					import { ChannelType, Interaction, PermissionFlagsBits } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function interactionCreate(client: RadioClient, interaction: Interaction) {
 | 
				
			||||||
 | 
					    if(!(interaction.isButton()) && !(interaction.isChatInputCommand()) && !(interaction.isStringSelectMenu())) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(interaction.channel?.type != ChannelType.DM){
 | 
				
			||||||
 | 
					        const permissions = interaction.channel?.permissionsFor(interaction.client.user);
 | 
				
			||||||
 | 
					        if (!permissions?.has(PermissionFlagsBits.ViewChannel)) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!permissions?.has(PermissionFlagsBits.EmbedLinks)) return interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.noPermsEmbed,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(interaction.isChatInputCommand()){
 | 
				
			||||||
 | 
					        const commandName = interaction.commandName;
 | 
				
			||||||
 | 
					        const command = client.commands.get(commandName);
 | 
				
			||||||
 | 
					        if (!command) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            command.execute(interaction, client);
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.runningCommandFailed,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            console.error(error);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    } else if (interaction.isStringSelectMenu() || interaction.isButton()){
 | 
				
			||||||
 | 
					        const commandName = interaction.customId;
 | 
				
			||||||
 | 
					        const command = client.commands.get(commandName);
 | 
				
			||||||
 | 
					        if (!command) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            command.execute(interaction, client, command);
 | 
				
			||||||
 | 
					        } catch (error) {
 | 
				
			||||||
 | 
					            interaction.reply({
 | 
				
			||||||
 | 
					                content: client.messages.emojis["error"] + client.messages.runningCommandFailed,
 | 
				
			||||||
 | 
					                ephemeral: true
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            console.error(error);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,62 +0,0 @@
 | 
				
			|||||||
import { EmbedBuilder, PermissionFlagsBits } from "discord.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'messageCreate',
 | 
					 | 
				
			||||||
    async execute(client, message) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (message.author.bot || !message.guild) return;
 | 
					 | 
				
			||||||
        let prefix = "rx$";
 | 
					 | 
				
			||||||
        if(client.user.username == "RadioX"){
 | 
					 | 
				
			||||||
            prefix = "rx>";
 | 
					 | 
				
			||||||
        } else if (client.user.username == "RadioX Beta"){
 | 
					 | 
				
			||||||
            prefix = "rx-";
 | 
					 | 
				
			||||||
        } else if (client.user.username == "RadioX Dev"){
 | 
					 | 
				
			||||||
            prefix = "rx$";
 | 
					 | 
				
			||||||
        } else if(message.mentions.members.first() && message.mentions.members.first().user.id === client.user.id){
 | 
					 | 
				
			||||||
            prefix = "<@!" + client.user.id + "> ";
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        const args = message.content.slice(prefix.length).split(' ');
 | 
					 | 
				
			||||||
        if (!message.content.startsWith(prefix)) return;
 | 
					 | 
				
			||||||
        if (!args[0]) return;
 | 
					 | 
				
			||||||
        const commandName = args[0].toLowerCase();
 | 
					 | 
				
			||||||
        if (commandName === 'none') return;
 | 
					 | 
				
			||||||
        const command = client.commands.get(commandName) || client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
 | 
					 | 
				
			||||||
        if (!command && message.content !== `${prefix}`) return;
 | 
					 | 
				
			||||||
        const permissions = message.channel.permissionsFor(message.client.user);
 | 
					 | 
				
			||||||
        if (!permissions.has(PermissionFlagsBits.EmbedLinks)) return message.channel.send(client.messages.noPermsEmbed);
 | 
					 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            let newMessage = {};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            newMessage.messageCommandsDeprecatedTitle = client.messages.messageCommandsDeprecatedTitle.replace("%client.user.username%", client.user.username);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const embed = new EmbedBuilder()
 | 
					 | 
				
			||||||
                .setTitle(newMessage.messageCommandsDeprecatedTitle)
 | 
					 | 
				
			||||||
                .setThumbnail("https://cdn.discordapp.com/emojis/" + client.messageEmojis["logo"].replace(/[^0-9]+/g, ''))
 | 
					 | 
				
			||||||
                .setColor(client.config.embedColor)
 | 
					 | 
				
			||||||
                .setDescription(client.messages.messageCommandsDeprecatedDescription)
 | 
					 | 
				
			||||||
                .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					 | 
				
			||||||
                .setFooter({
 | 
					 | 
				
			||||||
                    text: client.messages.footerText,
 | 
					 | 
				
			||||||
                    iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let msg = await message.channel.send({ embeds: [embed] });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            setTimeout(async function() {
 | 
					 | 
				
			||||||
                try {
 | 
					 | 
				
			||||||
                    await msg.delete();
 | 
					 | 
				
			||||||
                } catch (DiscordAPIError) {
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }, 30000);
 | 
					 | 
				
			||||||
        } catch (error) {
 | 
					 | 
				
			||||||
            message.reply({
 | 
					 | 
				
			||||||
                content: client.messages.runningCommandFailed,
 | 
					 | 
				
			||||||
                ephemeral: true
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
            console.error(error);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'messageDelete',
 | 
					 | 
				
			||||||
    async execute(client, msg) {
 | 
					 | 
				
			||||||
        if(!msg.author.bot || !msg.guild) return;
 | 
					 | 
				
			||||||
        const radio = client.radio.get(msg.guild.id);
 | 
					 | 
				
			||||||
        if(!radio) return;
 | 
					 | 
				
			||||||
        if(!radio.message) return;
 | 
					 | 
				
			||||||
        if(msg.id != radio.message.id) return;
 | 
					 | 
				
			||||||
        radio.message = null;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										11
									
								
								src/client/events/messageDelete.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/client/events/messageDelete.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import { Message, PartialMessage } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function messageDelete(client: RadioClient, msg: Message | PartialMessage){
 | 
				
			||||||
 | 
					    if(!msg.author?.bot || !msg.guild) return;
 | 
				
			||||||
 | 
					    const radio = client.radio?.get(msg.guild.id);
 | 
				
			||||||
 | 
					    if(!radio) return;
 | 
				
			||||||
 | 
					    if(!radio.message) return;
 | 
				
			||||||
 | 
					    if(msg.id != radio.message.id) return;
 | 
				
			||||||
 | 
					    radio.message = null;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,95 +0,0 @@
 | 
				
			|||||||
import Datastore from "../classes/Datastore.js";
 | 
					 | 
				
			||||||
import Radio from "../classes/Radio.js";
 | 
					 | 
				
			||||||
import Stations from "../classes/Stations.js";
 | 
					 | 
				
			||||||
import Streamer from "../classes/Streamer.js";
 | 
					 | 
				
			||||||
import Statistics from "../classes/Statistics.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'ready',
 | 
					 | 
				
			||||||
    async execute(client) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.funcs.logger("Bot", "Ready");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*DATASTORE*/
 | 
					 | 
				
			||||||
        client.funcs.logger('Datastore', 'Initialize');
 | 
					 | 
				
			||||||
        client.datastore = new Datastore();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.datastore.map.forEach(datastore => {
 | 
					 | 
				
			||||||
            client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.funcs.logger('Datastore', 'Ready');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*DEVELOPERS*/
 | 
					 | 
				
			||||||
        client.developers = "";
 | 
					 | 
				
			||||||
        let user = "";
 | 
					 | 
				
			||||||
        for (let i = 0; i < client.config.devId.length; i++) {
 | 
					 | 
				
			||||||
            user = await client.users.fetch(client.config.devId[i]);
 | 
					 | 
				
			||||||
            client.funcs.logger('Developers', user.tag);
 | 
					 | 
				
			||||||
            if (i == client.config.devId.length - 1) {
 | 
					 | 
				
			||||||
                client.developers += user.tag;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                client.developers += user.tag + " & ";
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*STATIONS*/
 | 
					 | 
				
			||||||
        client.stations = new Stations();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        await client.stations.fetch({
 | 
					 | 
				
			||||||
            url: client.config.stationslistUrl,
 | 
					 | 
				
			||||||
            show: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*setInterval(async () => {
 | 
					 | 
				
			||||||
            await client.stations.fetch({
 | 
					 | 
				
			||||||
                url: client.config.stationslistUrl,
 | 
					 | 
				
			||||||
                show: false
 | 
					 | 
				
			||||||
            });
 | 
					 | 
				
			||||||
        }, 3600000);*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.streamer = new Streamer();
 | 
					 | 
				
			||||||
        client.streamer.init(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(!client.stations) {
 | 
					 | 
				
			||||||
            client.user.setStatus('dnd');
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*GUILDS*/
 | 
					 | 
				
			||||||
        client.funcs.logger('Guilds', 'Started fetching list');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let guilds = await client.guilds.fetch();
 | 
					 | 
				
			||||||
        guilds.forEach(guild => {
 | 
					 | 
				
			||||||
            client.funcs.logger('Guilds', guild.id + " / " + guild.name);
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.funcs.logger('Guilds', 'Successfully fetched list');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*STATISTICS*/
 | 
					 | 
				
			||||||
        client.statistics = new Statistics();
 | 
					 | 
				
			||||||
        client.statistics.calculateGlobal(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*EMOJIS*/
 | 
					 | 
				
			||||||
        require(`../emojis.js`).execute(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*COMMANDS*/
 | 
					 | 
				
			||||||
        require(`../commands.js`).execute(client);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        /*RADIO*/
 | 
					 | 
				
			||||||
        client.radio = new Radio();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        setTimeout(function () {
 | 
					 | 
				
			||||||
            /*RESTORE RADIOS*/
 | 
					 | 
				
			||||||
            client.radio.restore(client, guilds);
 | 
					 | 
				
			||||||
        }, 5000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        setTimeout(function () {
 | 
					 | 
				
			||||||
            if(client.stations) {
 | 
					 | 
				
			||||||
                /*MAINTENANCE MODE*/
 | 
					 | 
				
			||||||
                client.funcs.logger("Maintenance Mode", "Disabled");
 | 
					 | 
				
			||||||
                client.config.maintenanceMode = false;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }, 10000);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										77
									
								
								src/client/events/ready.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/client/events/ready.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import Datastore, { datastore } from "../classes/Datastore";
 | 
				
			||||||
 | 
					import Radio from "../classes/Radio";
 | 
				
			||||||
 | 
					import Stations from "../classes/Stations";
 | 
				
			||||||
 | 
					import Streamer from "../classes/Streamer";
 | 
				
			||||||
 | 
					import Statistics from "../classes/Statistics";
 | 
				
			||||||
 | 
					import commands from "../commands";
 | 
				
			||||||
 | 
					import { OAuth2Guild } from "discord.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function ready(client: RadioClient) {
 | 
				
			||||||
 | 
					    client.funcs.logger("Bot", "Ready");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*DATASTORE*/
 | 
				
			||||||
 | 
					    client.funcs.logger('Datastore', 'Initialize');
 | 
				
			||||||
 | 
					    client.datastore = new Datastore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.datastore.map.forEach((datastore: datastore) => {
 | 
				
			||||||
 | 
					        client.funcs.logger('Datastore', datastore.guild.id + " / " + datastore.guild.name);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.funcs.logger('Datastore', 'Ready');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*DEVELOPERS*/
 | 
				
			||||||
 | 
					    let developers : string[] = [];
 | 
				
			||||||
 | 
					    for(let devID of client.config.devIDs){
 | 
				
			||||||
 | 
					        developers.push((await client.users.fetch(devID)).tag);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    client.funcs.logger('Developers', developers.join(" & "));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*STATIONS*/
 | 
				
			||||||
 | 
					    client.stations = new Stations();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await client.stations.fetch({
 | 
				
			||||||
 | 
					        url: client.config.stationslistUrl,
 | 
				
			||||||
 | 
					        show: true
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.streamer = new Streamer();
 | 
				
			||||||
 | 
					    client.streamer.init(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(!client.stations) {
 | 
				
			||||||
 | 
					        client.user?.setStatus('dnd');
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*GUILDS*/
 | 
				
			||||||
 | 
					    client.funcs.logger('Guilds', 'Started fetching list');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let guilds = await client.guilds.fetch();
 | 
				
			||||||
 | 
					    guilds.forEach((guild: OAuth2Guild) => {
 | 
				
			||||||
 | 
					        client.funcs.logger('Guilds', guild.id + " / " + guild.name);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.funcs.logger('Guilds', 'Successfully fetched list');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*STATISTICS*/
 | 
				
			||||||
 | 
					    client.statistics = new Statistics();
 | 
				
			||||||
 | 
					    client.statistics.calculateGlobal(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*COMMANDS*/
 | 
				
			||||||
 | 
					    commands(client);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /*RADIO*/
 | 
				
			||||||
 | 
					    client.radio = new Radio();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setTimeout(function () {
 | 
				
			||||||
 | 
					        /*RESTORE RADIOS*/
 | 
				
			||||||
 | 
					        client.radio?.restore(client, guilds);
 | 
				
			||||||
 | 
					    }, 5000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    setTimeout(function () {
 | 
				
			||||||
 | 
					        if(client.stations) {
 | 
				
			||||||
 | 
					            /*MAINTENANCE MODE*/
 | 
				
			||||||
 | 
					            client.funcs.logger("Maintenance Mode", "Disabled");
 | 
				
			||||||
 | 
					            client.config.maintenanceMode = false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, 10000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,11 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'uncaughtException',
 | 
					 | 
				
			||||||
    execute(client, error) {
 | 
					 | 
				
			||||||
        client.funcs.logger("Error");
 | 
					 | 
				
			||||||
        console.log(error.stack);
 | 
					 | 
				
			||||||
        console.log('');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if(error.name == "DiscordAPIError" && error.message == "Unknown interaction") return;
 | 
					 | 
				
			||||||
        process.emit('SIGINT');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										10
									
								
								src/client/events/uncaughtException.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/client/events/uncaughtException.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function uncaughtException(client: RadioClient, error: Error) {
 | 
				
			||||||
 | 
					    client.funcs.logger("Error");
 | 
				
			||||||
 | 
					    console.log(error.stack);
 | 
				
			||||||
 | 
					    console.log('');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(error.name == "DiscordAPIError" && error.message == "Unknown interaction") return;
 | 
				
			||||||
 | 
					    process.emit('SIGINT');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,68 +0,0 @@
 | 
				
			|||||||
import { PermissionFlagsBits } from "discord.js";
 | 
					 | 
				
			||||||
const {
 | 
					 | 
				
			||||||
    getVoiceConnection,
 | 
					 | 
				
			||||||
    joinVoiceChannel
 | 
					 | 
				
			||||||
} = require("@discordjs/voice");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: "voiceStateUpdate",
 | 
					 | 
				
			||||||
    async execute(client, oldState, newState) {
 | 
					 | 
				
			||||||
        if (oldState.channel === null) return;
 | 
					 | 
				
			||||||
        let change = false;
 | 
					 | 
				
			||||||
        const radio = client.radio?.get(newState.guild.id);
 | 
					 | 
				
			||||||
        if (!radio) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (newState.member.id === client.user.id && oldState.member.id === client.user.id) {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (newState.channel === null) {
 | 
					 | 
				
			||||||
                client.statistics.update(client, newState.guild, radio);
 | 
					 | 
				
			||||||
                radio.connection?.destroy();
 | 
					 | 
				
			||||||
                radio.message?.delete();
 | 
					 | 
				
			||||||
                client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop');
 | 
					 | 
				
			||||||
                return client.radio.delete(newState.guild.id);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            const newPermissions = newState.channel.permissionsFor(newState.client.user);
 | 
					 | 
				
			||||||
            if (!newPermissions.has(PermissionFlagsBits.Connect) || !newPermissions.has(PermissionFlagsBits.Speak) || !newPermissions.has(PermissionFlagsBits.ViewChannel)) {
 | 
					 | 
				
			||||||
                try {
 | 
					 | 
				
			||||||
                    setTimeout(
 | 
					 | 
				
			||||||
                        async () => (
 | 
					 | 
				
			||||||
                            radio.connection = joinVoiceChannel({
 | 
					 | 
				
			||||||
                                channelId: oldState.channel.id,
 | 
					 | 
				
			||||||
                                guildId: oldState.channel.guild.id,
 | 
					 | 
				
			||||||
                                adapterCreator: oldState.channel.guild.voiceAdapterCreator
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                            //radio.connection = await oldState.channel.join()
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                        1000
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
                } catch (error) {
 | 
					 | 
				
			||||||
                    client.statistics.update(client, newState.guild, radio);
 | 
					 | 
				
			||||||
                    radio.connection?.destroy();
 | 
					 | 
				
			||||||
                    radio.message?.delete();
 | 
					 | 
				
			||||||
                    client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop');
 | 
					 | 
				
			||||||
                    client.radio.delete(oldState.guild.id);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            if (newState.channel !== radio.voiceChannel) {
 | 
					 | 
				
			||||||
                change = true;
 | 
					 | 
				
			||||||
                radio.voiceChannel = newState.channel;
 | 
					 | 
				
			||||||
                radio.connection = getVoiceConnection(newState.channel.guild.id);
 | 
					 | 
				
			||||||
                //radio.connection = await newState.channel.join();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        if ((oldState.channel.members.filter(member => !member.user.bot).size === 0 && oldState.channel === radio.voiceChannel) || change) {
 | 
					 | 
				
			||||||
            setTimeout(() => {
 | 
					 | 
				
			||||||
                if (!radio || !radio.connection || !radio.connection === null) return;
 | 
					 | 
				
			||||||
                if (radio.voiceChannel.members.filter(member => !member.user.bot).size === 0) {
 | 
					 | 
				
			||||||
                    client.statistics.update(client, newState.guild, radio);
 | 
					 | 
				
			||||||
                    radio.connection?.destroy();
 | 
					 | 
				
			||||||
                    radio.message?.delete();
 | 
					 | 
				
			||||||
                    client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop');
 | 
					 | 
				
			||||||
                    client.radio.delete(newState.guild.id);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }, 5000);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										65
									
								
								src/client/events/voiceStateUpdate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/client/events/voiceStateUpdate.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
				
			|||||||
 | 
					import { GuildMember, PermissionFlagsBits, VoiceState } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					const {
 | 
				
			||||||
 | 
					    getVoiceConnection,
 | 
				
			||||||
 | 
					    joinVoiceChannel
 | 
				
			||||||
 | 
					} = require("@discordjs/voice");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default async function voiceStateUpdate(client: RadioClient, oldState: VoiceState, newState: VoiceState) {
 | 
				
			||||||
 | 
					    if (oldState.channel === null) return;
 | 
				
			||||||
 | 
					    let change = false;
 | 
				
			||||||
 | 
					    const radio = client.radio?.get(newState.guild.id);
 | 
				
			||||||
 | 
					    if (!radio) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (newState.member?.id === client.user?.id && oldState.member?.id === client.user?.id) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (newState.channel === null) {
 | 
				
			||||||
 | 
					            client.statistics?.update(client, newState.guild, radio);
 | 
				
			||||||
 | 
					            radio.connection?.destroy();
 | 
				
			||||||
 | 
					            radio.message?.delete();
 | 
				
			||||||
 | 
					            client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop');
 | 
				
			||||||
 | 
					            return client.radio?.delete(newState.guild.id);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const newPermissions = newState.channel.permissionsFor(newState.client.user);
 | 
				
			||||||
 | 
					        if (!newPermissions?.has(PermissionFlagsBits.Connect) || !newPermissions?.has(PermissionFlagsBits.Speak) || !newPermissions?.has(PermissionFlagsBits.ViewChannel)) {
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                setTimeout(
 | 
				
			||||||
 | 
					                    async () => (
 | 
				
			||||||
 | 
					                        radio.connection = joinVoiceChannel({
 | 
				
			||||||
 | 
					                            channelId: oldState.channel?.id,
 | 
				
			||||||
 | 
					                            guildId: oldState.channel?.guild.id,
 | 
				
			||||||
 | 
					                            adapterCreator: oldState.channel?.guild.voiceAdapterCreator
 | 
				
			||||||
 | 
					                        })
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    1000
 | 
				
			||||||
 | 
					                );
 | 
				
			||||||
 | 
					            } catch (error) {
 | 
				
			||||||
 | 
					                client.statistics?.update(client, newState.guild, radio);
 | 
				
			||||||
 | 
					                radio.connection?.destroy();
 | 
				
			||||||
 | 
					                radio.message?.delete();
 | 
				
			||||||
 | 
					                client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop');
 | 
				
			||||||
 | 
					                client.radio?.delete(oldState.guild.id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (newState.channel !== radio.voiceChannel) {
 | 
				
			||||||
 | 
					            change = true;
 | 
				
			||||||
 | 
					            radio.voiceChannel = newState.channel;
 | 
				
			||||||
 | 
					            radio.connection = getVoiceConnection(newState.channel.guild.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if ((oldState.channel.members.filter(member => !member.user.bot).size === 0 && oldState.channel === radio.voiceChannel) || change) {
 | 
				
			||||||
 | 
					        setTimeout(() => {
 | 
				
			||||||
 | 
					            if (!radio || !radio.connection || !radio.connection === null) return;
 | 
				
			||||||
 | 
					            if (radio.voiceChannel.members.filter((member: GuildMember) => !member.user.bot).size === 0) {
 | 
				
			||||||
 | 
					                client.statistics?.update(client, newState.guild, radio);
 | 
				
			||||||
 | 
					                radio.connection?.destroy();
 | 
				
			||||||
 | 
					                radio.message?.delete();
 | 
				
			||||||
 | 
					                client.funcs.logger('Radio', newState.guild.id + " / " + 'Stop');
 | 
				
			||||||
 | 
					                client.radio?.delete(newState.guild.id);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }, 5000);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
module.exports = {
 | 
					 | 
				
			||||||
    name: 'warning',
 | 
					 | 
				
			||||||
    execute(client, warning) {
 | 
					 | 
				
			||||||
        if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        client.funcs.logger("Warning");
 | 
					 | 
				
			||||||
        console.warn(warning.name);
 | 
					 | 
				
			||||||
        console.warn(warning.message);
 | 
					 | 
				
			||||||
        console.warn(warning.stack);
 | 
					 | 
				
			||||||
        console.log('');
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										11
									
								
								src/client/events/warning.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/client/events/warning.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function warning(client: RadioClient, warning: Error) {
 | 
				
			||||||
 | 
					    if(warning.name == "ExperimentalWarning" && warning.message.startsWith("stream/web")) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.funcs.logger("Warning");
 | 
				
			||||||
 | 
					    console.warn(warning.name);
 | 
				
			||||||
 | 
					    console.warn(warning.message);
 | 
				
			||||||
 | 
					    console.warn(warning.stack);
 | 
				
			||||||
 | 
					    console.log('');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										12
									
								
								src/client/funcs.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/client/funcs.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					import check from "./funcs/check";
 | 
				
			||||||
 | 
					import isDev from "./funcs/isDev";
 | 
				
			||||||
 | 
					import listStations from "./funcs/listStations";
 | 
				
			||||||
 | 
					import loadState from "./funcs/loadState";
 | 
				
			||||||
 | 
					import logger from "./funcs/logger";
 | 
				
			||||||
 | 
					import msToTime from "./funcs/msToTime";
 | 
				
			||||||
 | 
					import play from "./funcs/play";
 | 
				
			||||||
 | 
					import saveState from "./funcs/saveState";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const funcs = {
 | 
				
			||||||
 | 
					    check, isDev, listStations, loadState, logger, msToTime, play, saveState
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,35 +0,0 @@
 | 
				
			|||||||
module.exports = function check(client, interaction, command) {
 | 
					 | 
				
			||||||
    let message = {};
 | 
					 | 
				
			||||||
    const radio = client.radio.get(interaction.guild.id);
 | 
					 | 
				
			||||||
    if(client.config.maintenanceMode){
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + client.messages.maintenance,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if(!client.stations) {
 | 
					 | 
				
			||||||
        message.errorToGetPlaylist = client.messages.errorToGetPlaylist.replace("%client.config.supportGuild%", client.config.supportGuild);
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + message.errorToGetPlaylist,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (!radio) {
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + client.messages.notPlaying,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (interaction.member.voice.channel !== radio.voiceChannel) {
 | 
					 | 
				
			||||||
        interaction.reply({
 | 
					 | 
				
			||||||
            content: client.messageEmojis["error"] + client.messages.wrongVoiceChannel,
 | 
					 | 
				
			||||||
            ephemeral: true
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
        return false;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
							
								
								
									
										34
									
								
								src/client/funcs/check.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/client/funcs/check.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					import { ButtonInteraction, ChatInputCommandInteraction, GuildMember, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { command } from "../commands";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function check(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction, command: command) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const radio = client.radio?.get(interaction.guild?.id);
 | 
				
			||||||
 | 
					    if(!client.stations) {
 | 
				
			||||||
 | 
					        interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.replace(client.messages.errorToGetPlaylist, {
 | 
				
			||||||
 | 
					                "%client.config.supportGuild%": client.config.supportGuild
 | 
				
			||||||
 | 
					            }),
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if (!radio) {
 | 
				
			||||||
 | 
					        interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.notPlaying,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (interaction.member instanceof GuildMember && interaction.member?.voice.channel !== radio.voiceChannel) {
 | 
				
			||||||
 | 
					        interaction.reply({
 | 
				
			||||||
 | 
					            content: client.messages.emojis["error"] + client.messages.wrongVoiceChannel,
 | 
				
			||||||
 | 
					            ephemeral: true
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
@@ -1,10 +0,0 @@
 | 
				
			|||||||
module.exports = function isDev(devList, authorID){
 | 
					 | 
				
			||||||
    let response = false;
 | 
					 | 
				
			||||||
    Object.keys(devList).forEach(function(oneDev) {
 | 
					 | 
				
			||||||
        let devID = devList[oneDev];
 | 
					 | 
				
			||||||
        if(authorID == devID){
 | 
					 | 
				
			||||||
            response = true;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    return response;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										9
									
								
								src/client/funcs/isDev.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/client/funcs/isDev.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					import { Snowflake } from "discord.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function isDev(devIDs : string[], authorID : Snowflake){
 | 
				
			||||||
 | 
					    for (const devID of devIDs){
 | 
				
			||||||
 | 
					        if(authorID == devID){
 | 
				
			||||||
 | 
					            return true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,33 +0,0 @@
 | 
				
			|||||||
import { ActionRowBuilder, StringSelectMenuBuilder } from "discord.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
module.exports = function listStations(client, interaction){
 | 
					 | 
				
			||||||
    let stations = new Array();
 | 
					 | 
				
			||||||
    let options = new Array();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    stations = client.stations.forEach(station => {
 | 
					 | 
				
			||||||
        if(station.name == "GrooveFM") return;
 | 
					 | 
				
			||||||
        station = {
 | 
					 | 
				
			||||||
            label: station.name,
 | 
					 | 
				
			||||||
            description: station.owner,
 | 
					 | 
				
			||||||
            value: station.name
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        options.push(station);
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const menu = new ActionRowBuilder()
 | 
					 | 
				
			||||||
        .addComponents(
 | 
					 | 
				
			||||||
            new StringSelectMenuBuilder()
 | 
					 | 
				
			||||||
                .setCustomId('play')
 | 
					 | 
				
			||||||
                .setPlaceholder('Nothing selected')
 | 
					 | 
				
			||||||
                .addOptions(options)
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    stations = null;
 | 
					 | 
				
			||||||
    options = null;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return interaction.reply({
 | 
					 | 
				
			||||||
        content: '**Select station:**',
 | 
					 | 
				
			||||||
        components: [menu],
 | 
					 | 
				
			||||||
        ephemeral: true
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										30
									
								
								src/client/funcs/listStations.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/client/funcs/listStations.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					import { ActionRowBuilder, ButtonInteraction, ChatInputCommandInteraction, SelectMenuComponentOptionData, StringSelectMenuBuilder, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function listStations(client: RadioClient, interaction: ButtonInteraction | ChatInputCommandInteraction | StringSelectMenuInteraction){
 | 
				
			||||||
 | 
					    if(!client.stations) return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let options : SelectMenuComponentOptionData[] = new Array();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (const station of client.stations){
 | 
				
			||||||
 | 
					        options.push({
 | 
				
			||||||
 | 
					            label: station.name,
 | 
				
			||||||
 | 
					            description: station.owner,
 | 
				
			||||||
 | 
					            value: station.name
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const menu = new ActionRowBuilder<StringSelectMenuBuilder>()
 | 
				
			||||||
 | 
					        .addComponents(
 | 
				
			||||||
 | 
					            new StringSelectMenuBuilder()
 | 
				
			||||||
 | 
					                .setCustomId('play')
 | 
				
			||||||
 | 
					                .setPlaceholder('Nothing selected')
 | 
				
			||||||
 | 
					                .addOptions(options)
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return interaction.reply({
 | 
				
			||||||
 | 
					        content: '**Select station:**',
 | 
				
			||||||
 | 
					        components: [menu],
 | 
				
			||||||
 | 
					        ephemeral: true
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,12 +0,0 @@
 | 
				
			|||||||
module.exports = function loadState(client, guild){
 | 
					 | 
				
			||||||
    let data = client.datastore.getEntry(guild.id);
 | 
					 | 
				
			||||||
    if(!data) return;
 | 
					 | 
				
			||||||
    let state;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    state = data.state;
 | 
					 | 
				
			||||||
    if(!state) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.state = {};
 | 
					 | 
				
			||||||
    client.datastore.updateEntry(guild, data);
 | 
					 | 
				
			||||||
    return state;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										13
									
								
								src/client/funcs/loadState.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/client/funcs/loadState.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					import { OAuth2Guild } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function loadState(client: RadioClient, guild: OAuth2Guild) {
 | 
				
			||||||
 | 
					    if(!client.datastore) return;
 | 
				
			||||||
 | 
					    let data = client.datastore.getEntry(guild.id);
 | 
				
			||||||
 | 
					    if(!data) return;
 | 
				
			||||||
 | 
					    let state = data.state;
 | 
				
			||||||
 | 
					    if(!state) return;
 | 
				
			||||||
 | 
					    data.state = null;
 | 
				
			||||||
 | 
					    client.datastore.updateEntry(guild, data);
 | 
				
			||||||
 | 
					    return state;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,5 +0,0 @@
 | 
				
			|||||||
module.exports = function logger(area, text){
 | 
					 | 
				
			||||||
    let date = new Date();
 | 
					 | 
				
			||||||
    console.log('[' + area + '] – ' + date.toISOString());
 | 
					 | 
				
			||||||
    if(text)  console.log(text + '\n');
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										5
									
								
								src/client/funcs/logger.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/client/funcs/logger.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					export default function logger(area: string, text?: string){
 | 
				
			||||||
 | 
					    let date = new Date();
 | 
				
			||||||
 | 
					    console.log('[' + area + '] - ' + date.toISOString());
 | 
				
			||||||
 | 
					    if(text) console.log(text + '\n');
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
module.exports = function msToTime(duration) {
 | 
					export default function msToTime(duration : number) {
 | 
				
			||||||
    let seconds = Math.floor((duration / 1000) % 60),
 | 
					    let seconds = Math.floor((duration / 1000) % 60),
 | 
				
			||||||
        minutes = Math.floor((duration / (1000 * 60)) % 60),
 | 
					        minutes = Math.floor((duration / (1000 * 60)) % 60),
 | 
				
			||||||
        hours = Math.floor((duration / (1000 * 60 * 60)) % 24),
 | 
					        hours = Math.floor((duration / (1000 * 60 * 60)) % 24),
 | 
				
			||||||
@@ -1,61 +1,64 @@
 | 
				
			|||||||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
 | 
					import { ActionRowBuilder, ButtonBuilder, ButtonStyle, ChatInputCommandInteraction, EmbedBuilder, Guild, OAuth2Guild, StringSelectMenuInteraction } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { station } from "../classes/Stations";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = async function play(client, interaction, guild, station) {
 | 
					export default async function play(client: RadioClient, interaction: ChatInputCommandInteraction | StringSelectMenuInteraction | null, guild: OAuth2Guild | Guild | null, station: station) {
 | 
				
			||||||
    let message = {};
 | 
					    if(!guild) return;
 | 
				
			||||||
    const radio = client.radio.get(guild.id);
 | 
					
 | 
				
			||||||
    const audioPlayer = client.streamer.listen(station);
 | 
					    const radio = client.radio?.get(guild.id);
 | 
				
			||||||
 | 
					    const audioPlayer = client.streamer?.listen(station);
 | 
				
			||||||
    radio.connection.subscribe(audioPlayer);
 | 
					    radio.connection.subscribe(audioPlayer);
 | 
				
			||||||
    client.funcs.logger('Radio', guild.id + " / " + "Play" + " / " + radio.station.name);
 | 
					    client.funcs.logger('Radio', guild.id + " / " + "Play" + " / " + radio.station.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    message.nowplayingDescription = client.messages.nowplayingDescription.replace("%radio.station.name%", radio.station.name);
 | 
					 | 
				
			||||||
    message.nowplayingDescription = message.nowplayingDescription.replace("%radio.station.owner%", radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "");
 | 
					 | 
				
			||||||
    message.nowplayingDescription = message.nowplayingDescription.replace("%client.funcs.msToTime(completed)%", "");
 | 
					 | 
				
			||||||
    message.nowplayingDescription = message.nowplayingDescription.replace("**", "");
 | 
					 | 
				
			||||||
    message.nowplayingDescription = message.nowplayingDescription.replace("**", "");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const embed = new EmbedBuilder()
 | 
					    const embed = new EmbedBuilder()
 | 
				
			||||||
        .setTitle(client.user.username)
 | 
					        .setTitle(client.user?.username || "-")
 | 
				
			||||||
        .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messageEmojis["play"].replace(/[^0-9]+/g, '')))
 | 
					        .setThumbnail((radio.station.logo || "https://cdn.discordapp.com/emojis/" + client.messages.emojis["play"].replace(/[^0-9]+/g, '')))
 | 
				
			||||||
        .setColor(client.config.embedColor)
 | 
					        .setColor(client.config.embedColor)
 | 
				
			||||||
        .addFields({
 | 
					        .addFields({
 | 
				
			||||||
            name: client.messages.nowplayingTitle,
 | 
					            name: client.messages.nowplayingTitle,
 | 
				
			||||||
            value: message.nowplayingDescription
 | 
					            value: client.messages.replace(client.messages.nowplayingDescription, {
 | 
				
			||||||
 | 
					                "%radio.station.name%": radio.station.name,
 | 
				
			||||||
 | 
					                "%radio.station.owner%\n": radio.station.name != radio.station.owner ? radio.station.owner + "\n" : "",
 | 
				
			||||||
 | 
					                "%client.funcs.msToTime(completed)%": "",
 | 
				
			||||||
 | 
					                "**": "",
 | 
				
			||||||
 | 
					                "**:2": ""
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
        .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
					        .setImage('https://waren.io/berriabot-temp-sa7a36a9xm6837br/images/empty-3.png')
 | 
				
			||||||
        .setFooter({
 | 
					        .setFooter({
 | 
				
			||||||
            text: client.messages.footerText,
 | 
					            text: client.messages.footerText,
 | 
				
			||||||
            iconURL: "https://cdn.discordapp.com/emojis/" + client.messageEmojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
					            iconURL: "https://cdn.discordapp.com/emojis/" + client.messages.emojis["eximiabots"].replace(/[^0-9]+/g, '')
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const buttons = new ActionRowBuilder()
 | 
					    const buttons = new ActionRowBuilder<ButtonBuilder>()
 | 
				
			||||||
        .addComponents(
 | 
					        .addComponents(
 | 
				
			||||||
            new ButtonBuilder()
 | 
					            new ButtonBuilder()
 | 
				
			||||||
                .setCustomId('list')
 | 
					                .setCustomId('list')
 | 
				
			||||||
                .setEmoji(client.messageEmojis["list"])
 | 
					                .setEmoji(client.messages.emojis["list"])
 | 
				
			||||||
                .setStyle(ButtonStyle.Secondary)
 | 
					                .setStyle(ButtonStyle.Secondary)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .addComponents(
 | 
					        .addComponents(
 | 
				
			||||||
            new ButtonBuilder()
 | 
					            new ButtonBuilder()
 | 
				
			||||||
                .setCustomId('prev')
 | 
					                .setCustomId('prev')
 | 
				
			||||||
                .setEmoji(client.messageEmojis["prev"])
 | 
					                .setEmoji(client.messages.emojis["prev"])
 | 
				
			||||||
                .setStyle(ButtonStyle.Secondary)
 | 
					                .setStyle(ButtonStyle.Secondary)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .addComponents(
 | 
					        .addComponents(
 | 
				
			||||||
            new ButtonBuilder()
 | 
					            new ButtonBuilder()
 | 
				
			||||||
                .setCustomId('stop')
 | 
					                .setCustomId('stop')
 | 
				
			||||||
                .setEmoji(client.messageEmojis["stop"])
 | 
					                .setEmoji(client.messages.emojis["stop"])
 | 
				
			||||||
                .setStyle(ButtonStyle.Secondary)
 | 
					                .setStyle(ButtonStyle.Secondary)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .addComponents(
 | 
					        .addComponents(
 | 
				
			||||||
            new ButtonBuilder()
 | 
					            new ButtonBuilder()
 | 
				
			||||||
                .setCustomId('next')
 | 
					                .setCustomId('next')
 | 
				
			||||||
                .setEmoji(client.messageEmojis["next"])
 | 
					                .setEmoji(client.messages.emojis["next"])
 | 
				
			||||||
                .setStyle(ButtonStyle.Secondary)
 | 
					                .setStyle(ButtonStyle.Secondary)
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        .addComponents(
 | 
					        .addComponents(
 | 
				
			||||||
            new ButtonBuilder()
 | 
					            new ButtonBuilder()
 | 
				
			||||||
                .setCustomId('statistics')
 | 
					                .setCustomId('statistics')
 | 
				
			||||||
                .setEmoji(client.messageEmojis["statistics"])
 | 
					                .setEmoji(client.messages.emojis["statistics"])
 | 
				
			||||||
                .setStyle(ButtonStyle.Secondary)
 | 
					                .setStyle(ButtonStyle.Secondary)
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -70,10 +73,10 @@ module.exports = async function play(client, interaction, guild, station) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    message.play = client.messages.play.replace("%radio.station.name%", radio.station.name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    interaction?.reply({
 | 
					    interaction?.reply({
 | 
				
			||||||
        content: client.messageEmojis["play"] + message.play,
 | 
					        content: client.messages.emojis["play"] + client.messages.replace(client.messages.play, {
 | 
				
			||||||
 | 
					            "%radio.station.name%": radio.station.name
 | 
				
			||||||
 | 
					        }),
 | 
				
			||||||
        ephemeral: true
 | 
					        ephemeral: true
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1,18 +0,0 @@
 | 
				
			|||||||
module.exports = function saveState(client, guild, radio){
 | 
					 | 
				
			||||||
    client.datastore.checkEntry(guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let date = new Date();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let data = client.datastore.getEntry(guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    data.state = {};
 | 
					 | 
				
			||||||
    data.state.channels = {};
 | 
					 | 
				
			||||||
    data.state.channels.text = radio.textChannel.id;
 | 
					 | 
				
			||||||
    data.state.channels.voice = radio.voiceChannel.id;
 | 
					 | 
				
			||||||
    data.state.date = date.toISOString();
 | 
					 | 
				
			||||||
    data.state.station = {};
 | 
					 | 
				
			||||||
    data.state.station.name = radio.station.name;
 | 
					 | 
				
			||||||
    data.state.station.owner = radio.station.owner;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    client.datastore.updateEntry(guild, data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										26
									
								
								src/client/funcs/saveState.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/client/funcs/saveState.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					import { Guild } from "discord.js";
 | 
				
			||||||
 | 
					import RadioClient from "../../Client";
 | 
				
			||||||
 | 
					import { radio } from "../classes/Radio";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function saveState(client: RadioClient, guild: Guild, radio: radio){
 | 
				
			||||||
 | 
					    if(!client.datastore) return;
 | 
				
			||||||
 | 
					    client.datastore.checkEntry(guild.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let date = new Date();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    let data = client.datastore.getEntry(guild.id);
 | 
				
			||||||
 | 
					    if(!data) return;
 | 
				
			||||||
 | 
					    data.state = {
 | 
				
			||||||
 | 
					        channels: {
 | 
				
			||||||
 | 
					            text: radio.textChannel?.id,
 | 
				
			||||||
 | 
					            voice: radio.voiceChannel?.id
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        date: date.toISOString(),
 | 
				
			||||||
 | 
					        station: {
 | 
				
			||||||
 | 
					            name: radio.station.name,
 | 
				
			||||||
 | 
					            owner: radio.station.owner
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    client.datastore.updateEntry(guild, data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,4 +1,16 @@
 | 
				
			|||||||
module.exports = {
 | 
					export const messages = {
 | 
				
			||||||
 | 
					    replace(message: string, variables: { [key: string]: string }){
 | 
				
			||||||
 | 
					        for(let variable in variables){
 | 
				
			||||||
 | 
					            if(variable.includes('%')){
 | 
				
			||||||
 | 
					                message = message.replace(variable, variables[variable]);
 | 
				
			||||||
 | 
					            } else if(variable.includes(':')){
 | 
				
			||||||
 | 
					                message = message.replace(variable.split(':')[0], variables[variable]);
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                message = message.replace(variable, variables[variable]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return message;
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    wrongVoiceChannel: "You need to be in the same voice channel as RadioX to use this command!",
 | 
					    wrongVoiceChannel: "You need to be in the same voice channel as RadioX to use this command!",
 | 
				
			||||||
    noPerms: "You need the %command.permission% permission to use this command!",
 | 
					    noPerms: "You need the %command.permission% permission to use this command!",
 | 
				
			||||||
    notPlaying: "There is nothing playing!",
 | 
					    notPlaying: "There is nothing playing!",
 | 
				
			||||||
@@ -35,7 +47,17 @@ module.exports = {
 | 
				
			|||||||
    statusField4: ":hourglass: Latency",
 | 
					    statusField4: ":hourglass: Latency",
 | 
				
			||||||
    statusField5: ":globe_with_meridians: Hosted by",
 | 
					    statusField5: ":globe_with_meridians: Hosted by",
 | 
				
			||||||
    errorStationURL: "Station can't be URL",
 | 
					    errorStationURL: "Station can't be URL",
 | 
				
			||||||
    messageCommandsDeprecatedTitle: "%client.user.username%",
 | 
					    maintenance: "Shhhh... We are now sleeping and dreaming about new features to implement. Will be back soon.",
 | 
				
			||||||
    messageCommandsDeprecatedDescription: "We recommend you to reauthorize our bot by clicking the invite link down below, because Discord is planning to remove message content from verified bots [Read More](https://support-dev.discord.com/hc/en-us/articles/4404772028055)" + "\n\n" + "**Invite Bot**" + "\n" + "https://wgi.fi/radiox_invite" + "\n\n" + "This bot now supports slash commands, you should start using them instead. Type / into the message box and select the bot you wish to use. Remember to be careful as there are a few bugs here and there on Discord." + "\n\n" + "We will remove this deprecation message in March of 2022 when RadioX 1.0.0 is released.",
 | 
					    emojis: {
 | 
				
			||||||
    maintenance: "Shhhh... We are now sleeping and dreaming about new features to implement. Will be back soon."
 | 
					        logo: "<:RadioX:688765708808487072>",
 | 
				
			||||||
 | 
					        eximiabots: "<:EximiaBots:693277919929303132>",
 | 
				
			||||||
 | 
					        list: "<:RadioXList:688541155519889482>",
 | 
				
			||||||
 | 
					        play: "<:RadioXPlay:688541155712827458>",
 | 
				
			||||||
 | 
					        stop: "<:RadioXStop:688541155377414168>",
 | 
				
			||||||
 | 
					        statistics: "<:RadioXStatistics:694954485507686421>",
 | 
				
			||||||
 | 
					        maintenance: "<:RadioXMaintenance:695043843057254493>",
 | 
				
			||||||
 | 
					        error: "<:RadioXError:688541155792781320>",
 | 
				
			||||||
 | 
					        prev: "<:RadioXPrev:882153637370023957>",
 | 
				
			||||||
 | 
					        next: "<:RadioXNext:882153637474893834>"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@@ -1,3 +0,0 @@
 | 
				
			|||||||
export interface command { }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export interface radio {}
 | 
					 | 
				
			||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
require('dotenv/config');
 | 
					import { ColorResolvable } from "discord.js";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					export default {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //credentials
 | 
					    //credentials
 | 
				
			||||||
    token: process.env.DISCORD_TOKEN,
 | 
					    token: process.env.DISCORD_TOKEN,
 | 
				
			||||||
@@ -10,17 +10,17 @@ module.exports = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    //support
 | 
					    //support
 | 
				
			||||||
    supportGuild: "https://discord.gg/rRA65Mn",
 | 
					    supportGuild: "https://discord.gg/rRA65Mn",
 | 
				
			||||||
    devId: [
 | 
					    devIDs: [
 | 
				
			||||||
        "493174343484833802",
 | 
					        "493174343484833802",
 | 
				
			||||||
        "360363051792203779"
 | 
					        "360363051792203779"
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //misc
 | 
					    //misc
 | 
				
			||||||
    embedColor: "#88aa00",
 | 
					    embedColor: "#88aa00" as ColorResolvable,
 | 
				
			||||||
    hostedBy: "[Warén Group](https://waren.io)",
 | 
					    hostedBy: "[Warén Group](https://waren.io)",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //Settings
 | 
					    //Settings
 | 
				
			||||||
    version: process.env.DEV_MODE ? process.env.npm_package_version + "-dev" : process.env.npm_package_version,
 | 
					    version: process.env.DEV_MODE ? (process.env.npm_package_version ?? "0.0.0") + "-dev" : process.env.npm_package_version ?? "-",
 | 
				
			||||||
    debug: process.env.DEBUG_MODE || false,
 | 
					    debug: process.env.DEBUG_MODE || false,
 | 
				
			||||||
    devMode: process.env.DEV_MODE || false,
 | 
					    devMode: process.env.DEV_MODE || false,
 | 
				
			||||||
    maintenanceMode: false,
 | 
					    maintenanceMode: false,
 | 
				
			||||||
@@ -1,3 +0,0 @@
 | 
				
			|||||||
const { default: RadioClient } = require("./Client");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
const client = new RadioClient();
 | 
					 | 
				
			||||||
							
								
								
									
										3
									
								
								src/index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/index.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					import RadioClient from "./Client";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new RadioClient();
 | 
				
			||||||
		Reference in New Issue
	
	Block a user