Skip to content

Commit f3eee45

Browse files
committed
Merge branch 'ts-dev'
2 parents 18ae935 + 9245161 commit f3eee45

File tree

352 files changed

+14656
-4357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

352 files changed

+14656
-4357
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,11 @@ When your terminal is created, write `npm install` in your terminal to download
9292
If you encounter any error, make you sure that you have the latest version of nodejs or ask in the discord server.
9393

9494
__Step 3.__
95-
When the modules have been downloaded and a `node-modules` directory has been created, go to the `config.js` file and setup the bot.
95+
When the modules have been downloaded and a `node-modules` directory has been created, go to the `config.ts` file in the `src` folder and setup the bot.
9696
You can find some comments about every setting.
9797

9898
__Step 4.__
99-
Now, you can start the bot by pressing `F5` or putting `node index.js` in the terminal.
99+
Now, you can start the bot by pressing `F5` or putting `npm run start` in the terminal.
100100

101101
__Step 5.__
102102
Enjoy your bot !

index.js

Lines changed: 0 additions & 4 deletions
This file was deleted.

index.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//IMPORTANT: If you need help with the installation of Green-bot, you can join my server here: https://discord.gg/Q5QSbAHaXB for help
2+
3+
4+
import { Manager, ReClusterManager } from "discord-hybrid-sharding";
5+
import config from "./module/config";
6+
7+
const manager = new Manager("./module/src/cluster.js", {
8+
mode: "process",
9+
token: config.token,
10+
shardsPerClusters: 10
11+
});
12+
13+
manager.extend(
14+
new ReClusterManager({
15+
delay: 2000,
16+
timeout: -1,
17+
restartMode: 'gracefulSwitch',
18+
})
19+
)
20+
21+
manager.on("clusterCreate", (cluster) => {
22+
cluster.on("ready" ,()=>{
23+
if(config.debug) console.log("[Cluster Manager ==> Cluster] Cluster \""+cluster.id+"\" entered ready")
24+
})
25+
cluster.on("reconnecting",()=>{
26+
if(config.debug) console.log("[Cluster Manager ==> Cluster] Cluster \""+cluster.id+"\" is reconnecting to discord WS")
27+
})
28+
cluster.on('message', message => {
29+
console.log(message);
30+
if(message === "restart"){
31+
manager.recluster.start( {
32+
delay: 2000,
33+
timeout: -1,
34+
shardsPerClusters: 15,
35+
restartMode: 'gracefulSwitch'
36+
} );
37+
}
38+
})
39+
if(config.debug) console.log("[Cluster Manager ==> Cluster] Cluster \""+cluster.id+"\" created")
40+
})
41+
42+
manager
43+
.spawn({ timeout: -1 })
44+
.then(() => {
45+
console.log("[Cluster Manager] The bot is now ready and all shards are connected to discord Websocked.\nCurrent Debug Mode is set to: "+config.debug+"")
46+
})

module/SlashUpdate.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
const { REST } = require('@discordjs/rest');
2+
const { Routes } = require('discord-api-types/v9');
3+
import config from "./config"
4+
import { readdirSync } from "fs";
5+
6+
const { token } = require('./config.js');
7+
console.log('• Loading the commands to refresh');
8+
// the current amount of commands to refresh
9+
const commands = [];
10+
const x=-1;
11+
// peseudo load the commands to get the interaction data
12+
const files = readdirSync(`${__dirname}/src/interactions`, { withFileTypes: true });
13+
files.forEach(cat => {
14+
const dirFiles = readdirSync(`${__dirname}/src/interactions/${cat.name}`, { withFileTypes: true });
15+
dirFiles.forEach(async cmd => {
16+
if (cmd.name.endsWith(".map")) return;
17+
try {
18+
const command = new ((await import(`${__dirname}/src/interactions/${cat.name}/${cmd.name}`)).default)
19+
commands.push({
20+
name: command.name,
21+
description: command.description,
22+
options: command.arguments,
23+
})
24+
console.log(commands)
25+
} catch (error) {
26+
console.log(`[Command Handler] Cannot load file ${cmd.name}. Missing export default?: ${error}`)
27+
}
28+
29+
})
30+
})
31+
// stuffs are loaded, now lets log how many commands we have
32+
setTimeout(()=>{
33+
console.log(`• Loaded ${commands.length} slash commands to refresh`);
34+
// as per d.js guide, create a rest client
35+
const rest = new REST({ version: '9' }).setToken(config.token);
36+
// start the load up process
37+
(async () => {
38+
try {
39+
console.log(`• Refreshing client "946414667436269579" slash commands. Developer Mode? `);
40+
await rest.put(Routes.applicationCommands(config.botId), { body: commands });
41+
console.log(`• Success! Refreshed client "946414667436269579" slash commands`);
42+
} catch (error) {
43+
console.error(error);
44+
}
45+
})();
46+
})

