1
0
mirror of https://github.com/toast-ts/Daggerbot-TS.git synced 2024-09-29 04:11:00 -04:00

i think i done enough for now. (Push part 5)

This commit is contained in:
toast-ts 2022-11-16 01:06:18 +11:00
parent b86e7d01c4
commit 178286c189
20 changed files with 559 additions and 481 deletions

1
.gitignore vendored
View File

@ -4,6 +4,5 @@ package-lock.json
.ncurc.json
# TypeScript stuff
dist/
typings/
# Bot stuff
database/MPDB.dat

View File

@ -1,5 +1,5 @@
# Daggerbot-TS
Original JavaScript Daggerbot from [here](https://github.com/SpaceManBuzz/DaggerBot-) converted to TypeScript.
TypeScript-based Daggerbot converted from JavaScript at [SpaceManBuzz/DaggerBot-](https://github.com/SpaceManBuzz/DaggerBot-)
### Todo list:
- [ ] Development

View File

@ -1,46 +1,3 @@
interface createTableOpt {
columnAlign: any,
columnSeparator: any,
columnEmptyChar: any
}
interface formatTimeOpt {
longNames: boolean,
commas: boolean
}
interface CommandInfoOpt {
insertNewline: boolean,
parts: string[], //idfk
titles: string[]
}
interface punOpt {
time?: string,
reason?: string;
interaction?: any
}
interface Punishment {
id: number;
type: string;
member: string;
moderator: string;
expired?: boolean;
time?: number;
reason: string;
endTime?: number;
cancels?: number;
duration?: number;
}
interface punData {
id: number;
type: string;
member: string;
moderator: string;
expired?: boolean;
time?: number;
reason: string;
endTime?: number;
cancels?: number;
duration?: number;
}
import Discord, { Client, GatewayIntentBits, Partials } from 'discord.js';
import fs from 'node:fs';
import { Database } from './database';
@ -51,9 +8,6 @@ export class TClient extends Client {
registry: Array<Discord.ApplicationCommandDataResolvable>;
config: any;
tokens: any;
categoryNames: any;
commandPages: any;
helpDefaultOptions: any;
YTCache: any;
embed: typeof Discord.EmbedBuilder;
collection: any;
@ -62,6 +16,7 @@ export class TClient extends Client {
moment: any;
xjs: any;
axios: any;
ms: any;
memberCount_LastGuildFetchTimestamp: any;
userLevels: userLevels;
punishments: punishments;
@ -89,12 +44,6 @@ export class TClient extends Client {
this.registry = [];
this.config = require('./config.json');
this.tokens = require('./tokens.json');
this.categoryNames;
this.commandPages = [];
this.helpDefaultOptions = {
parts: ['name', 'usage', 'shortDescription', 'alias'],
titles: ['alias']
}
this.YTCache = {
'UCQ8k8yTDLITldfWYKDs3xFg': undefined, // Daggerwin
'UCguI73--UraJpso4NizXNzA': undefined // Machinery Restorer
@ -106,11 +55,12 @@ export class TClient extends Client {
this.moment = import('moment');
this.xjs = import('xml-js');
this.axios = import('axios');
this.ms = import('ms');
this.memberCount_LastGuildFetchTimestamp = 0;
this.userLevels(this);
this.bonkCount(this);
this.punishments(this);
this.bannedWords(this);
this.userLevels = new userLevels(this);
this.bonkCount = new bonkCount(this);
this.punishments = new punishments(this);
this.bannedWords = new bannedWords(this);
this.repeatedMessages = {};
this.setMaxListeners(80)
}
@ -127,65 +77,6 @@ export class TClient extends Client {
this.registry.push(command.data.toJSON())
}
}
commandInfo(client: TClient, command: any, options?: CommandInfoOpt){
let text = ':small_orange_diamond: ';
if (!options.titles) options.titles = [];
function e(){
text += '\n';
if (options.insertNewline){
text += '\n';
} return;
}
if (options.parts.includes('name') && command.name){
if (options.titles.includes('name') && options.titles.includes('usage')){
text += 'Name & Usage: ';
} else if (options.titles.includes('name')){
text += 'Name: ';
}
text += '`' + client.config.prefix + command.name;
if (options.parts.includes('usage') && command.usage){
text += ' ' + command.usage.map((x:string)=>x.startsWith('?') ? '?['+x.slice(1)+']' : '['+x+']').join(' ');
}
text += '`';
e();
} else if (options.parts.includes('usage') && command.usage){
if (options.titles.includes('usage')) text += 'Usage: ';
text += '`'+command.usage.map((x:string)=>x.startsWith('?') ? '?['+x+']' : '['+x+']').join(' ') + '`';
e();
}
if (options.parts.includes('description') && command.description){
if (options.titles.includes('description')) text += 'Description: ';
text += command.description;
e();
}
if (options.parts.includes('shortDescription')){
if (command.shortDescription){
if (options.titles.includes('shortDescription')) text += 'Shorter description: ';
text += command.shortDescription;
e();
} else if (!options.titles.includes('shortDescription') && command.description){
text += command.description;
e();
}
}
if (options.parts.includes('alias') && command.alias){
if (options.titles.includes('alias')) text += 'Aliases: ';
text += command.alias.map((x:any)=>'`'+x+'`').join(', ');
e();
}
if (options.parts.includes('category') && command.category){
if (options.titles.includes('category')) text += 'Category: ';
text += command.category;
e();
}
if (options.parts.includes('autores') && command.autores){
if (options.titles.includes('autores')) text += 'AutoResponse:tm: Requirements: ';
text += '`['+command.autores.join('] [')+']`';
e();
}
e();
return text;
}
formatPunishmentType(punishment: Punishment, client: TClient, cancels: Punishment){
if (punishment.type == 'removeOtherPunishment'){
cancels ||= this.punishments._content.find((x: Punishment)=>x.id === punishment.cancels)
@ -194,7 +85,7 @@ export class TClient extends Client {
}
formatTime(integer: number, accuracy = 1, options?: formatTimeOpt){
let achievedAccuracy = 0;
let text = '';
let text:any = '';
const { longNames, commas } = options
for (const timeName of timeNames){
if (achievedAccuracy < accuracy){
@ -220,6 +111,9 @@ export class TClient extends Client {
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))
}
youNeedRole(interaction: Discord.CommandInteraction, role:string){
return interaction.reply(`This command is restricted to <@&${this.config.mainServer.roles[role]}>`)
}
alignText(text: string, length: number, alignment: string, emptyChar = ' '){
if (alignment == 'right'){
text = emptyChar.repeat(length - text.length)+text;
@ -272,7 +166,7 @@ export class TClient extends Client {
{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 || 'Unspecified'}\``, inline: true},
{name: '🔹 Reason', value: `\`${data.reason || 'Reason unspecified'}\``, inline: true},
)
if (data.duration) {
embed.addFields(
@ -280,106 +174,39 @@ export class TClient extends Client {
{name: '\u200b', value: '\u200b', inline: true}
)
}
if (data.cancels) embed.addFields({name: '🔹 Overwrites', value: `This case overwrites Case #${cancels.id} \`${cancels.reason}\``})
if (data.cancels) embed.addFields({name: '🔹 Overwrites', value: `This case overwrites Case #${cancels.id} \`${cancels.reason}\``});
// send embed to log channel
(client.channels.cache.get(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed]})
}
async punish(client: TClient, message: Discord.Message, args: string, type: string){
let member: any;
if (message.guildId !== client.config.mainServer.id) return message.channel.send('This command doesn\'t work in this server');
if (!message.member.roles.cache.has(client.config.mainServer.roles.dcmod)) return message.reply(`You need the <@&${client.config.mainServer.roles.dcmod}> role to use this command.`)
if (type == 'ban' && args[1]){
member = message.mentions.users?.first() || (await client.users.fetch(args[1]).catch(()=>undefined));
} else if (args[1]){
member = message.mentions.members?.first() || (await message.guild.members.fetch(args[1]).catch(()=>undefined));
}
let memberAsked = false;
if (!member){
memberAsked = true;
await message.channel.send(`Which member would you like to ${type}?\nSend another message with a mention or a user ID. (30s)`).then(async (x:any)=>{
const filter = m=>m.author.id == message.author.id;
member = await message.channel.awaitMessages({filter, time: 30000, errors: ['time'], max: 1}).then(async (z:any)=>{
if (z.first().content.startsWith(client.config.prefix)) return 'timedout';
if (type == 'ban'){
return z.first().mentions.users?.first() || (await client.users.fetch(z.first().content).catch(()=>undefined));
} else {
return z.first().mentions.members?.first() || (await message.guild.members.fetch(z.first().content).catch(()=>undefined))
}
}).catch(async()=>{
message.channel.send('Command cancelled after 30 seconds of inactivity.');
return 'timedout';
});
})
}
if (member === 'timedout') return;
else if (!member) return message.channel.send('You failed to mention a member.');
let time;
let reason;
let col1; // idfk if this should be included here but just wanted to get rid of red underline.
async punish(client: TClient, interaction: Discord.ChatInputCommandInteraction<'cached'>, type: string){
let result: any;
if (args[2] && !memberAsked){
// if the first character of args 2 is a number, args 2 is the time. otherwise its the reason.
time = (args[2][0].match(/[0-9]/) && !['softban', 'kick', 'warn'].includes(type)) ? args[2] : undefined;
// if time is in args 2, reason starts at args 3. if no time was provided, reason starts at args 2
reason = args.slice(time ? 3 : 2).join(' '); // "Property 'join' does not exist on type 'string'." :linus: x99
if (!client.isStaff(interaction.member as Discord.GuildMember)) return this.youNeedRole(interaction, 'dcmod')
//if (type !== ('warn' || 'mute') && (interaction.member as Discord.GuildMember).roles.cache.has(client.config.mainServer.roles.idk)) return this.youNeedRole(interaction, 'dcmod');
const time = this.ms(interaction.options.getString('time'));
const reason = interaction.options.getString('reason') ?? 'Reason unspecified';
if (type == 'ban'){
const user = interaction.options.getUser('member') as Discord.User;
if (interaction.user.id == user.id) return interaction.reply(`You cannot ${type} yourself!`);
result = await this.punishments.addPunishment(type, user, {time,reason,interaction}, interaction.user.id);
} else {
if (!['softban', 'kick', 'warn'].includes(type)){
await message.channel.send(`How long do you want to ${type} this user for?\nSend another message with a time name, or 'forever' to ${type} this user forever. (30s)`);
const filter = m=>m.author.id === message.author.id;
col1 = await message.channel.awaitMessages({filter, time: 30000, errors: ['time'], max: 1}).then(collected=>{
if (collected.first()?.content.startsWith(client.config.prefix)) return 'timedout';
return collected.first()?.content.toLowerCase() === 'forever' ? 'inf' : collected.first()?.content;
}).catch(()=>{
message.channel.send('Command cancelled after 30 seconds of inactivity.');
return 'timedout';
});
if (time === 'timedout') return;
const member = interaction.options.getMember('member') as Discord.GuildMember;
if (interaction.user.id == member.id) return interaction.reply(`You cannot ${type} yourself!`);
if (this.isStaff(member)) return interaction.reply(`You cannot ${type} other staff!`);
result = await this.punishments.addPunishment(type, member, {time,reason,interaction}, interaction.user.id);
}
await message.channel.send(`Send another message with a reason for this ${type}.\nSend another message with "-" to leave the reason unspecified. (30s)`);
const filter = m=>m.author.id === message.author.id;
reason = await message.channel.awaitMessages({filter, time: 30000, errors: ['time'], max: 1}).then(collected=>{
if (collected.first()?.content.startsWith(client.config)) return 0;
return collected.first()?.content == '-' ? undefined : collected.first()?.content;
}).catch(()=>{
message.channel.send('Command cancelled after 30 seconds of inactivity.');
return 0;
})
if (reason === 0) return;
}
const punishmentResult = await client.punishments.addPunishment(type, member, {time, reason}, message.author.id, message);
(typeof result == 'string' ? message.reply(punishmentResult) : message.reply({embeds: [punishmentResult]}))
(typeof result == 'string' ? interaction.reply({content: `${result}`}) : interaction.reply({embeds: [result]}))
};
async unPunish(client: TClient, message: Discord.Message, args: string){
if (message.guildId !== client.config.mainServer.id) return message.channel.send('This command doesn\'t work in this server');
if (!message.member.roles.cache.has(client.config.mainServer.roles.dcmod)) return message.reply(`You need the <@&${client.config.mainServer.roles.dcmod}> role to use this command.`)
let punishment;
if (args[1]) punishment = client.punishments._content.find((x:any)=>x.id == args[1])
if (!punishment){
await message.channel.send(`Which punishment would you like to remove?\nSend another message with a Case # (30s)`).then(async (x:any)=>{
const filter = m=>m.author.id === message.author.id;
punishment = await message.channel.awaitMessages({filter, time: 30000, errors: ['time'], max: 1}).then(async (z:any)=>{
return client.punishments._content.find((x:any)=>x.id == z.first()?.content);
}).catch(async()=>{
message.channel.send('Command cancelled after 30 seconds of inactivity.');
return 'timedout';
});
})
}
if (punishment === 'timedout') return;
else if (!punishment) return message.channel.send('You failed to mention a Case #');
//if (punishment.type !== 'warn' && message.member.roles.cache.has(client.config.mainServer.roles.trialmoderator)) return message.channel.send('Trial moderators can only remove warnings.');
let reason;
if (args[2]){
reason = args.slice(2).join(' '); // "Property 'join' does not exist on type 'string'." :linus: x50
}else{
await message.channel.send(`Send another message with a reason for this ${punishment.type} removal. (30s)\n*Send \`-\` to leave the reason unspecified.*`);
const filter = m=>m.author.id === message.author.id;
reason = await message.channel.awaitMessages({filter, time: 30000, errors: ['time'], max: 1}).then(collected=>collected.first()?.content === '-' ? undefined : collected.first()?.content).catch(()=>0);
if (reason === 0) return message.channel.send('Invalid reason.');
}
const unpunishResult = await client.punishments.removePunishment(punishment.id, message.author.id, reason);
message.channel.send(unpunishResult);
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});
//if (type !== ('warn' || 'mute') && (interaction.member as Discord.GuildMember).roles.cache.has(client.config.mainServer.roles.idk)) return this.youNeedRole(interaction, 'dcmod');
const reason = interaction.options.getString('reason') ?? 'Reason unspecified';
const unpunishResult = await this.punishments.removePunishment(punishment.id, interaction.user.id, reason);
interaction.reply(unpunishResult)
}
async YTLoop(YTChannelID: string, YTChannelName: string, DCChannelID: string){
const Data = this.xjs.xml2js((await this.axios.get(`https://www.youtube.com/feeds/videos.xml?channel_id=${YTChannelID}`, {timeout: 5000})), {compact: true, spaces: 2}).catch(()=>{return null});
if (!Data) return;
@ -410,13 +237,13 @@ class punishments extends Database {
this.client = client;
}
createId(){
return Math.max(...this.client.punishments._content.map((x:punData)=>x.id), 0)+1;
return Math.max(...this.client.punishments._content.map((x:Punishment)=>x.id), 0)+1;
}
async addPunishment(type: string, member: any, options: punOpt, moderator: string){
const now = Date.now();
const {time, reason, interaction}=options;
const ms = require('ms');
let timeInMillis;
let timeInMillis: number;
if(type !== 'mute'){
timeInMillis = time ? ms(time) : null;
} else {
@ -424,15 +251,40 @@ class punishments extends Database {
}
switch (type) {
case 'ban':
const banData: punData={type, id: this.createId(), member: member.id, moderator, time: now};
const dm1: Discord.Message = await member.send(`You've been banned from ${interaction.guild.name} ${timeInMillis ? `for ${this.client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Unspecified'}\` (Case #${banData.id})`).catch(()=>{return interaction.channel.send('Failed to DM user.')})
const banResult = await interaction.guild.bans.create(member.id, {reason: `${reason || 'Unspecified'} | Case #${banData.id}`}).catch((err:Error)=>err.message);
const banData: Punishment={type, id: this.createId(), member: member.id, moderator, time: now};
const dm1: Discord.Message = await member.send(`You've been banned from ${interaction.guild.name} ${timeInMillis ? `for ${this.client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Reason unspecified'}\` (Case #${banData.id})`).catch(()=>{return interaction.channel.send('Failed to DM user.')})
const banResult = await interaction.guild.bans.create(member.id, {reason: `${reason || 'Reason unspecified'} | Case #${banData.id}`}).catch((err:Error)=>err.message);
if (typeof banResult === 'string'){
dm1.delete()
return `Ban was unsuccessful: ${banResult}`
} else {
if (timeInMillis){
banData.endTime = now + timeInMillis;
banData.duration = timeInMillis
}
if (reason) banData.reason = reason;
this.client.makeModlogEntry(banData, this.client);
this.addData(banData).forceSave();
return new this.client.embed().setColor(this.client.config.embedColor).setTitle(`Case #${banData.id}: Ban`).setDescription(`${member?.user?.tag ?? member?.tag}\n<@${member.id}>\n(\`${member.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Reason unspecified'}\``},
{name: 'Duration', value: `${timeInMillis ? `for ${this.client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'}`}
)
}
case 'softban':
const guild = member.guild;
const softbanData: Punishment={type, id: this.createId(), member: member.user.id, moderator, time: now};
const dm2 = Discord.Message = await member.send(`You've been softbanned from ${member.guild.name} ${timeInMillis ? `for ${this.client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Reason unspecified'}\` (Case #${softbanData.id})`).catch(()=>{return interaction.channel.send('Failed to DM user.')})
const softbanResult = await member.ban({deleteMessageDays: 3, reason: `${reason || 'Reason unspecified'} | Case #${softbanData.id}`}).catch((err:Error)=>err.message);
if (typeof softbanResult === 'string') {
dm2.delete();
return `Softban was unsuccessful: ${softbanResult}`;
}
case 'kick':
case 'warn':
case 'mute':
}
}
async removePunishment(caseId:number, moderator:any, reason:string):Promise<any>{}
}
class userLevels extends Database {
client: TClient;
@ -441,24 +293,44 @@ class userLevels extends Database {
this.client = client
}
incrementUser(userid: string){
const data = this._content[userid];
const data = this._content[userid];// User's data. Integer for old format, object for new format.
if (data) {
this._content[userid].messages++;
if (data.messages >= this.algorithm(data.level+2)){
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
while (data.messages > this.algorithm(data.level+1)){
this._content[userid].level++;
console.log(`${userid} EXTENDED LEVELUP ${this._content[userid].level}`)
}
} else if (data.messages >= this.algorithm(data.level+1)){
this._content[userid].level++;
} 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.
(this.client.channels.resolve(this.client.config.mainServer.channels.thismeanswar) as Discord.TextChannel).send({content: `<@${userid}> has reached level **${data.level}**. GG!`})
}
} else {
} else {// If user doesn't exist on file, create an object for it.
this._content[userid] = {messages: 1, level: 0};
}
}
algorithm(level: number){
algorithm(level: number){// Algorithm for determining levels. If adjusting, recommended to only change the integer at the end of equation.
return level*level*15;
}
}
class bonkCount extends Database {
client: TClient;
constructor(client: TClient){
super('./database/bonkCount.json', 'object')
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;
}
}

View File

@ -1,5 +1,4 @@
{
"prefix": ".",
"embedColor": "#0052cf",
"embedColorGreen": "#57f287",
"embedColorYellow": "#ffea00",
@ -11,7 +10,8 @@
"commands": false,
"logs": false,
"automod": false,
"mpstats": false
"mpstats": false,
"autores": false
},
"eval": {
"allowed": true,

File diff suppressed because one or more lines are too long

View File

@ -1 +1,28 @@
{"696085982201643090":3,"532662366354276352":2849,"178941218510602240":9,"615761944154210305":7,"141304507249197057":14,"190407856527376384":7,"711527768185372742":1,"716355511552966737":5,"593696856165449749":14,"824043915539513406":20,"771892617599516674":10,"889665445915926588":1,"488683638310043677":1027,"475037861725339649":1,"389237487094071337":1,"859313171964887140":1,"301350210926280704":2,"695323013813633076":2,"458688902102908928":2,"606595407769894995":1,"734703851558535188":2,"544215307972247553":2,"506022868157595648":1,"468837263577579524":3,"743212818467258468":1,"954092707213619221":1}
{
"696085982201643090": 3,
"532662366354276352": 2849,
"178941218510602240": 9,
"615761944154210305": 8,
"141304507249197057": 14,
"190407856527376384": 7,
"711527768185372742": 1,
"716355511552966737": 5,
"593696856165449749": 14,
"824043915539513406": 20,
"771892617599516674": 10,
"889665445915926588": 1,
"488683638310043677": 1027,
"475037861725339649": 1,
"389237487094071337": 1,
"859313171964887140": 1,
"301350210926280704": 2,
"695323013813633076": 2,
"458688902102908928": 2,
"606595407769894995": 1,
"734703851558535188": 2,
"544215307972247553": 2,
"506022868157595648": 1,
"468837263577579524": 3,
"743212818467258468": 1,
"954092707213619221": 1
}

View File

@ -1 +1 @@
[[0,674965],[1,675885],[2,676639],[3,677245],[4,677609],[5,678188],[6,678916],[7,679465],[8,679938],[9,680540],[10,681614],[11,682079],[12,682780],[13,683187],[14,683547],[15,683900],[16,684592],[17,685466],[18,686078],[19,686481],[20,676748],[21,676968],[22,677427],[23,677592],[24,677894],[25,678116],[26,676785],[27,677570],[28,678491],[29,679137],[30,679818],[31,680094],[32,680417],[33,680783],[34,681563],[35,682070],[36,682670],[37,683504],[38,684078],[39,684383],[40,684692],[41,685448],[42,685664],[43,685994],[44,686366],[45,687118],[46,687626],[47,688008],[48,688754],[49,688942],[50,689107],[51,689472],[52,690143],[53,690644],[54,691124],[55,692196],[56,692624],[57,692906],[58,693456],[59,693952],[60,694586],[61,695070],[62,696163],[63,696564],[64,697315],[65,698548],[66,699138],[67,699558],[68,700307],[69,701063],[70,701394],[71,701868],[72,702453],[73,702917],[76,705187],[77,705243],[78,705488],[79,705961],[80,706585],[81,707467],[82,708212]]
[[0,674965],[1,675885],[2,676639],[3,677245],[4,677609],[5,678188],[6,678916],[7,679465],[8,679938],[9,680540],[10,681614],[11,682079],[12,682780],[13,683187],[14,683547],[15,683900],[16,684592],[17,685466],[18,686078],[19,686481],[20,676748],[21,676968],[22,677427],[23,677592],[24,677894],[25,678116],[26,676785],[27,677570],[28,678491],[29,679137],[30,679818],[31,680094],[32,680417],[33,680783],[34,681563],[35,682070],[36,682670],[37,683504],[38,684078],[39,684383],[40,684692],[41,685448],[42,685664],[43,685994],[44,686366],[45,687118],[46,687626],[47,688008],[48,688754],[49,688942],[50,689107],[51,689472],[52,690143],[53,690644],[54,691124],[55,692196],[56,692624],[57,692906],[58,693456],[59,693952],[60,694586],[61,695070],[62,696163],[63,696564],[64,697315],[65,698548],[66,699138],[67,699558],[68,700307],[69,701063],[70,701394],[71,701868],[72,702453],[73,702917],[76,705187],[77,705243],[78,705488],[79,705961],[80,706585],[81,707467],[82,708212],[83,709024],[84,709773]]

View File

@ -1,54 +1,54 @@
{
"190407856527376384": {
"messages": 52904,
"messages": 52961,
"level": 59
},
"593696856165449749": {
"messages": 51257,
"messages": 51388,
"level": 58
},
"141304507249197057": {
"messages": 67482,
"messages": 67550,
"level": 67
},
"533707949831487488": {
"messages": 56765,
"messages": 56984,
"level": 61
},
"532662366354276352": {
"messages": 33505,
"messages": 33675,
"level": 47
},
"824043915539513406": {
"messages": 18398,
"messages": 18434,
"level": 35
},
"178941218510602240": {
"messages": 6368,
"messages": 6372,
"level": 20
},
"215497515934416896": {
"messages": 33121,
"messages": 33124,
"level": 46
},
"301350210926280704": {
"messages": 14272,
"messages": 14306,
"level": 30
},
"695323013813633076": {
"messages": 14063,
"messages": 14072,
"level": 30
},
"389237487094071337": {
"messages": 12223,
"messages": 12240,
"level": 28
},
"716355511552966737": {
"messages": 9115,
"messages": 9122,
"level": 24
},
"633345781780185099": {
"messages": 29362,
"messages": 29364,
"level": 44
},
"711527768185372742": {
@ -64,23 +64,23 @@
"level": 18
},
"458688902102908928": {
"messages": 6181,
"messages": 6190,
"level": 20
},
"475037861725339649": {
"messages": 10096,
"level": 25
"messages": 10192,
"level": 26
},
"392699530912727041": {
"messages": 4925,
"messages": 4928,
"level": 18
},
"468837263577579524": {
"messages": 7565,
"messages": 7631,
"level": 22
},
"734703851558535188": {
"messages": 20183,
"messages": 20200,
"level": 36
},
"488683638310043677": {
@ -92,11 +92,11 @@
"level": 39
},
"322835877027905547": {
"messages": 9999,
"messages": 10018,
"level": 25
},
"485793265568841728": {
"messages": 37876,
"messages": 37880,
"level": 50
},
"837979120142778388": {
@ -108,11 +108,11 @@
"level": 0
},
"257954059988893720": {
"messages": 5391,
"level": 0
"messages": 5392,
"level": 18
},
"690090143008555064": {
"messages": 9973,
"messages": 9974,
"level": 25
},
"849633082440941628": {
@ -124,7 +124,7 @@
"level": 0
},
"452576735494406175": {
"messages": 1675,
"messages": 1676,
"level": 10
},
"763055599654666291": {
@ -136,7 +136,7 @@
"level": 0
},
"366896479098372096": {
"messages": 2956,
"messages": 2958,
"level": 14
},
"445940328634253323": {
@ -148,7 +148,7 @@
"level": 0
},
"169891949464125441": {
"messages": 516,
"messages": 518,
"level": 5
},
"718453763932946432": {
@ -156,15 +156,15 @@
"level": 30
},
"472809522226790420": {
"messages": 2773,
"messages": 2776,
"level": 13
},
"763803832542035978": {
"messages": 678,
"messages": 679,
"level": 6
},
"931816463113814066": {
"messages": 672,
"messages": 673,
"level": 6
},
"958108557503524904": {
@ -172,7 +172,7 @@
"level": 0
},
"771892617599516674": {
"messages": 621,
"messages": 626,
"level": 6
},
"468437000232501269": {
@ -188,11 +188,11 @@
"level": 0
},
"309373272594579456": {
"messages": 3582,
"messages": 3585,
"level": 15
},
"399625244588900362": {
"messages": 21298,
"messages": 21300,
"level": 37
},
"889665445915926588": {
@ -200,8 +200,8 @@
"level": 0
},
"615761944154210305": {
"messages": 2924,
"level": 13
"messages": 2997,
"level": 14
},
"397101726047666197": {
"messages": 5553,
@ -216,7 +216,7 @@
"level": 0
},
"820029314103246860": {
"messages": 19,
"messages": 20,
"level": 1
},
"831633702492307473": {
@ -228,7 +228,7 @@
"level": 2
},
"645342896312156181": {
"messages": 662,
"messages": 679,
"level": 6
},
"488505753133645826": {
@ -236,7 +236,7 @@
"level": 0
},
"313461397457600512": {
"messages": 77,
"messages": 78,
"level": 2
},
"848489550065827850": {
@ -244,7 +244,7 @@
"level": 1
},
"862138850423472128": {
"messages": 51,
"messages": 52,
"level": 1
},
"700053257996992573": {
@ -264,7 +264,7 @@
"level": 0
},
"617353338324779008": {
"messages": 173,
"messages": 178,
"level": 3
},
"983545546348318771": {
@ -280,7 +280,7 @@
"level": 0
},
"509374532109336576": {
"messages": 27,
"messages": 28,
"level": 1
},
"464887328138199042": {
@ -292,7 +292,7 @@
"level": 0
},
"283864360697331713": {
"messages": 55,
"messages": 57,
"level": 1
},
"481056143536553984": {
@ -300,7 +300,7 @@
"level": 2
},
"813156260563910696": {
"messages": 25,
"messages": 26,
"level": 1
},
"236902492955344898": {
@ -336,7 +336,7 @@
"level": 0
},
"929408228255731713": {
"messages": 34,
"messages": 35,
"level": 1
},
"810517881392988220": {
@ -348,7 +348,7 @@
"level": 0
},
"549295707304099846": {
"messages": 44,
"messages": 45,
"level": 1
},
"759390179064283178": {
@ -400,7 +400,7 @@
"level": 0
},
"903147621961588757": {
"messages": 13,
"messages": 14,
"level": 0
},
"386627658773168137": {
@ -424,7 +424,7 @@
"level": 0
},
"281518331427553280": {
"messages": 26,
"messages": 27,
"level": 1
},
"708758234407895050": {
@ -472,8 +472,8 @@
"level": 0
},
"557611382028369921": {
"messages": 50,
"level": 0
"messages": 58,
"level": 1
},
"587649354811179011": {
"messages": 1,
@ -532,7 +532,7 @@
"level": 0
},
"818595993121062974": {
"messages": 45,
"messages": 46,
"level": 1
},
"273755695680192513": {
@ -544,7 +544,7 @@
"level": 0
},
"869718328313278555": {
"messages": 87,
"messages": 96,
"level": 2
},
"772197160372404234": {
@ -564,7 +564,7 @@
"level": 0
},
"705189525743206460": {
"messages": 13,
"messages": 14,
"level": 0
},
"1007746635377410110": {
@ -656,7 +656,7 @@
"level": 0
},
"188304766923833344": {
"messages": 20,
"messages": 21,
"level": 1
},
"749311773819142326": {
@ -792,7 +792,7 @@
"level": 0
},
"698428165445517356": {
"messages": 23,
"messages": 26,
"level": 1
},
"940617130703990864": {
@ -824,11 +824,11 @@
"level": 0
},
"513009978315898891": {
"messages": 10,
"level": 0
"messages": 18,
"level": 1
},
"667815332047486978": {
"messages": 1,
"messages": 2,
"level": 0
},
"902243585511026738": {
@ -1044,7 +1044,7 @@
"level": 0
},
"455423861362655252": {
"messages": 1,
"messages": 2,
"level": 0
},
"760579326344691762": {
@ -1056,15 +1056,15 @@
"level": 0
},
"781289786143932499": {
"messages": 105,
"level": 0
"messages": 106,
"level": 2
},
"348617165135544321": {
"messages": 1,
"level": 0
},
"268494595594256386": {
"messages": 4,
"messages": 6,
"level": 0
},
"120971157158625280": {
@ -1263,10 +1263,6 @@
"messages": 5,
"level": 0
},
"750064203213307905": {
"messages": 2,
"level": 0
},
"631673794783870986": {
"messages": 1,
"level": 0
@ -1320,7 +1316,7 @@
"level": 0
},
"486352184707907585": {
"messages": 3,
"messages": 4,
"level": 0
},
"309170189164085249": {
@ -1336,7 +1332,7 @@
"level": 0
},
"478243224469766144": {
"messages": 1,
"messages": 2,
"level": 0
},
"425065519360507904": {
@ -1348,7 +1344,7 @@
"level": 0
},
"98464148379148288": {
"messages": 1358,
"messages": 1396,
"level": 9
},
"1025723411680460840": {
@ -1468,7 +1464,7 @@
"level": 0
},
"207828776262828034": {
"messages": 5,
"messages": 6,
"level": 0
},
"819948487588184125": {
@ -1480,7 +1476,7 @@
"level": 0
},
"889624632724963329": {
"messages": 35,
"messages": 37,
"level": 1
},
"687692546314600530": {
@ -1568,8 +1564,8 @@
"level": 0
},
"1018003331890810990": {
"messages": 12,
"level": 0
"messages": 15,
"level": 1
},
"999815021301334147": {
"messages": 4,
@ -1608,8 +1604,8 @@
"level": 0
},
"306234177404272640": {
"messages": 32,
"level": 0
"messages": 48,
"level": 1
},
"602538366831034368": {
"messages": 2,
@ -1624,7 +1620,7 @@
"level": 0
},
"792098245441486859": {
"messages": 68,
"messages": 70,
"level": 2
},
"544435655070056448": {
@ -1664,7 +1660,7 @@
"level": 0
},
"937750032344571934": {
"messages": 96,
"messages": 102,
"level": 2
},
"873149038709571594": {
@ -1712,7 +1708,7 @@
"level": 0
},
"825286490828701699": {
"messages": 3,
"messages": 6,
"level": 0
},
"877631827337150615": {
@ -1732,7 +1728,7 @@
"level": 0
},
"796040852400635914": {
"messages": 314,
"messages": 354,
"level": 4
},
"1011307308325818438": {
@ -1748,7 +1744,7 @@
"level": 0
},
"673289306424475659": {
"messages": 103,
"messages": 117,
"level": 2
},
"907163452043305000": {
@ -1832,7 +1828,7 @@
"level": 0
},
"335637071878422529": {
"messages": 98,
"messages": 125,
"level": 2
},
"646684489573203968": {
@ -1848,15 +1844,15 @@
"level": 0
},
"682165767109738507": {
"messages": 103,
"level": 0
"messages": 106,
"level": 2
},
"127840266701766656": {
"messages": 6,
"level": 0
},
"396778041470222349": {
"messages": 98,
"messages": 100,
"level": 2
},
"967849095379189861": {
@ -1864,8 +1860,8 @@
"level": 0
},
"1031950921233600662": {
"messages": 14,
"level": 0
"messages": 15,
"level": 1
},
"907951346769092618": {
"messages": 3,
@ -1932,8 +1928,8 @@
"level": 0
},
"813866707365265419": {
"messages": 100,
"level": 0
"messages": 109,
"level": 2
},
"726188513518813275": {
"messages": 1,
@ -1976,7 +1972,7 @@
"level": 0
},
"1030526730462572558": {
"messages": 189,
"messages": 191,
"level": 3
},
"530533266206359552": {
@ -1984,7 +1980,7 @@
"level": 0
},
"479291578352140298": {
"messages": 1,
"messages": 7,
"level": 0
},
"889408189987192863": {
@ -2056,7 +2052,7 @@
"level": 0
},
"1023915974690340946": {
"messages": 17,
"messages": 20,
"level": 1
},
"871113268633174128": {
@ -2100,8 +2096,8 @@
"level": 0
},
"123080080946757632": {
"messages": 14,
"level": 0
"messages": 27,
"level": 1
},
"1001530115148226711": {
"messages": 1,
@ -2172,8 +2168,8 @@
"level": 0
},
"787081270475096084": {
"messages": 78,
"level": 0
"messages": 79,
"level": 2
},
"1035210998321258586": {
"messages": 4,
@ -2271,10 +2267,6 @@
"messages": 1,
"level": 0
},
"934366726282416168": {
"messages": 6,
"level": 0
},
"444210633035087873": {
"messages": 4,
"level": 0
@ -2320,7 +2312,7 @@
"level": 0
},
"406582522697482241": {
"messages": 1,
"messages": 2,
"level": 0
},
"231907580748759040": {
@ -2500,7 +2492,7 @@
"level": 0
},
"284482432684785664": {
"messages": 1,
"messages": 2,
"level": 0
},
"727948378067173407": {
@ -2512,8 +2504,8 @@
"level": 0
},
"490183428990304286": {
"messages": 50,
"level": 1
"messages": 65,
"level": 2
},
"787352638811013151": {
"messages": 1,
@ -2528,7 +2520,7 @@
"level": 0
},
"799988133893505054": {
"messages": 2,
"messages": 3,
"level": 0
},
"534500956688351242": {
@ -2556,7 +2548,7 @@
"level": 0
},
"697953686487564348": {
"messages": 102,
"messages": 110,
"level": 2
},
"664233182941413427": {
@ -2583,10 +2575,6 @@
"messages": 1,
"level": 0
},
"1040299894365241465": {
"messages": 14,
"level": 0
},
"312915980303204352": {
"messages": 2,
"level": 0
@ -2608,8 +2596,8 @@
"level": 0
},
"340587045250531358": {
"messages": 39,
"level": 1
"messages": 79,
"level": 2
},
"911709434554777660": {
"messages": 2,
@ -2628,7 +2616,7 @@
"level": 0
},
"1027639990521434172": {
"messages": 1,
"messages": 3,
"level": 0
},
"274616625292902400": {
@ -2656,7 +2644,7 @@
"level": 0
},
"701688417091584078": {
"messages": 2,
"messages": 4,
"level": 0
},
"907652504253263902": {
@ -2664,19 +2652,99 @@
"level": 0
},
"997785792401375252": {
"messages": 3,
"level": 0
},
"895364206025637998": {
"messages": 1,
"messages": 7,
"level": 0
},
"963848176912195664": {
"messages": 3,
"messages": 6,
"level": 0
},
"828585944206540850": {
"messages": 3,
"level": 0
},
"419057716200210432": {
"messages": 1,
"level": 0
},
"154312601495404544": {
"messages": 2,
"level": 0
},
"972906041295634462": {
"messages": 1,
"level": 0
},
"980710517817614336": {
"messages": 1,
"level": 0
},
"860017528109924372": {
"messages": 3,
"level": 0
},
"999736341220839464": {
"messages": 5,
"level": 0
},
"901565970974392331": {
"messages": 4,
"level": 0
},
"388211913621897216": {
"messages": 3,
"level": 0
},
"1039241529912475729": {
"messages": 1,
"level": 0
},
"562257805927776286": {
"messages": 7,
"level": 0
},
"995622955897864272": {
"messages": 42,
"level": 1
},
"153323923633733632": {
"messages": 6,
"level": 0
},
"190028480786726913": {
"messages": 2,
"level": 0
},
"528866704873488386": {
"messages": 2,
"level": 0
},
"590595536537518091": {
"messages": 1,
"level": 0
},
"576383133763764225": {
"messages": 1,
"level": 0
},
"995778519571378266": {
"messages": 10,
"level": 0
},
"328602696040841216": {
"messages": 7,
"level": 0
},
"222861120329744387": {
"messages": 1,
"level": 0
},
"927957676120473671": {
"messages": 1,
"level": 0
},
"846431793715871749": {
"messages": 1,
"level": 0
}
}

View File

@ -0,0 +1,35 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'guildMemberAdd',
execute: async(client:TClient, member:Discord.GuildMember)=>{
if (member.partial) return;
const index = member.guild.memberCount;
const suffix = ((index)=>{
const numbers = index.toString().split('').reverse(); // eg 1850 --> [0,5,8,1]
if (numbers[1] === '1'){// this is some -teen
return 'th';
} else {
if (numbers[0] === '1') return 'st';
else if (numbers[0] === '2') return 'nd';
else if (numbers[0] === '3') return 'rd';
else return 'th';
}
})(index);
const embed0: Discord.EmbedBuilder = new client.embed().setColor(client.config.embedColor).setThumbnail(member.user.displayAvatarURL({size: 2048}) || member.user.defaultAvatarURL).setTitle(`Welcome to Daggerwin, ${member.user.tag}!`).setFooter({text: `${index}${suffix} member`});
(client.channels.resolve(client.config.mainServer.channels.welcome) as Discord.TextChannel).send({embeds: [embed0]})
if (!client.config.botSwitches.logs) return;
const oldInvites = client.invites;
const newInvites = await member.guild.invites.fetch();
const usedInvite = newInvites.find((inv:any)=>oldInvites.get(inv.code)?.uses < inv.uses);
newInvites.forEach((inv:any)=>client.invites.set(inv.code,{uses: inv.uses, creator: inv.inviter.id}));
const embed1 = new client.embed().setColor(client.config.embedColorGreen).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048})).setTitle(`Member Joined: ${member.user.tag}`).setDescription(`<@${member.user.id}>\n\`${member.user.id}\``).addFields(
{name: '🔹 Account Creation Date', value: `<:t${Math.round(member.user.createdTimestamp/1000)}>\n<t:${Math.round(member.user.createdTimestamp/1000)}:R>`},
{name: '🔹 Invite Data:', value: usedInvite ? `Invite: \`${usedInvite.code}\`\nCreated by: **${usedInvite.inviter?.tag}**` : 'I couldn\'t find out how they joined!'}
);
(client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed1]})
}
}

View File

@ -0,0 +1,17 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'guildMemberRemove',
execute: async(client:TClient, member:Discord.GuildMember)=>{
if (!client.config.botSwitches.logs) return;
if (!member.joinedTimestamp) return;
const embed = new client.embed().setColor(client.config.embedColorRed).setTimestamp().setThumbnail(member.user.displayAvatarURL({size: 2048}) as string).setTitle(`Member Left: ${member.user.tag}`).setDescription(`<@${member.user.id}>\n\`${member.user.id}\``).addFields(
{name: '🔹 Account Creation Date', value: `<t:${Math.round(member.user.createdTimestamp/1000)}>\n<t:${Math.round(member.user.createdTimestamp/1000)}:R>`},
{name: '🔹 Join Date', value: `<t:${Math.round(member.joinedTimestamp/1000)}>\n<t:${Math.round(member.joinedTimestamp/1000)}:R>`},
{name: `🔹 Roles: ${member.roles.cache.size - 1}`, value: `${member.roles.cache.size > 1 ? member.roles.cache.filter((x)=>x.id !== member.guild.roles.everyone.id).sort((a,b)=>b.position - a.position).map(x=>x).join(member.roles.cache.size > 4 ? ' ' : '\n').slice(0,1024) : 'No roles'}`, inline: true},
{name: '🔹 Level messages', value: `${client.userLevels._content[member.user.id]?.messages.toLocaleString('en-US') || 0}`, inline: true}
);
(client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed]});
delete client.userLevels._content[member.user.id];
}
}

View File

@ -0,0 +1,32 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'guildMemberUpdate',
execute: async(client:TClient, oldMember:Discord.GuildMember, newMember:Discord.GuildMember)=>{
if (oldMember.guild.id != client.config.mainServer.id) return;
if (!client.config.botSwitches.logs) return;
const channel = (client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel)
if (oldMember.nickname != newMember.nickname){
const embed = new client.embed().setColor(client.config.embedColor).setTimestamp().setThumbnail(newMember.user.displayAvatarURL({size: 2048})).setTitle(`Nickname updated: ${newMember.user.tag}`).setDescription(`<@${newMember.user.id}>\n\`${newMember.user.id}\``).addFields(
{name: '🔹 Old nickname', value: `\`\`\`${oldMember.nickname == null ? ' ' : oldMember.nickname}\`\`\``},
{name: '🔹 New nickname', value: `\`\`\`${newMember.nickname == null ? ' ' : newMember.nickname}\`\`\``}
);
channel.send({embeds: [embed]})
}
/*
todo: role update
- howtobasic the nonexistent '._roles'
const newRoles = newMember._roles.filter(x=>!oldMember._roles.some(y=>y==x));
const oldRoles = oldMember._roles.filter(x=>!newMember._roles.some(y=>y==x));
const embed = new client.embed().setColor(client.config.embedColor).setThumbnail(newMember.user.displayAvatarURL({size: 2048})).setTitle(`Role updated: ${newMember.user.tag}`).setDescription(`<@${newMember.user.id}>\n\`${newMember.user.id}\``)
if (newRoles.length != 0){
embed.addFields({name: '🔹 Role added', value: newRoles.map((x)=>`<@&${x}>`).join(' ')})
}
if (oldRoles.length != 0){
embed.addFields({name: '🔹 Role removed', value: oldRoles.map((x)=>`<@&${x}>`).join(' ')})
}
channel.send({embeds: [embed]})
*/
}
}

View File

@ -0,0 +1,23 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'interactionCreate',
execute: async(client:TClient, interaction:Discord.ChatInputCommandInteraction)=>{
if (!interaction.inGuild() || !interaction.inCachedGuild() || !interaction.command) return;
if (interaction.isCommand()){
const commandFile = client.commands.get(interaction.commandName);
console.log(`[${client.moment().format('DD/MM/YY HH:mm:ss')}] ${interaction.user.tag} used /${interaction.commandName} ${interaction.options.getSubcommand() ?? ''} in #${interaction.channel.name}`);
if (!client.config.botSwitches.commands && !client.config.eval.whitelist.includes(interaction.user.id)) return interaction.reply({content: 'Commands are currently disabled.', ephemeral: true});
if (commandFile){
if (commandFile.disabled) return interaction.reply({content: 'This command is currently disabled.', ephemeral: true});
try{
commandFile.run(client, interaction);
commandFile.uses ? commandFile.uses++ : commandFile.uses = 1;
} catch (error:any){
console.log(`\x1b[31mAn error occured while running command "${commandFile.name}"`, error, error.stack);
return interaction.reply('An error occured while executing this command.');
}
}
}
}
}

View File

@ -0,0 +1,10 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'inviteCreate',
execute: async(client:TClient, invite: Discord.Invite)=>{
if (!invite.guild) return;
const newInvites = await (invite.guild as Discord.Guild).invites.fetch();
newInvites.forEach(inv=>client.invites.set(inv.code,{uses: inv.code, creator: inv.inviterId}))
}
}

View File

@ -0,0 +1,8 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'inviteDelete',
execute: async(client:TClient, invite: Discord.Invite)=>{
client.invites.delete(invite.code)
}
}

View File

@ -1,6 +1,5 @@
import Discord, { Channel, ChannelType, TextChannel } from 'discord.js';
import Discord, { ChannelType } from 'discord.js';
import { TClient } from '../client';
export default {
name: 'messageCreate',
execute: async(client:TClient, message:Discord.Message)=>{
@ -10,27 +9,6 @@ export default {
const msgarr = message.content.toLowerCase().split(' ');
let automodded: any;
// Command handler
if (message.content.startsWith(client.config.prefix)){
const args = message.content.slice(client.config.prefix.length).replace(/\n/g, " ").split(" ");
const commandFile = client.commands.find((x: any)=>x.name === args[0].toLowerCase() || x.alias?.includes(args[0].toLowerCase()));
if (commandFile){
console.log(`[${client.moment().format('DD/MM/YY HH:mm:ss')}] ${message.author.tag} used ${client.config.prefix}${commandFile.name} in #${message.channelId}`);
// do the cmd
try {
commandFile.run(client, message, args);
commandFile.uses ? commandFile.uses++ : commandFile.uses = 1;
return
} catch (error){
console.log(error)
client.channels.fetch(client.config.mainServer.channels.errors).then((channel: TextChannel)=>{
channel.send({embeds: [new client.embed().setColor('#420420').setTitle('Error caught!').setDescription(`**Error:** \`${error.message}\`\n\n**Stack:** \`${`${error.stack}`.slice(0, 2500)}\``)]})
})
return message.reply('An error occured while executing that command.')
}
}
}
function onTimeout(){
delete client.repeatedMessages[message.author.id]
}
@ -59,7 +37,7 @@ export default {
// a spammed message is one that has been sent atleast 4 times in the last threshold milliseconds
const spammedMessage = client.repeatedMessages[message.author.id]?.find((x:any)=>{
return client.repeatedMessages[message.author.id].filter((y:any)=>x.cont === y.cont).size >= 4;
return client.repeatedMessages[message.author.id].size >= 4;
});
// if a spammed message exists;
@ -90,10 +68,11 @@ export default {
'742324777934520350', // #discord-moderators
]
if (message.content.toLowerCase().includes('tenor.com/view') || message.content.toLowerCase().includes('giphy.com/gifs/') || message.content.toLowerCase().includes('giphy.com/media/') && bannedChannels.includes(message.channelId)) {
message.reply('Gifs are disabled in this channel.').then((msg: any)=>message.delete())
message.reply('Gifs are not allowed in this channel.').then((msg: any)=>message.delete())
}
// Autoresponse:tm:
if (!client.config.botSwitches.autores && !automodded) {
if (message.mentions.members.has('309373272594579456') && !client.isStaff(message.member) && message.type != 19){
message.reply('Please don\'t tag Daggerwin, read rule 14 in <#468846117405196289>')
}
@ -130,3 +109,4 @@ export default {
}
}
}
}

View File

@ -0,0 +1,16 @@
import Discord from 'discord.js';
import { TClient } from '../client';
export default {
name: 'messageDelete',
execute: async(client:TClient, msg:Discord.Message)=>{
if (!client.config.botSwitches.logs) return;
const channel = client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel;
if (msg.partial) return;
if (msg.author.bot) return;
const embed = new client.embed().setColor(client.config.embedColorRed).setTimestamp().setAuthor({name: `Author: ${msg.author.tag} (${msg.author.id})`, iconURL: `${msg.author.displayAvatarURL()}`}).setTitle('Message deleted').setDescription(`<@${msg.author.id}>\nContent:\n\`\`\`\n${msg.content}\n\`\`\`\nChannel: <#${msg.channelId}>`)
channel.send({embeds: [embed]})
if (msg.attachments?.first()?.width && ['png', 'jpeg', 'jpg', 'gif', 'webp'].some(x=>((msg.attachments.first() as Discord.Attachment).name as string).endsWith(x))) {
embed.setImage(`${[msg.attachments?.first() as Discord.Attachment]}`)
}
}
}

View File

@ -0,0 +1,15 @@
import Discord, { Message, Snowflake } from 'discord.js';
import { TClient } from '../client';
export default {
name: 'messageDeleteBulk',
execute: async(client:TClient, messages:Discord.Collection<Snowflake, Message>)=>{
const channel = client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel;
if (!client.config.botSwitches.logs) return;
let text = '';
messages.forEach((m)=>{
text += `${m.author.username}: ${m.content}\n`;
});
const embed = new client.embed().setColor(client.config.embedColorRed).setTimestamp().setTitle(`${messages.size} messages were purged`).setDescription(`\`\`\`${text}\`\`\``.slice(0,3900)).addFields({name: 'Channel', value: `<#${(messages.first() as Discord.Message).channel.id}>`});
channel.send({embeds: [embed]})
}
}

View File

@ -0,0 +1,18 @@
import Discord, { ActionRowBuilder, ButtonBuilder } from 'discord.js';
import { TClient } from '../client';
export default {
name: 'messageUpdate',
execute: async(client:TClient, oldMsg:Discord.Message, newMsg:Discord.Message)=>{
if (!client.config.botSwitches.logs) return;
if (oldMsg.author == null) return;
if (oldMsg?.author.bot) return;
if (oldMsg.partial) return;
if (newMsg.partial) return;
if (!newMsg.member) return;
const msgarr = newMsg.content.toLowerCase().split(' ');
if (client.bannedWords._content.some((word:string)=>msgarr.includes(word)) && (!client.isStaff(newMsg.member))) newMsg.delete();
if (newMsg.content === oldMsg.content) return;
const embed = new client.embed().setColor(client.config.embedColor).setTimestamp().setAuthor({name: `Author: ${oldMsg.author.tag} (${oldMsg.author.id})`, iconURL: `${oldMsg.author.displayAvatarURL()}`}).setTitle('Message edited').setDescription(`<@${oldMsg.author.id}>\nOld content:\n\`\`\`\n${oldMsg.content}\n\`\`\`\nNew content:\n\`\`\`\nChannel: <#${oldMsg.channelId}>`);
(client.channels.resolve(client.config.mainServer.channels.logs) as Discord.TextChannel).send({embeds: [embed], components: [new ActionRowBuilder<ButtonBuilder>().addComponents(new ButtonBuilder().setStyle(5).setURL(`${oldMsg.url}`).setLabel('Jump to message'))]});
}
}

View File

@ -46,17 +46,10 @@ process.on('error', async(error: Error)=>{
(client.channels.resolve(client.config.mainServer.channels.errors) as Discord.TextChannel).send({embeds: [new client.embed().setColor('#420420').setTitle('Error caught!').setDescription(`**Error:** \`${error.message}\`\n\n**Stack:** \`${`${error.stack}`.slice(0, 2500)}\``)]})
});
// Command handler
const commandFiles = fs.readdirSync('./commands').filter(file=>file.endsWith('.js'));
for (const file of commandFiles){
const command = require(`./commands/${file}`);
client.commands.set(command.name, command)
}
// Daggerwin MP loop
setInterval(async()=>{
if (!client.config.botSwitches.mpstats) return;
const msg = await client.channels.resolve('ChannelID').messages.fetch('MessageID')
const msg = await (client.channels.resolve('ChannelID') as Discord.TextChannel).messages.fetch('MessageID')
const embed = new client.embed();
let Players = [];
let Server: any;
@ -132,18 +125,6 @@ setInterval(async()=>{
// Event loop for punishments and daily msgs
setInterval(async()=>{
interface Punishment {
id: number;
type: string;
member: string;
moderator: string;
expired?: boolean;
time?: number;
reason: string;
endTime?: number;
cancels?: number;
duration?: number;
}
const now = Date.now()
const lrsStart = client.config.LRSstart;
@ -171,69 +152,15 @@ setInterval(async()=>{
}
}, 5000)
// Assign page number to commands
const categories = {};
while (client.commands.some(command=>!command.hidden && !command.page)){
const command = client.commands.find(command=>!command.hidden && !command.page);
if (!command.category) command.category = 'Misc';
if (!categories[command.category]) categories[command.category] = {text: '', currentPage: 1}
const commandInfo = client.commandInfo(client, command, client.helpDefaultOptions);
if (categories[command.category].text.length+commandInfo.length>1024){
categories[command.category].text = commandInfo;
categories[command.category].currentPage++;
} else {
categories[command.category].text += commandInfo;
}
command.page = categories[command.category].currentPage;
}
client.categoryNames = Object.keys(categories);
delete categories;
// create pages without contents
client.commands.filter(command=>!command.hidden).forEach(command=>{
if (!client.commandPages.some((x:any)=>x.category === command.category && x.pages === command.pages)){
client.commandPages.push({
name: `${command.category} - Page ${command.page}/${Math.max(...client.commands.filter((x:any)=>x.category === command.category).map((x:any)=>x.page))}`,
category: command.category,
page: command.page
});
}
});
client.commandPages.sort((a: any, b: any)=>{
if (a.name<b.name){
return -1;
} else if (a.name>b.name){
return 1;
} else {
return 0;
}
});
// Punishments
interface punOpt {
time: number,
reason: string,
message: any
}
interface punData {
id: number;
type: string;
member: string;
moderator: string;
expired?: boolean;
time?: number;
reason?: string;
endTime?: number;
cancels?: number;
duration?: number;
}
Object.assign(client.punishments,{
createId(){
return Math.max(...client.punishments._content.map((x: punData)=>x.id), 0) + 1;
return Math.max(...client.punishments._content.map((x:Punishment)=>x.id), 0) + 1;
},
async addPunishment(type: string, member: Discord.GuildMember, options: punOpt, moderator: string){
async addPunishment(type: string, member: any, options: punOpt, moderator: string){
const now = Date.now();
const { time, reason, message } = options;
const ms = import('ms');
const { time, reason, interaction } = options;
const ms = require('ms');
let timeInMillis;
if (type !== 'mute'){
timeInMillis = time ? ms(time) : null;
@ -242,14 +169,14 @@ Object.assign(client.punishments,{
}
switch (type) {
case 'ban':
const banData: punData = {type, id: this.createId(), member: member.id, moderator, time: now};
let dm1;
const banData: Punishment = {type, id: this.createId(), member: member.id, moderator, time: now};
let dm1:any;
try {
dm1 = await member.send(`You've been banned from ${message.guild.name} ${timeInMillis ? `for ${client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Unspecified'}\` (Case #${banData.id})`)
dm1 = await member.send(`You've been banned from ${interaction.guild.name} ${timeInMillis ? `for ${client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Reason unspecified'}\` (Case #${banData.id})`)
} catch (err) {
setTimeout(()=>message.channel.send('Failed to DM user.'), 500)
setTimeout(()=>interaction.channel.send('Failed to DM user.'), 500)
}
const banResult = await message.guild.bans.create(member.id, {reason: `${reason || 'Unspecified'} | Case #${banData.id}`}).catch((err: Error)=>err.message);
const banResult = await interaction.guild.bans.create(member.id, {reason: `${reason || 'Reason unspecified'} | Case #${banData.id}`}).catch((err: Error)=>err.message);
if (typeof banResult === 'string'){
dm1.delete();
return `Ban was unsuccessful: ${banResult}`;
@ -263,20 +190,20 @@ Object.assign(client.punishments,{
this.addData(banData);
this.forceSave();
return new client.embed().setColor(client.config.embedColor).setTitle(`Case #${banData.id}: Ban`).setDescription(`${member.tag}\n<@${member.id}>\n(\`${member.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Unspecified'}\``},
{name: 'Reason', value: `\`${reason || 'Reason unspecified'}\``},
{name: 'Duration', value: `${timeInMillis ? `for ${client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'}`}
)
}
case 'softban':
const guild = member.guild;
const softbanData: punData = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const dm2 = await member.send(`You've been softbanned from ${member.guild.name} for reason \`${reason || 'Unspecified'}\` (Case #${softbanData.id})`).catch(err=>setTimeout(()=>message.channel.send(`Failed to DM <@${member.user.id}>.`), 500));
const softbanResult = await member.ban({deleteMessageDays: 7, reason: `${reason || 'Unspecified'} | Case #${softbanData.id}`}).catch((err: Error)=>err.message);
const softbanData: Punishment = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const dm2 = await member.send(`You've been softbanned from ${member.guild.name} for reason \`${reason || 'Reason unspecified'}\` (Case #${softbanData.id})`).catch(err=>setTimeout(()=>interaction.channel.send(`Failed to DM <@${member.user.id}>.`), 500));
const softbanResult = await member.ban({deleteMessageDays: 7, reason: `${reason || 'Reason unspecified'} | Case #${softbanData.id}`}).catch((err: Error)=>err.message);
if (typeof softbanResult === 'string'){
dm2.delete();
return `Softban was unsuccessful: ${softbanResult}`;
} else {
const unbanResult = guild.members.unban(softbanData.member, `${reason || 'Unspecified'} | Case #${softbanData.id}`).catch((err: Error)=>err.message);
const unbanResult = guild.members.unban(softbanData.member, `${reason || 'Reason unspecified'} | Case #${softbanData.id}`).catch((err: Error)=>err.message);
if (typeof unbanResult === 'string'){
return `Softban (unban) was unsuccessful: ${softbanResult}`
} else {
@ -285,14 +212,14 @@ Object.assign(client.punishments,{
this.addData(softbanData)
this.forceSave();
return new client.embed().setColor(client.config.embedColor).setTitle(`Case #${softbanData.id}: Softban`).setDescription(`${member.user.tag}\n<@${member.user.id}>\n(\`${member.user.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Unspecified'}\``}
{name: 'Reason', value: `\`${reason || 'Reason unspecified'}\``}
)
}
}
case 'kick':
const kickData: punData = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const dm3 = await member.send(`You've been kicked from ${member.guild.name} for reason \`${reason || 'Unspecified'}\` (Case #${kickData.id})`).catch((err:Error)=>setTimeout(()=>message.channel.send(`Failed to DM <@${member.user.id}>.`), 500));
const kickResult = await member.kick(`${reason || 'Unspecified'} | Case #${kickData.id}`).catch((err:Error)=>err.message);
const kickData: Punishment = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const dm3 = await member.send(`You've been kicked from ${member.guild.name} for reason \`${reason || 'Reason unspecified'}\` (Case #${kickData.id})`).catch((err:Error)=>setTimeout(()=>interaction.channel.send(`Failed to DM <@${member.user.id}>.`), 500));
const kickResult = await member.kick(`${reason || 'Reason unspecified'} | Case #${kickData.id}`).catch((err:Error)=>err.message);
if (typeof kickResult === 'string'){
dm3.delete();
return `Kick was unsuccessful: ${kickResult}`;
@ -302,17 +229,17 @@ Object.assign(client.punishments,{
this.addData(kickData);
this.forceSave();
return new client.embed().setColor(client.config.embedColor).setTitle(`Case #${kickData.id}: Kick`).setDescription(`${member.user.tag}\n<@${member.user.id}>\n(\`${member.user.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Unspecified'}\``}
{name: 'Reason', value: `\`${reason || 'Reason unspecified'}\``}
)
}
case 'mute':
const muteData: punData = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const muteData: Punishment = {type, id: this.createId(), member: member.user.id, moderator, time: now};
let muteResult;
const dm4 = await member.send(`You've been muted in ${member.guild.name} ${timeInMillis ? `for ${client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Unspecified'}\` (Case #${muteData.id})`).catch((err:Error)=>setTimeout(()=>message.channel.send('Failed to DM user.'), 500));
const dm4 = await member.send(`You've been muted in ${member.guild.name} ${timeInMillis ? `for ${client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)` : 'forever'} for reason \`${reason || 'Reason unspecified'}\` (Case #${muteData.id})`).catch((err:Error)=>setTimeout(()=>interaction.channel.send('Failed to DM user.'), 500));
if (timeInMillis){
muteResult = await member.timeout(timeInMillis, `${reason || 'Unspecified'} | Case #${muteData.id}`).catch((err: Error)=>err.message);
muteResult = await member.timeout(timeInMillis, `${reason || 'Reason unspecified'} | Case #${muteData.id}`).catch((err: Error)=>err.message);
} else {
muteResult = await member.timeout(2419200000, `${reason || 'Unspecified'} | Case #${muteData.id}`).catch((err: Error)=>err.message);
muteResult = await member.timeout(2419200000, `${reason || 'Reason unspecified'} | Case #${muteData.id}`).catch((err: Error)=>err.message);
}
if (typeof muteResult === 'string') {
dm4.delete();
@ -326,15 +253,15 @@ Object.assign(client.punishments,{
client.makeModlogEntry(muteData, client);
this.addData(muteData);
this.forceSave();
const embedm = new client.embed().setColor().setTitle(`Case #${muteData.id}: Mute`).setDescription(`${member.user.tag}\n<@${member.user.id}>\n(\`${member.user.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Unspecified'}\``},
const embedm = new client.embed().setColor(client.config.embedColor).setTitle(`Case #${muteData.id}: Mute`).setDescription(`${member.user.tag}\n<@${member.user.id}>\n(\`${member.user.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Reason unspecified'}\``},
{name: 'Duration', value: `${client.formatTime(timeInMillis, 4, {longNames: true, commas: true})} (${timeInMillis}ms)`}
)
if (moderator !== '795443537356521502') {return embedm};
}
case 'warn':
const warnData: punData = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const warnResult = await member.send(`You've been warned in ${member.guild.name} for reason \`${reason || 'Unspecified'}\` (Case #${warnData.id})`).catch((err:Error)=>setTimeout(()=>message.channel.send(`Failed to DM <@${member.user.id}>.`), 500));
const warnData: Punishment = {type, id: this.createId(), member: member.user.id, moderator, time: now};
const warnResult = await member.send(`You've been warned in ${member.guild.name} for reason \`${reason || 'Reason unspecified'}\` (Case #${warnData.id})`).catch((err:Error)=>setTimeout(()=>interaction.channel.send(`Failed to DM <@${member.user.id}>.`), 500));
if (typeof warnResult === 'string'){
return `Warn was unsuccessful: ${warnResult}`;
} else {
@ -343,7 +270,7 @@ Object.assign(client.punishments,{
this.addData(warnData);
this.forceSave();
const embedw = new client.embed().setColor(client.config.embedColor).setTitle(`Case #${warnData.id}: Warn`).setDescription(`${member.user.tag}\n<@${member.user.id}>\n(\`${member.user.id}\`)`).addFields(
{name: 'Reason', value: `\`${reason || 'Unspecified'}\``}
{name: 'Reason', value: `\`${reason || 'Reason unspecified'}\``}
)
if (moderator !== '795443537356521502') {return embedw};
}
@ -359,14 +286,14 @@ Object.assign(client.punishments,{
let removePunishmentResult;
if(punishment.type === 'ban'){
// unban
removePunishmentResult = await guild.members.unban(punishment.member, `${reason || 'Unspecified'} | Case #${id}`).catch((err: TypeError)=>err.message);
removePunishmentResult = await guild.members.unban(punishment.member, `${reason || 'Reason unspecified'} | Case #${id}`).catch((err: TypeError)=>err.message);
}else if (punishment.type === 'mute') {
//remove role
const member = await guild.members.fetch(punishment.member).catch(err=>undefined);
if (member){
removePunishmentResult = await member
if (typeof removePunishmentResult !== 'string'){
member.timeout(null, `${reason || 'Unspecified'} | Case #${id}`)
member.timeout(null, `${reason || 'Reason unspecified'} | Case #${id}`)
removePunishmentResult.send(`You've been unmuted in ${removePunishmentResult.guild.name}.`)
removePunishmentResult = removePunishmentResult.user; //removing a role returns a guildmember
}
@ -383,7 +310,7 @@ Object.assign(client.punishments,{
client.makeModlogEntry(removePunishmentData, client);
this._content[this._content.findIndex(x=>x.id === punishment.id)].expired = true;
this.addData(removePunishmentData).forceSave();
return `Successfully ${punishment.type === 'ban' ? 'unbanned' : 'unmuted'} ${removePunishmentResult?.tag} (\`${removePunishmentResult?.id}\`) for reason \`${reason || 'Unspecified'}\``;
return `Successfully ${punishment.type === 'ban' ? 'unbanned' : 'unmuted'} ${removePunishmentResult?.tag} (\`${removePunishmentResult?.id}\`) for reason \`${reason || 'Reason unspecified'}\``;
}
} else {
try {
@ -392,7 +319,7 @@ Object.assign(client.punishments,{
this._content[this._content.findIndex(x=>x.id === punishment.id)].expired = true;
this.addData(removePunishmentData).forceSave();
return `Successfully removed Case #${punishment.id} (type: ${punishment.type}, user: ${punishment.member}).`;
} catch(error: Error){
} catch(error: any){
return `${punishment.type[0].toUpperCase()+punishment.type.slice(1)} removal was unsuccessful: ${error.message}`
}
}

31
src/typings/interfaces.d.ts vendored Normal file
View File

@ -0,0 +1,31 @@
interface createTableOpt {
columnAlign: any,
columnSeparator: any,
columnEmptyChar: any
}
interface formatTimeOpt {
longNames: boolean,
commas: boolean
}
interface CommandInfoOpt {
insertNewline: boolean,
parts: string[], //idfk
titles: string[]
}
interface punOpt {
time?: string,
reason?: string,
interaction?: any
}
interface Punishment {
id: number;
type: string;
member: string;
moderator: string;
expired?: boolean;
time?: number;
reason?: string;
endTime?: number;
cancels?: number;
duration?: number;
}