2022-11-13 08:46:50 -05:00
import Discord , { Client , GatewayIntentBits , Partials } from 'discord.js' ;
import fs from 'node:fs' ;
import { Database } from './database' ;
2022-11-13 19:18:15 -05:00
import timeNames from './timeNames' ;
2022-12-29 05:10:13 -05:00
import { Punishment , formatTimeOpt , createTableOpt , punOpt , Tokens , Config } from './typings/interfaces' ;
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' ;
import config from './config.json' ;
2022-11-13 08:46:50 -05:00
export 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 ;
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 = [ ] ;
2022-12-29 05:10:13 -05:00
this . config = config as Config ;
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 = { } ;
2022-11-13 08:46:50 -05:00
this . setMaxListeners ( 80 )
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 ( ) ;
this . userLevels . initLoad ( ) . intervalSave ( 15000 ) . 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 ;
}
createTable ( columnTitles = [ ] , rowsData = [ ] , options : createTableOpt , client : TClient ) {
const rows : any = [ ] ;
let { columnAlign = [ ] , columnSeparator = [ ] , columnEmptyChar = [ ] } = options ;
if ( columnSeparator . length < 1 ) columnSeparator . push ( '|' ) ;
columnSeparator = columnSeparator . map ( ( x : string ) = > ` ${ x } ` ) ;
// col widths
const columnWidths = columnTitles . map ( ( title : any , i ) = > Math . max ( title . length , . . . rowsData . map ( ( x : any ) = > x [ i ] . length ) ) ) ;
// first row
rows . push ( columnTitles . map ( ( title , i ) = > {
let text = client . alignText ( title , columnWidths [ i ] , columnAlign [ i ] , columnEmptyChar [ i ] ) ;
if ( columnSeparator [ i ] ) {
text += ' ' . repeat ( columnSeparator [ i ] . length ) ;
}
return text ;
} ) . join ( '' ) )
// big line
rows . push ( '━' . repeat ( rows [ 0 ] . length ) ) ;
//data
// remove unicode
rowsData . map ( ( row : any ) = > {
return row . map ( ( element : string ) = > {
return element . split ( '' ) . map ( ( char : string ) = > {
if ( char . charCodeAt ( 0 ) > 128 ) return '□' ;
} ) . join ( '' )
} )
} )
rows . push ( rowsData . map ( ( row : any ) = > row . map ( ( element : string , i : number ) = > {
return client . alignText ( element , columnWidths [ i ] , columnEmptyChar [ i ] ) + ( i === columnTitles . length - 1 ? '' : columnSeparator [ i ] ) ;
} ) . join ( '' )
) . join ( '\n' ) )
2022-11-11 19:58:11 -05:00
2022-11-13 08:46:50 -05:00
return rows . join ( '\n' ) ;
}
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
}
//class
class bannedWords extends Database {
client : TClient ;
constructor ( client : TClient ) {
2022-11-16 13:53:42 -05:00
super ( 'src/database/bannedWords.json' , 'array' ) ;
2022-11-14 03:45:40 -05:00
this . client = client ;
}
}
class punishments extends Database {
client : TClient ;
constructor ( client : TClient ) {
2022-11-16 13:53:42 -05:00
super ( 'src/database/punishments.json' , 'array' ) ;
2022-11-14 03:45:40 -05:00
this . client = client ;
}
createId ( ) {
2022-11-15 09:06:18 -05:00
return Math . max ( . . . this . client . punishments . _content . map ( ( x :Punishment ) = > x . id ) , 0 ) + 1 ;
2022-11-14 03:45:40 -05:00
}
2022-12-01 17:53:57 -05:00
makeModlogEntry ( data : Punishment ) {
const cancels = data . cancels ? this . client . punishments . _content . find ( ( x : Punishment ) = > x . id === data . cancels ) : null ;
2022-12-03 18:35:14 -05:00
const channelId = [ 'kick' , 'ban' ] . includes ( data . type ) ? '1048341961901363352' : this . client . config . mainServer . channels . logs ;
2022-12-01 17:53:57 -05:00
// format data into embed
const embed = new this . client . embed ( )
. setTitle ( ` ${ this . client . formatPunishmentType ( data , this . client , cancels ) } | Case # ${ data . id } ` )
. addFields (
{ name : '🔹 User' , value : ` <@ ${ data . member } > \` ${ data . member } \` ` , inline : true } ,
{ name : '🔹 Moderator' , value : ` <@ ${ data . moderator } > \` ${ data . moderator } \` ` , inline : true } ,
{ name : '\u200b' , value : '\u200b' , inline : true } ,
{ name : '🔹 Reason' , value : ` \` ${ data . reason } \` ` , inline : true } )
. setColor ( this . client . config . embedColor )
. setTimestamp ( data . time )
if ( data . duration ) {
embed . addFields (
{ name : '🔹 Duration' , value : this.client.formatTime ( data . duration , 100 ) , inline : true } ,
{ name : '\u200b' , value : '\u200b' , inline : true }
)
2022-11-14 03:45:40 -05:00
}
2022-12-24 14:48:01 -05:00
if ( data . cancels ) embed . addFields ( { name : '🔹 Overwrites' , value : ` This case overwrites Case # ${ cancels . id } \ n \` ${ cancels . reason } \` ` } ) ;
2022-12-01 17:53:57 -05:00
// send embed in modlog channel
2022-12-03 18:35:14 -05:00
( this . client . channels . cache . get ( channelId ) as Discord . TextChannel ) . send ( { embeds : [ embed ] } ) ;
2022-12-01 17:53:57 -05:00
} ;
getTense ( type : string ) { // Get past tense form of punishment type, grammar yes
switch ( type ) {
case 'ban' :
return 'banned' ;
case 'softban' :
return 'softbanned' ;
case 'kick' :
return 'kicked' ;
case 'mute' :
return 'muted' ;
case 'warn' :
return 'warned' ;
}
}
async addPunishment ( type : string , options : punOpt , moderator : string , reason : string , User : Discord.User , GuildMember? : Discord.GuildMember ) {
const { time , interaction } = options ;
const ms = require ( 'ms' ) ;
const now = Date . now ( ) ;
const guild = this . client . guilds . cache . get ( this . client . config . mainServer . id ) as Discord . Guild ;
const punData : Punishment = { type , id : this.createId ( ) , member : User.id , reason , moderator , time : now }
const embed = new this . client . embed ( )
. setColor ( this . client . config . embedColor )
. setTitle ( ` Case # ${ punData . id } : ${ type [ 0 ] . toUpperCase ( ) + type . slice ( 1 ) } ` )
. setDescription ( ` ${ User . tag } \ n<@ ${ User . id } > \ n( \` ${ User . id } \` ) ` )
. addFields ( { name : 'Reason' , value : reason } )
let punResult : any ;
let timeInMillis : number ;
let DM : Discord.Message < false > | undefined ;
if ( type == "mute" ) {
timeInMillis = time ? ms ( time ) : 2419140000 ; // Timeouts have a limit of 4 weeks
} else {
timeInMillis = time ? ms ( time ) : null ;
}
// Add field for duration if time is specified
if ( time ) embed . addFields ( { name : 'Duration' , value : ` ${ timeInMillis ? ` for ${ this . client . formatTime ( timeInMillis , 4 , { longNames : true , commas : true } )} ` : "forever" } ` } )
if ( GuildMember ) {
try {
2022-12-07 07:06:49 -05:00
DM = await GuildMember . send ( ` You've been ${ this . getTense ( type ) } ${ [ 'warn' , 'mute' ] . includes ( type ) ? 'in' : 'from' } ${ guild . name } ${ time ? ( timeInMillis ? ` for ${ this . client . formatTime ( timeInMillis , 4 , { longNames : true , commas : true } )} ` : 'forever' ) : '' } for reason \` ${ reason } \` (Case # ${ punData . id } ) ` ) ;
2022-12-01 17:53:57 -05:00
} catch ( err : any ) {
embed . setFooter ( { text : 'Failed to DM member of punishment' } ) ;
}
}
if ( [ 'ban' , 'softban' ] . includes ( type ) ) {
2022-12-02 13:25:44 -05:00
const banned = await guild . bans . fetch ( User . id ) . catch ( ( ) = > undefined ) ;
if ( ! banned ) {
punResult = await guild . bans . create ( User . id , { reason : ` ${ reason } | Case # ${ punData . id } ` } ) . catch ( ( err : Error ) = > err . message ) ;
} else {
punResult = 'User is already banned.' ;
}
2022-12-01 17:53:57 -05:00
} else if ( type == 'kick' ) {
punResult = await GuildMember ? . kick ( ` ${ reason } | Case # ${ punData . id } ` ) . catch ( ( err : Error ) = > err . message ) ;
} else if ( type == 'mute' ) {
punResult = await GuildMember ? . timeout ( timeInMillis , ` ${ reason } | Case # ${ punData . id } ` ) . catch ( ( err : Error ) = > err . message ) ;
}
if ( type == 'softban' && typeof punResult != 'string' ) { // If type was softban and it was successful, continue with softban (unban)
punResult = await guild . bans . remove ( User . id , ` ${ reason } | Case # ${ punData . id } ` ) . catch ( ( err : Error ) = > err . message ) ;
}
if ( timeInMillis && [ 'mute' , 'ban' ] . includes ( type ) ) { // If type is mute or ban, specify duration and endTime
punData . endTime = now + timeInMillis ;
punData . duration = timeInMillis ;
}
if ( typeof punResult == 'string' ) { // Punishment was unsuccessful
if ( DM ) DM . delete ( ) ;
if ( interaction ) {
2022-12-03 18:35:14 -05:00
return interaction . editReply ( punResult ) ;
2022-12-01 17:53:57 -05:00
} else {
return punResult ;
}
} else { // Punishment was successful
this . makeModlogEntry ( punData ) ;
this . client . punishments . addData ( punData ) . forceSave ( ) ;
if ( interaction ) {
2022-12-03 18:35:14 -05:00
return interaction . editReply ( { embeds : [ embed ] } ) ;
2022-12-01 17:53:57 -05:00
} else {
return punResult ;
}
}
}
2022-11-18 06:29:03 -05:00
async removePunishment ( caseId :number , moderator :any , reason :string ) : Promise < any > {
const now = Date . now ( )
const punishment = this . _content . find ( ( x :Punishment ) = > x . id === caseId ) ;
const id = this . createId ( ) ;
if ( ! punishment ) return 'Punishment not found' ;
if ( [ 'ban' , 'mute' ] . includes ( punishment . type ) ) {
const guild = this . client . guilds . cache . get ( this . client . config . mainServer . id ) as Discord . Guild ;
let removePunishmentResult ;
if ( punishment . type === 'ban' ) {
removePunishmentResult = await guild . members . unban ( punishment . member , ` ${ reason || 'Reason unspecified' } | Case # ${ id } ` ) . catch ( ( err :TypeError ) = > err . message ) ;
} else if ( punishment . type === 'mute' ) {
const member = await guild . members . fetch ( punishment . member ) . catch ( err = > undefined ) ;
if ( member ) {
removePunishmentResult = await member
if ( typeof removePunishmentResult !== 'string' ) {
member . timeout ( null , ` ${ reason || 'Reason unspecified' } | Case # ${ id } ` )
removePunishmentResult . send ( ` You've been unmuted in ${ removePunishmentResult . guild . name } . ` ) ;
removePunishmentResult = removePunishmentResult . user ;
}
} else {
// user probably left, quietly remove punishment
const removePunishmentData = { type : ` un ${ punishment . type } ` , id , cancels : punishment.id , member : punishment.member , reason , moderator , time : now } ;
this . _content [ this . _content . findIndex ( ( x :Punishment ) = > x . id === punishment . id ) ] . expired = true
this . addData ( removePunishmentData ) . forceSave ( ) ;
}
}
if ( typeof removePunishmentResult === 'string' ) return ` Un ${ punishment . type } was unsuccessful: ${ removePunishmentResult } ` ;
else {
const removePunishmentData = { type : ` un ${ punishment . type } ` , id , cancels : punishment.id , member : punishment.member , reason , moderator , time : now } ;
2022-12-01 19:36:51 -05:00
this . makeModlogEntry ( removePunishmentData ) ;
2022-11-18 06:29:03 -05:00
this . _content [ this . _content . findIndex ( ( x :Punishment ) = > x . id === punishment . id ) ] . expired = true ;
this . addData ( removePunishmentData ) . forceSave ( ) ;
return ` Successfully ${ punishment . type === 'ban' ? 'unbanned' : 'unmuted' } ** ${ removePunishmentResult ? . tag } ** ( ${ removePunishmentResult ? . id } ) for reason \` ${ reason || 'Reason unspecified' } \` `
}
} else {
try {
const removePunishmentData = { type : 'removeOtherPunishment' , id , cancels : punishment.id , member : punishment.member , reason , moderator , time : now } ;
2022-12-01 19:36:51 -05:00
this . makeModlogEntry ( removePunishmentData ) ;
2022-11-18 06:29:03 -05:00
this . _content [ this . _content . findIndex ( ( x :Punishment ) = > x . id === punishment . id ) ] . expired = true ;
this . addData ( removePunishmentData ) . forceSave ( ) ;
return ` Successfully removed Case # ${ punishment . id } (type: ${ punishment . type } , user: ${ punishment . member } ). ` ;
} catch ( error :any ) {
return ` ${ punishment . type [ 0 ] . toUpperCase ( ) + punishment . type . slice ( 1 ) } removal was unsuccessful: ${ error . message } ` ;
}
}
}
2022-11-14 03:45:40 -05:00
}
class userLevels extends Database {
client : TClient ;
constructor ( client : TClient ) {
2022-11-16 13:53:42 -05:00
super ( 'src/database/userLevels.json' , 'object' ) ;
2022-11-14 03:45:40 -05:00
this . client = client
}
incrementUser ( userid : string ) {
2022-11-15 09:06:18 -05:00
const data = this . _content [ userid ] ; // User's data. Integer for old format, object for new format.
2022-11-14 03:45:40 -05:00
2022-11-15 09:06:18 -05:00
if ( typeof data == 'number' ) { // If user's data is an integer, convert it into object for new format.
this . _content [ userid ] = { messages : data , level : 0 } ;
}
if ( data ) { // If user exists on file...
this . _content [ userid ] . messages ++ ; // Increment their message count
if ( data . messages >= this . algorithm ( data . level + 2 ) ) { // Quietly level up users who can surpass more than 2 levels at once, usually due to manually updating their message count
2022-11-14 03:45:40 -05:00
while ( data . messages > this . algorithm ( data . level + 1 ) ) {
this . _content [ userid ] . level ++ ;
console . log ( ` ${ userid } EXTENDED LEVELUP ${ this . _content [ userid ] . level } ` )
}
2022-11-15 09:06:18 -05:00
} else if ( data . messages >= this . algorithm ( data . level + 1 ) ) { // If user's message count meets/exceeds message requirement for next level...
this . _content [ userid ] . level ++ ; // Level them up.
2022-11-23 07:28:21 -05:00
( this . client . channels . resolve ( this . client . config . mainServer . channels . botcommands ) as Discord . TextChannel ) . send ( { content : ` <@ ${ userid } > has reached level ** ${ data . level } **. GG! ` , allowedMentions : { parse : [ 'users' ] } } )
2022-11-14 03:45:40 -05:00
}
2022-11-15 09:06:18 -05:00
} else { // If user doesn't exist on file, create an object for it.
2022-11-14 03:45:40 -05:00
this . _content [ userid ] = { messages : 1 , level : 0 } ;
}
}
2022-11-15 09:06:18 -05:00
algorithm ( level : number ) { // Algorithm for determining levels. If adjusting, recommended to only change the integer at the end of equation.
2022-11-14 03:45:40 -05:00
return level * level * 15 ;
}
2022-11-15 09:06:18 -05:00
}
class bonkCount extends Database {
client : TClient ;
constructor ( client : TClient ) {
2022-11-16 13:53:42 -05:00
super ( 'src/database/bonkCount.json' , 'object' )
2022-11-15 09:06:18 -05:00
this . client = client
}
_incrementUser ( userid : string ) {
const amount = this . _content [ userid ] ;
if ( amount ) this . _content [ userid ] ++ ;
else this . _content [ userid ] = 1 ;
return this ;
}
getUser ( userid : string ) {
return this . _content [ userid ] || 0 ;
}
2022-11-27 02:28:51 -05:00
}