config.js renamed to module/config.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
1-
module.exports = {
2-
//IMPORTANT: If you need help with the installation of Green-bot, you can join our support server here: https://green-bot.app/discord
1+
export default {
2+
//IMPORTANT: If you need help with the installation of Green-bot, you can join my server here: https://discord.gg/Q5QSbAHaXB for help
33
// Complete it carefuly else it won't work, check the readme for more informations
44
lavalink: [
55
{ name: "1", url: "LAVALINK_IP:PORT", auth: "LAVALINK_AUTH", secure: null },
66
],
7+
// Sends a lot of info into console.
8+
debug: false,
9+
botId: "",
710
// The prefix used to answer to commands
811
prefix: "*",
912
// Optional, for loading playlists with more than 100 tracks ( Else using a scaper )
1013
spotify: { clientId: "", clientSecret: "", cacheResults: !0, cacheLifetime: 36e5 },
1114
// The wrapper used to connect to the lavalink server: https://deivu.github.io/Shoukaku
1215
shoukaku: { moveOnDisconnect: !0, resumable: !0, closedEventDelay: 1e3, resumableTimeout: 500, reconnectTries: 5, restTimeout: 3e4 },
1316
// The database. Create a database on Atlas/ Your vps and copy the connection url here. Additional informations: https://www.mongodb.com/
14-
database: {
17+
mongo: {
1518
url: "mongodb://localhost:27017/test",
1619
options: {
1720
maxPoolSize: 200,

module/src/BaseDiscordClient.ts

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
import * as Eris from "eris";
2+
import dbl from "dblapi.js";
3+
import { ShoukakuHandler } from "./modules/ShoukakuHandler";
4+
import { QueueManager } from "./modules/Queue";
5+
import { EventHandler } from "./modules/EventHandler";
6+
import { Spotify } from "@tuneorg/spotify";
7+
import { CommandLoader } from "./modules/CommandHandler";
8+
import { DatabaseManager } from "./modules/DatabaseManager";
9+
import { BaseError } from "./abstract/BaseListener";
10+
import { Server } from "./modules/server";
11+
import { CommandManager } from "./modules/CommandService";
12+
import { voiceService } from "./modules/voiceService";
13+
import { Client } from "discord-hybrid-sharding";
14+
import { SlashManager } from "./modules/buttonHandler";
15+
import { CollectorManager } from "./modules/Collector";
16+
import { sweeperManager } from "./modules/sweeperManager";
17+
import { Context } from "./modules/Context";
18+
import { SlashContext } from "./modules/SlashContext";
19+
const Cluster = require("discord-hybrid-sharding");
20+
21+
22+
export class BaseDiscordClient extends Eris.Client {
23+
location: string;
24+
commands: CommandLoader;
25+
commandManager: CommandManager;
26+
database: DatabaseManager;
27+
config: any;
28+
collectors: CollectorManager;
29+
cluster: Client;
30+
voiceHandler: voiceService;
31+
shoukaku: ShoukakuHandler;
32+
dbl: dbl;
33+
events: EventHandler;
34+
server?: Server;
35+
sweepers: sweeperManager;
36+
spotify: Spotify;
37+
slashManager: SlashManager;
38+
queue: QueueManager;
39+
constructor(options: any) {
40+
41+
// Passing options for the eris client
42+
super(options.token,
43+
{
44+
firstShardID: Cluster.data.FIRST_SHARD_ID,
45+
lastShardID: Cluster.data.LAST_SHARD_ID,
46+
maxShards: Cluster.data.TOTAL_SHARDS,
47+
restMode: true,
48+
largeThreshold: 1000000,
49+
guildCreateTimeout: 1000,
50+
allowedMentions: { everyone: false, roles: false, users: false },
51+
autoreconnect: true,
52+
intents: ["guilds", "guildVoiceStates", "guildMessages"],
53+
connectionTimeout: 40000,
54+
maxResumeAttempts: 40,
55+
messageLimit: 0,
56+
disableEvents: {
57+
"TYPING_START": true,
58+
"USER_NOTE_UPDATE": true,
59+
"CHANNEL_PINS_UPDATE": true,
60+
"MESSAGE_UPDATE": true,
61+
"RELATIONSHIP_ADD": true,
62+
"RELATIONSHIP_REMOVE": true,
63+
"GUILD_UPDATE": true,
64+
"CHANNEL_CREATE": true,
65+
"CHANNEL_UPDATE": true,
66+
"CHANNEL_DELETE": true,
67+
"CHANNEL_OVERWRITE_CREATE": true,
68+
"CHANNEL_OVERWRITE_UPDATE": true,
69+
"CHANNEL_OVERWRITE_DELETE": true,
70+
"MEMBER_KICK": true,
71+
"MEMBER_PRUNE": true,
72+
"MEMBER_BAN_ADD": true,
73+
"MEMBER_BAN_REMOVE": true,
74+
"MEMBER_UPDATE": true,
75+
"MEMBER_ROLE_UPDATE": true,
76+
"BOT_ADD ": true,
77+
"ROLE_CREATE": true,
78+
"ROLE_UPDATE": true,
79+
"ROLE_DELETE": true,
80+
"INVITE_CREATE": true,
81+
"INVITE_UPDATE ": true,
82+
"INVITE_DELETE ": true,
83+
"WEBHOOK_CREATE": true,
84+
"WEBHOOK_UPDATE": true,
85+
"WEBHOOK_DELETE": true,
86+
"EMOJI_CREATE": true,
87+
"EMOJI_UPDATE": true,
88+
"EMOJI_DELETE": true,
89+
"MESSAGE_DELETE": true,
90+
"MESSAGE_BULK_DELETE": true,
91+
"MESSAGE_PIN": true,
92+
"MESSAGE_UNPIN": true,
93+
"INTEGRATION_CREATE": true,
94+
"INTEGRATION_UPDATE": true,
95+
"INTEGRATION_DELETE": true,
96+
"STAGE_INSTANCE_CREATE": true,
97+
"STAGE_INSTANCE_UPDATE": true,
98+
"STAGE_INSTANCE_DELETE": true,
99+
"STICKER_CREATE": true,
100+
"STICKER_UPDATE": true,
101+
"STICKER_DELETE": true,
102+
"GUILD_SCHEDULED_EVENT_CREATE": true,
103+
"GUILD_SCHEDULED_EVENT_UPDATE": true,
104+
"GUILD_SCHEDULED_EVENT_DELETE": true,
105+
"THREAD_CREATE": true,
106+
"THREAD_UPDATE": true,
107+
"THREAD_DELETE": true,
108+
"APPLICATION_COMMAND_PERMISSION_UPDATE": true,
109+
},
110+
});
111+
112+
// Core Things //
113+
this.config = options;
114+
this.shoukaku = new ShoukakuHandler(this);
115+
this.location = process.cwd();
116+
this.spotify = new Spotify(options.spotify);
117+
this.dbl = new dbl(options.dbl, this);
118+
this.cluster = new Cluster.Client(this);
119+
this.collectors = new CollectorManager();
120+
121+
122+
// Command/Slash Manager //
123+
this.commands = new CommandLoader(this);
124+
this.commandManager = new CommandManager(this);
125+
this.slashManager = new SlashManager(this);
126+
127+
// Listenners for events //
128+
this.voiceHandler = new voiceService(this);
129+
this.on("voiceChannelJoin", (member, newChannel) => this.voiceHandler.handle("join", member, newChannel));
130+
this.on("voiceChannelLeave", (member, oldChannel) => this.voiceHandler.handle("leave", member, oldChannel));
131+
this.on("voiceChannelSwitch", (member, newChannel, oldChannel) => this.voiceHandler.handle("switch", member, newChannel, oldChannel));
132+
133+
this.on("messageCreate", m => this.commandManager.handle(m));
134+
this.on("interactionCreate", i => this.slashManager.handle(i))
135+
this.on("error", (err) => {
136+
if (err.toString().includes("Connection reset by peer")) return
137+
console.log(err)
138+
})
139+
140+
// Database //
141+
this.database = new DatabaseManager(this);
142+
143+
// Shoukaku ( For music )
144+
this.queue = new QueueManager(this);
145+
// Events
146+
this.events = new EventHandler(this);
147+
148+
if (this.cluster.maintenance) console.log("[Maitainance Mode] Cluster is in maitainance")
149+
150+
this.sweepers = new sweeperManager(this, {
151+
sweep: ["client", "emojis", "guildCategories", "stickers", "useless", "guildMembers"],
152+
timeout: 1000 * 60 * 60 * 10,
153+
changeStatus: "*help | green-bot.app"
154+
})
155+
}
156+
listenners(debug: boolean) {
157+
const _list = debug ? ["multipleResolves", "uncaughtException", "uncaughtExceptionMonitor", "unhandledRejection", "warning"] : ["uncaughtException", "uncaughtExceptionMonitor", "unhandledRejection"];
158+
_list.forEach((event) => {
159+
process.on(event, new BaseError(event).handler)
160+
})
161+
return Promise;
162+
}
163+
164+
hasBotPerm(context: Context | SlashContext, perm: any, channelVoice?: Eris.TextVoiceChannel) {
165+
if (context.me.permissions.has("administrator")) return true;
166+
const channel = channelVoice || context.channel;
167+
let hasPerm = false;
168+
if (perm === "voiceConnect" && !this.hasBotPerm(context, "viewChannel", channelVoice)) return false
169+
const owerwrites = channel.permissionOverwrites.filter(ow => ow.id === this.user.id || context.me.roles.includes(ow.id))
170+
if (!owerwrites.length && perm !== "viewChannel" && context.me.permissions.has(perm)) return true
171+
if (!owerwrites.length && channel.permissionsOf(context.me).has(perm)) return true
172+
owerwrites.forEach(owerwrite => {
173+
if (hasPerm === true || hasPerm === false) return;
174+
const data = owerwrite.json
175+
if (data[perm] === undefined) return
176+
if (data[perm] === true) return hasPerm = true;
177+
if (data[perm] === false) return hasPerm = false;
178+
})
179+
180+
if (!hasPerm && context.me.permissions.has(perm)) return true
181+
if (!hasPerm && channel.permissionsOf(context.me).has(perm)) return true
182+
183+
return hasPerm;
184+
}
185+
186+
187+
188+
189+
async init() {
190+
await this.connect();
191+
await this.database.connect();
192+
}
193+
}
194+

module/src/abstract/BaseCommand.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Constants } from "eris";
2+
3+
class Argument{
4+
name:string;
5+
required:boolean;
6+
description: string;
7+
}
8+
9+
class CommandCheck{
10+
vote: boolean;
11+
premium: boolean;
12+
voice: boolean;
13+
channel: boolean;
14+
dispatcher: boolean;
15+
}
16+
17+
export class BaseCommand {
18+
name: string;
19+
permissions: Array<string>;
20+
description: string;
21+
checks: CommandCheck;
22+
aliases: Array<string>;
23+
arguments: Array<Argument>;
24+
run: Function;
25+
26+
constructor(commandData) {
27+
}
28+
}

module/src/abstract/BaseEvent.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const EventEmitter = require("events");
2+
export class BaseEvent extends EventEmitter {
3+
once: boolean;
4+
name: string
5+
constructor(event) {
6+
super();
7+
this.name = event.name;
8+
this.once = event.once;
9+
}
10+
exec(...e) {
11+
this.run(...e).catch((e) => this.emit("error", e));
12+
}
13+
}
14+

module/src/abstract/BaseListener.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export class BaseError{
2+
name: any;
3+
constructor(name){
4+
this.name = name;
5+
}
6+
7+
handler(err){
8+
console.log(err)
9+
return console.log(`[${this.name || "Process<Unknownn>"}] ${err}`)
10+
}
11+
}

0 commit comments

Comments
 (0)