2022-11-13 08:46:50 -05:00
import Discord , { Client , GatewayIntentBits , Partials } from 'discord.js' ;
import fs from 'node:fs' ;
2022-11-13 19:18:15 -05:00
import timeNames from './timeNames' ;
2023-01-27 21:33:55 -05:00
import { Punishment , formatTimeOpt , Tokens , Config } from './typings/interfaces' ;
import { bannedWords , bonkCount , userLevels , punishments } from './schoolClassroom' ;
2022-11-22 05:45:55 -05:00
import MPDB from './models/MPServer' ;
2022-12-18 23:22:28 -05:00
import axios from 'axios' ;
import moment from 'moment' ;
2022-12-29 05:10:13 -05:00
import tokens from './tokens.json' ;
2023-01-06 19:41:20 -05:00
let importconfig :Config
try {
importconfig = require ( './DB-Beta.config.json' )
console . log ( 'Using development config : Daggerbot Beta' )
2023-01-11 03:33:38 -05:00
//importconfig = require('./Toast-Testbot.config.json')
//console.log('Using development config : Toast-Testbot')
2023-01-06 19:41:20 -05:00
} catch ( e ) {
importconfig = require ( './config.json' )
console . log ( 'Using production config' )
}
2023-01-27 21:33:55 -05:00
export default class TClient extends Client {
2022-11-14 03:45:40 -05:00
invites : Map < any , any > ;
commands : Discord.Collection < string , any > ;
registry : Array < Discord.ApplicationCommandDataResolvable > ;
2022-12-29 05:10:13 -05:00
config : Config ;
tokens : Tokens ;
2022-11-11 19:58:11 -05:00
YTCache : any ;
2022-11-14 03:45:40 -05:00
embed : typeof Discord . EmbedBuilder ;
2022-11-11 19:58:11 -05:00
collection : any ;
messageCollector : any ;
attachmentBuilder : any ;
2022-12-18 23:22:28 -05:00
moment : typeof moment ;
2022-11-13 08:46:50 -05:00
xjs : any ;
2022-12-18 23:22:28 -05:00
axios : typeof axios ;
2022-11-15 09:06:18 -05:00
ms : any ;
2022-11-14 03:45:40 -05:00
userLevels : userLevels ;
punishments : punishments ;
bonkCount : bonkCount ;
bannedWords : bannedWords ;
2022-11-11 19:58:11 -05:00
repeatedMessages : any ;
2023-01-22 06:21:32 -05:00
statsGraph : number ;
2022-11-11 19:58:11 -05:00
constructor ( ) {
super ( {
intents : [
GatewayIntentBits . Guilds , GatewayIntentBits . GuildMembers ,
GatewayIntentBits . GuildBans , GatewayIntentBits . GuildInvites ,
2022-11-26 17:18:40 -05:00
GatewayIntentBits . GuildPresences , GatewayIntentBits . MessageContent , GatewayIntentBits . GuildMessages
2022-11-11 19:58:11 -05:00
] ,
partials : [
Partials . Channel ,
Partials . Reaction ,
Partials . Message
] ,
2022-11-17 12:58:19 -05:00
allowedMentions : { users : [ ] , roles : [ ] }
2022-11-11 19:58:11 -05:00
} )
this . invites = new Map ( ) ;
this . commands = new Discord . Collection ( ) ;
2022-11-14 03:45:40 -05:00
this . registry = [ ] ;
2023-01-06 19:41:20 -05:00
this . config = importconfig as Config ;
2022-12-29 05:10:13 -05:00
this . tokens = tokens as Tokens ;
2022-11-11 19:58:11 -05:00
this . YTCache = {
'UCQ8k8yTDLITldfWYKDs3xFg' : undefined , // Daggerwin
2022-11-18 23:29:01 -05:00
'UCguI73--UraJpso4NizXNzA' : undefined // Machinery Restorer
2022-11-11 19:58:11 -05:00
}
this . embed = Discord . EmbedBuilder ;
this . collection = Discord . Collection ;
this . messageCollector = Discord . MessageCollector ;
this . attachmentBuilder = Discord . AttachmentBuilder ;
2022-12-18 23:22:28 -05:00
this . moment = moment ;
2022-11-16 13:53:42 -05:00
this . xjs = require ( 'xml-js' ) ;
2022-12-18 23:22:28 -05:00
this . axios = axios ;
2022-11-16 13:53:42 -05:00
this . ms = require ( 'ms' ) ;
2022-11-15 09:06:18 -05:00
this . userLevels = new userLevels ( this ) ;
this . bonkCount = new bonkCount ( this ) ;
this . punishments = new punishments ( this ) ;
this . bannedWords = new bannedWords ( this ) ;
2022-11-11 19:58:11 -05:00
this . repeatedMessages = { } ;
2023-01-22 06:21:32 -05:00
this . setMaxListeners ( 80 ) ;
this . statsGraph = - 60 ;
2022-11-11 19:58:11 -05:00
}
async init ( ) {
2022-11-22 05:45:55 -05:00
MPDB . sync ( ) ;
2022-11-22 16:51:00 -05:00
this . login ( this . tokens . token_main ) ;
2022-11-11 19:58:11 -05:00
this . punishments . initLoad ( ) ;
this . bannedWords . initLoad ( ) ;
this . bonkCount . initLoad ( ) ;
2023-01-27 21:42:15 -05:00
this . userLevels . initLoad ( ) . intervalSave ( 30000 ) . disableSaveNotifs ( ) ;
2022-11-16 13:53:42 -05:00
const commandFiles = fs . readdirSync ( 'src/commands' ) . filter ( file = > file . endsWith ( '.ts' ) ) ;
2022-11-14 03:45:40 -05:00
for ( const file of commandFiles ) {
2022-11-16 13:53:42 -05:00
const command = require ( ` ./commands/ ${ file } ` ) ;
this . commands . set ( command . default . data . name , command )
this . registry . push ( command . default . data . toJSON ( ) )
2022-11-14 03:45:40 -05:00
}
2022-11-11 19:58:11 -05:00
}
2022-11-17 12:58:19 -05:00
formatPunishmentType ( punishment : Punishment , client : TClient , cancels? : Punishment ) {
2022-11-11 19:58:11 -05:00
if ( punishment . type == 'removeOtherPunishment' ) {
2022-11-13 08:46:50 -05:00
cancels || = this . punishments . _content . find ( ( x : Punishment ) = > x . id === punishment . cancels )
2022-11-11 19:58:11 -05:00
return cancels . type [ 0 ] . toUpperCase ( ) + cancels . type . slice ( 1 ) + ' Removed' ;
} else return punishment . type [ 0 ] . toUpperCase ( ) + punishment . type . slice ( 1 ) ;
}
2022-11-13 08:46:50 -05:00
formatTime ( integer : number , accuracy = 1 , options? : formatTimeOpt ) {
2022-11-11 19:58:11 -05:00
let achievedAccuracy = 0 ;
2022-11-15 09:06:18 -05:00
let text :any = '' ;
2022-11-11 19:58:11 -05:00
for ( const timeName of timeNames ) {
if ( achievedAccuracy < accuracy ) {
const fullTimelengths = Math . floor ( integer / timeName . length ) ;
if ( fullTimelengths == 0 ) continue ;
achievedAccuracy ++ ;
2022-11-17 12:58:19 -05:00
text += fullTimelengths + ( options ? . longNames ? ( ' ' + timeName . name + ( fullTimelengths === 1 ? '' : 's' ) ) : timeName . name . slice ( 0 , timeName . name === 'month' ? 2 : 1 ) ) + ( options ? . commas ? ', ' : ' ' ) ;
2022-11-11 19:58:11 -05:00
integer -= fullTimelengths * timeName . length ;
} else {
break ;
}
}
2022-11-13 08:46:50 -05:00
if ( text . length == 0 ) text = integer + ( options ? . longNames ? ' milliseconds' : 'ms' ) + ( options ? . commas ? ', ' : '' ) ;
if ( options ? . commas ) {
2022-11-11 19:58:11 -05:00
text = text . slice ( 0 , - 2 ) ;
2022-11-13 08:46:50 -05:00
if ( options ? . longNames ) {
2022-11-11 19:58:11 -05:00
text = text . split ( '' ) ;
text [ text . lastIndexOf ( ',' ) ] = ' and' ;
text = text . join ( '' ) ;
}
} return text . trim ( ) ;
}
2022-11-13 08:46:50 -05:00
isStaff ( guildMember : Discord.GuildMember ) {
return this . config . mainServer . staffRoles . map ( ( x : string ) = > this . config . mainServer . roles [ x ] ) . some ( ( x : string ) = > guildMember . roles . cache . has ( x ) )
}
2022-11-15 09:06:18 -05:00
youNeedRole ( interaction : Discord.CommandInteraction , role :string ) {
return interaction . reply ( ` This command is restricted to <@& ${ this . config . mainServer . roles [ role ] } > ` )
}
2022-11-13 08:46:50 -05:00
alignText ( text : string , length : number , alignment : string , emptyChar = ' ' ) {
if ( alignment == 'right' ) {
text = emptyChar . repeat ( length - text . length ) + text ;
} else if ( alignment == 'middle' ) {
const emptyCharsPerSide = ( length - text . length ) / 2 ;
text = emptyChar . repeat ( Math . floor ( emptyCharsPerSide ) ) + text + emptyChar . repeat ( Math . floor ( emptyCharsPerSide ) ) ;
} else {
text = text + emptyChar . repeat ( length - text . length ) ;
} return text ;
}
2022-11-15 09:06:18 -05:00
async punish ( client : TClient , interaction : Discord.ChatInputCommandInteraction < 'cached' > , type : string ) {
2022-12-01 17:53:57 -05:00
if ( ! client . isStaff ( interaction . member as Discord . GuildMember ) ) return client . youNeedRole ( interaction , "dcmod" ) ;
2022-11-17 12:58:19 -05:00
const time = interaction . options . getString ( 'time' ) as string ;
2022-12-02 21:02:53 -05:00
const reason = interaction . options . getString ( 'reason' ) ? ? 'Reason unspecified' ;
2022-12-01 17:53:57 -05:00
const GuildMember = interaction . options . getMember ( 'member' ) as Discord . GuildMember ;
const User = interaction . options . getUser ( 'member' ) as Discord . User ;
if ( interaction . user . id == User . id ) return interaction . reply ( ` You cannot ${ type } yourself. ` ) ;
if ( ! GuildMember && type != 'ban' ) return interaction . reply ( ` You cannot ${ type } someone who is not in the server. ` ) ;
2022-12-03 18:35:14 -05:00
await interaction . deferReply ( ) ;
2022-12-01 17:53:57 -05:00
await client . punishments . addPunishment ( type , { time , interaction } , interaction . user . id , reason , User , GuildMember ) ;
2022-11-13 08:46:50 -05:00
} ;
2022-11-15 09:06:18 -05:00
async unPunish ( client : TClient , interaction : Discord.ChatInputCommandInteraction < 'cached' > ) {
if ( ! client . isStaff ( interaction . member as Discord . GuildMember ) ) return this . youNeedRole ( interaction , 'dcmod' ) ;
const punishment = this . punishments . _content . find ( ( x :Punishment ) = > x . id === interaction . options . getInteger ( 'case_id' ) ) ;
if ( ! punishment ) return interaction . reply ( { content : 'Invalid Case #' , ephemeral : true } ) ;
const reason = interaction . options . getString ( 'reason' ) ? ? 'Reason unspecified' ;
const unpunishResult = await this . punishments . removePunishment ( punishment . id , interaction . user . id , reason ) ;
interaction . reply ( unpunishResult )
2022-11-13 08:46:50 -05:00
}
async YTLoop ( YTChannelID : string , YTChannelName : string , DCChannelID : string ) {
2022-11-17 12:58:19 -05:00
let Data :any ;
let error ;
try {
await this . axios . get ( ` https://www.youtube.com/feeds/videos.xml?channel_id= ${ YTChannelID } ` , { timeout : 5000 } ) . then ( ( xml :any ) = > {
Data = this . xjs . xml2js ( xml . data , { compact : true , spaces : 2 } ) ;
} )
} catch ( err ) {
error = true ;
2022-11-24 19:28:46 -05:00
console . log ( ` [ ${ this . moment ( ) . format ( 'DD/MM/YY HH:mm:ss' ) } ] ` , ` ${ YTChannelName } YT fail ` )
2022-11-17 12:58:19 -05:00
}
2022-11-13 08:46:50 -05:00
if ( ! Data ) return ;
if ( this . YTCache [ YTChannelID ] == undefined ) {
this . YTCache [ YTChannelID ] = Data . feed . entry [ 0 ] [ 'yt:videoId' ] . _text ;
return ;
}
if ( Data . feed . entry [ 1 ] [ 'yt:videoId' ] . _text == this . YTCache [ YTChannelID ] ) {
2022-11-18 22:23:33 -05:00
this . YTCache [ YTChannelID ] = Data . feed . entry [ 0 ] [ 'yt:videoId' ] . _text ;
2022-11-13 08:46:50 -05:00
( this . channels . resolve ( DCChannelID ) as Discord . TextChannel ) . send ( ` ** ${ YTChannelName } ** just uploaded a video! \ n ${ Data . feed . entry [ 0 ] . link . _attributes . href } ` )
}
}
2022-11-14 03:45:40 -05:00
}