1
0
mirror of https://github.com/toast-ts/Daggerbot-TS.git synced 2024-11-17 16:30:58 -05:00
Daggerbot-TS/src/client.ts

217 lines
9.5 KiB
TypeScript
Raw Normal View History

2023-05-07 04:41:20 -04:00
import Discord, {Client, WebhookClient, GatewayIntentBits, Partials} from 'discord.js';
2023-05-23 01:14:17 -04:00
import {readFileSync, readdirSync} from 'node:fs';
2023-04-14 06:47:58 -04:00
import {exec} from 'node:child_process';
2023-02-24 19:55:11 -05:00
import mongoose from 'mongoose';
2023-05-07 04:41:20 -04:00
import {formatTimeOpt, Tokens, Config, repeatedMessages, MPServerCache} from './typings/interfaces';
2023-04-14 06:47:58 -04:00
import bannedWords from './models/bannedWords.js';
import userLevels from './models/userLevels.js';
import suggestion from './models/suggestion.js';
import punishments from './models/punishments.js';
import bonkCount from './models/bonkCount.js';
import MPServer from './models/MPServer.js';
import xjs from 'xml-js';
2022-12-18 23:22:28 -05:00
import axios from 'axios';
import moment from 'moment';
2023-07-20 08:13:09 -04:00
const tokens = JSON.parse(readFileSync('src/tokens.json', {encoding:'utf8'}));
// Import assertion warning workaround yes
2023-01-06 19:41:20 -05:00
let importconfig:Config
try{
2023-05-23 01:14:17 -04:00
importconfig = JSON.parse(readFileSync('src/DB-Beta.config.json', {encoding:'utf8'}));
2023-03-05 05:04:10 -05:00
console.log('Using development config :: Daggerbot Beta')
2023-01-06 19:41:20 -05:00
} catch(e){
2023-05-23 01:14:17 -04:00
importconfig = JSON.parse(readFileSync('src/config.json', {encoding:'utf8'}))
2023-03-05 05:04:10 -05:00
console.log('Using production config')
2023-01-06 19:41:20 -05:00
}
2023-01-27 21:33:55 -05:00
export default class TClient extends Client {
2023-03-05 05:04:10 -05:00
invites: Map<any, any>;
commands: Discord.Collection<string, any>;
registry: Array<Discord.ApplicationCommandDataResolvable>;
config: Config;
tokens: Tokens;
YTCache: any;
embed: typeof Discord.EmbedBuilder;
collection: any;
messageCollector: any;
attachmentBuilder: any;
moment: typeof moment;
2023-04-14 06:47:58 -04:00
xjs: typeof xjs;
2023-03-05 05:04:10 -05:00
axios: typeof axios;
ms: any;
userLevels: userLevels;
punishments: punishments;
bonkCount: bonkCount;
bannedWords: bannedWords;
MPServer: MPServer;
2023-05-07 04:41:20 -04:00
MPServerCache: MPServerCache;
2023-03-05 05:04:10 -05:00
suggestion: suggestion;
repeatedMessages: repeatedMessages;
statsGraph: number;
2022-11-11 19:58:11 -05:00
2023-03-05 05:04:10 -05:00
constructor(){
super({
intents: [
GatewayIntentBits.Guilds, GatewayIntentBits.GuildMembers,
GatewayIntentBits.GuildModeration, GatewayIntentBits.GuildInvites,
GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.GuildPresences,
2023-06-24 13:47:42 -04:00
GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessages,
GatewayIntentBits.GuildVoiceStates
], partials: [
Partials.Channel, Partials.Reaction, Partials.Message
], allowedMentions: {users:[],roles:[]}
2023-03-05 05:04:10 -05:00
})
this.invites = new Map();
this.commands = new Discord.Collection();
this.registry = [];
this.config = importconfig as Config;
this.tokens = tokens as Tokens;
this.YTCache = {
'UCQ8k8yTDLITldfWYKDs3xFg': undefined, // Daggerwin
'UCguI73--UraJpso4NizXNzA': undefined // Machinery Restorer
2022-11-11 19:58:11 -05:00
}
2023-03-05 05:04:10 -05:00
this.embed = Discord.EmbedBuilder;
this.collection = Discord.Collection;
this.messageCollector = Discord.MessageCollector;
this.attachmentBuilder = Discord.AttachmentBuilder;
this.moment = moment;
2023-04-14 06:47:58 -04:00
this.xjs = xjs;
2023-03-05 05:04:10 -05:00
this.axios = axios;
2023-04-14 06:47:58 -04:00
this.ms = import('ms').then(i=>i);
2023-03-05 05:04:10 -05:00
this.userLevels = new userLevels(this);
this.bonkCount = new bonkCount(this);
this.punishments = new punishments(this);
this.bannedWords = new bannedWords(this);
this.MPServer = new MPServer(this);
2023-05-20 03:17:23 -04:00
this.MPServerCache = {players: [], status: null, name: null} as MPServerCache;
2023-03-05 05:04:10 -05:00
this.suggestion = new suggestion(this);
this.repeatedMessages = {};
this.setMaxListeners(45);
2023-03-05 05:04:10 -05:00
this.statsGraph = -60;
}
async init(){
console.time('Startup');
mongoose.set('strictQuery', true);
await mongoose.connect(this.tokens.mongodb_uri, {
replicaSet: 'toastyy',
autoIndex: true,
2023-05-20 03:17:23 -04:00
authMechanism: 'DEFAULT',
2023-05-15 21:21:25 -04:00
authSource: 'admin',
2023-03-05 05:04:10 -05:00
serverSelectionTimeoutMS: 15000,
waitQueueTimeoutMS: 50000,
socketTimeoutMS: 30000,
2023-07-21 10:17:27 -04:00
tls: false,
2023-03-05 05:04:10 -05:00
family: 4
}).then(()=>console.log(this.logTime(), 'Successfully connected to MongoDB')).catch(err=>{console.error(this.logTime(), `Failed to connect to MongoDB\n${err}`); exec('pm2 stop Daggerbot')})
2023-06-09 21:12:15 -04:00
this.login(this.tokens.main);
2023-05-23 01:14:17 -04:00
for await (const file of readdirSync('dist/events')){
2023-04-14 06:47:58 -04:00
const eventFile = await import(`./events/${file}`);
2023-04-21 02:20:01 -04:00
this.on(file.replace('.js',''), async(...args)=>eventFile.default.run(this,...args))
};
2023-05-23 01:14:17 -04:00
for await (const file of readdirSync('dist/commands')){
2023-04-14 06:47:58 -04:00
const command = await import(`./commands/${file}`);
2023-04-21 02:20:01 -04:00
this.commands.set(command.default.data.name,{command, uses: 0});
2023-03-05 05:04:10 -05:00
this.registry.push(command.default.data.toJSON())
2023-04-21 02:20:01 -04:00
};
2023-03-05 05:04:10 -05:00
}
formatTime(integer: number, accuracy = 1, options?: formatTimeOpt){
let achievedAccuracy = 0;
let text:any = '';
for (const timeName of [
{name: 'year', length: 31536000000},
{name: 'month', length: 2592000000},
{name: 'week', length: 604800000},
{name: 'day', length: 86400000},
{name: 'hour', length: 3600000},
{name: 'minute', length: 60000},
{name: 'second', length: 1000}
]){
2023-03-05 05:04:10 -05:00
if (achievedAccuracy < accuracy){
const fullTimelengths = Math.floor(integer/timeName.length);
if (fullTimelengths === 0) continue;
2023-03-05 05:04:10 -05:00
achievedAccuracy++;
text += fullTimelengths + (options?.longNames ? (' '+timeName.name+(fullTimelengths === 1 ? '' : 's')) : timeName.name.slice(0, timeName.name === 'month' ? 2 : 1)) + (options?.commas ? ', ' : ' ');
integer -= fullTimelengths*timeName.length;
} else break;
2022-11-11 19:58:11 -05:00
}
2023-03-05 05:04:10 -05:00
if (text.length == 0) text = integer + (options?.longNames ? ' milliseconds' : 'ms') + (options?.commas ? ', ' : '');
if (options?.commas){
text = text.slice(0, -2);
if (options?.longNames){
text = text.split('');
text[text.lastIndexOf(',')] = ' and';
text = text.join('');
}
} return text.trim();
}
2023-05-07 04:41:20 -04:00
formatPlayerUptime(oldTime:number){
var Hours=0;
oldTime=Math.floor(Number(oldTime));
if(oldTime>=60){
var Hours=Math.floor(Number(oldTime)/60);
var Minutes=(Number(oldTime)-(Hours*60));
} else Minutes=Number(oldTime)
if(Hours>=24){
var Days=Math.floor(Number(Hours)/24);
var Hours=(Hours-(Days*24));
} return (Days>0?Days+' d ':'')+(Hours>0?Hours+' h ':'')+(Minutes>0?Minutes+' m':'')
}
2023-03-05 05:04:10 -05:00
isStaff = (guildMember:Discord.GuildMember)=>this.config.mainServer.staffRoles.map((x: string)=>this.config.mainServer.roles[x]).some((x: string)=>guildMember.roles.cache.has(x));
youNeedRole = (interaction:Discord.CommandInteraction, role:string)=>interaction.reply(`This command is restricted to <@&${this.config.mainServer.roles[role]}>`);
2022-12-01 17:53:57 -05:00
2023-03-05 05:04:10 -05:00
logTime = ()=>`[${this.moment().format('DD/MM/YY HH:mm:ss')}]`;
2022-12-01 17:53:57 -05:00
2023-05-07 04:41:20 -04:00
async punish(interaction: Discord.ChatInputCommandInteraction<'cached'>, type: string){
if (!this.isStaff(interaction.member as Discord.GuildMember)) return this.youNeedRole(interaction, "dcmod");
2023-03-05 05:04:10 -05:00
const time = interaction.options.getString('time') ?? undefined;
const reason = interaction.options.getString('reason') ?? 'Reason unspecified';
const GuildMember = interaction.options.getMember('member') ?? undefined;
const User = interaction.options.getUser('member', true);
2023-05-07 04:41:20 -04:00
console.log(this.logTime(), `[PunishmentLog] ${GuildMember?.user?.username ?? User?.username ?? 'No user data'} ${time ? ['warn', 'kick'].includes(this.punishments.type) ? 'and no duration set' : `and ${time} (duration)` : ''} was used in /${interaction.commandName} for ${reason}`);
(this.channels.cache.get(this.config.mainServer.channels.punishment_log) as Discord.TextChannel).send({embeds:[new this.embed().setColor(this.config.embedColor).setAuthor({name: interaction?.user?.username, iconURL: interaction?.user?.displayAvatarURL({size:2048})}).setTitle('Punishment Log').setDescription(`${GuildMember?.user?.username ?? User?.username ?? 'No user data'} ${time ? ['warn', 'kick'].includes(this.punishments.type) ? 'and no duration set' : `and ${time} (duration)` : ''} was used in \`/${interaction.commandName}\` for \`${reason}\``).setTimestamp()]});
if (interaction.user.id === User.id) return interaction.reply(`You cannot ${type} yourself.`);
if (!GuildMember && type != 'unban') return interaction.reply(`You cannot ${type} someone who is not in the server.`);
2023-03-05 05:04:10 -05:00
if (User.bot) return interaction.reply(`You cannot ${type} a bot!`);
await interaction.deferReply();
2023-05-07 04:41:20 -04:00
await this.punishments.addPunishment(type, { time, interaction }, interaction.user.id, reason, User, GuildMember);
2023-03-05 05:04:10 -05:00
}
async YTLoop(YTChannelID: string, YTChannelName: string, DCChannelID: string){
let Data:any;
try {
await this.axios.get(`https://www.youtube.com/feeds/videos.xml?channel_id=${YTChannelID}`, {timeout: 5000}).then(xml=>Data = this.xjs.xml2js(xml.data, {compact: true}))
2023-03-05 05:04:10 -05:00
} catch(err){
console.log(this.logTime(), `${YTChannelName} YT fail`)
2022-11-13 08:46:50 -05:00
}
2023-03-05 05:04:10 -05:00
if (!Data) return;
if (this.YTCache[YTChannelID] === undefined){
2023-03-05 05:04:10 -05:00
this.YTCache[YTChannelID] = Data.feed.entry[0]['yt:videoId']._text;
return;
2022-11-13 08:46:50 -05:00
}
if (Data.feed.entry[1]['yt:videoId']._text === this.YTCache[YTChannelID]){
2023-03-05 05:04:10 -05:00
this.YTCache[YTChannelID] = Data.feed.entry[0]['yt:videoId']._text;
(this.channels.resolve(DCChannelID) as Discord.TextChannel).send(`**${YTChannelName}** just uploaded a video!\n${Data.feed.entry[0].link._attributes.href}`)
}
}
2023-06-24 13:47:42 -04:00
// Bytes conversion
formatBytes(bytes:number, decimals:number = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals < 0 ? 0 : decimals)) + ' ' + ['Bytes', 'KB', 'MB', 'GB'][i];
2023-06-24 13:47:42 -04:00
};
}
2023-03-05 05:04:10 -05:00
export class WClient extends WebhookClient {
tokens: Tokens;
constructor(){
super({url: tokens.webhook_url})
2023-04-14 06:47:58 -04:00
this.tokens = tokens as Tokens;
2023-03-05 05:04:10 -05:00
}
}