Merge pull request #385 from VermiumSifell/dev
Better managers & logging & gdpr fix for guilds & some minor changes
This commit is contained in:
commit
41c6234d81
16 changed files with 211 additions and 103 deletions
|
@ -48,6 +48,7 @@
|
|||
"tsconfig-paths": "^4.0.0",
|
||||
"typescript": "^4.6.3",
|
||||
"uuid": "^8.3.2",
|
||||
"winston": "^3.8.0",
|
||||
"winston-daily-rotate-file": "^4.6.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -7,66 +7,60 @@ import timeoutSchema from "../../models/timeout";
|
|||
|
||||
import logger from "../../logger";
|
||||
|
||||
import { Guild } from "discord.js";
|
||||
import { Snowflake } from "discord.js";
|
||||
|
||||
export default async (guild: Guild) => {
|
||||
export default async (id: Snowflake) => {
|
||||
await guildSchema
|
||||
.deleteMany({ guildId: guild.id })
|
||||
.deleteMany({ guildId: id })
|
||||
.then(async () => {
|
||||
return logger?.silly(`Deleted guild: ${guild.id}`);
|
||||
return logger?.silly(`Deleted guild: ${id}`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(`Error deleting guild: ${guild.id} - ${error}`);
|
||||
logger?.error(`Error deleting guild: ${id} - ${error}`);
|
||||
});
|
||||
|
||||
await userSchema
|
||||
.deleteMany({ guildId: guild.id })
|
||||
.deleteMany({ guildId: id })
|
||||
.then(async () => {
|
||||
logger?.silly(`Deleted users for guild: ${guild.id} from database`);
|
||||
logger?.silly(`Deleted users for guild: ${id} from database`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(`Error deleting users for guild: ${guild.id} - ${error}`);
|
||||
logger?.error(`Error deleting users for guild: ${id} - ${error}`);
|
||||
});
|
||||
|
||||
await apiSchema
|
||||
.deleteMany({ guildId: guild.id })
|
||||
.deleteMany({ guildId: id })
|
||||
.then(async () => {
|
||||
logger?.silly(`Deleted apis for guild: ${guild.id} from database`);
|
||||
logger?.silly(`Deleted apis for guild: ${id} from database`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(`Error deleting apis for guild: ${guild.id} - ${error}`);
|
||||
logger?.error(`Error deleting apis for guild: ${id} - ${error}`);
|
||||
});
|
||||
|
||||
await counterSchema
|
||||
.deleteMany({ guildId: guild.id })
|
||||
.deleteMany({ guildId: id })
|
||||
.then(async () => {
|
||||
logger?.silly(`Deleted counters for guild: ${guild.id} from database`);
|
||||
logger?.silly(`Deleted counters for guild: ${id} from database`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(
|
||||
`Error deleting counters for guild: ${guild.id} - ${error}`
|
||||
);
|
||||
logger?.error(`Error deleting counters for guild: ${id} - ${error}`);
|
||||
});
|
||||
|
||||
await shopRoleSchema
|
||||
.deleteMany({ guildId: guild.id })
|
||||
.deleteMany({ guildId: id })
|
||||
.then(async () => {
|
||||
logger?.silly(`Deleted shop roles for guild: ${guild.id} from database`);
|
||||
logger?.silly(`Deleted shop roles for guild: ${id} from database`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(
|
||||
`Error deleting shop roles for guild: ${guild.id} - ${error}`
|
||||
);
|
||||
logger?.error(`Error deleting shop roles for guild: ${id} - ${error}`);
|
||||
});
|
||||
|
||||
await timeoutSchema
|
||||
.deleteMany({ guildId: guild.id })
|
||||
.deleteMany({ guildId: id })
|
||||
.then(async () => {
|
||||
logger?.silly(`Deleted timeouts for guild: ${guild.id} from database`);
|
||||
logger?.silly(`Deleted timeouts for guild: ${id} from database`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(
|
||||
`Error deleting timeouts for guild: ${guild.id} - ${error}`
|
||||
);
|
||||
logger?.error(`Error deleting timeouts for guild: ${id} - ${error}`);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// Dependencies
|
||||
import { Guild } from "discord.js";
|
||||
import { Snowflake } from "discord.js";
|
||||
|
||||
// Models
|
||||
import guildSchema from "../../models/guild";
|
||||
|
@ -8,18 +8,18 @@ import guildSchema from "../../models/guild";
|
|||
import logger from "../../logger";
|
||||
|
||||
// Function
|
||||
export default async (guild: Guild) => {
|
||||
const guildObj = await guildSchema?.findOne({ guildId: guild.id });
|
||||
export default async (id: Snowflake) => {
|
||||
const guildObj = await guildSchema?.findOne({ guildId: id });
|
||||
if (guildObj === null) {
|
||||
const newGuildObj = new guildSchema({ guildId: guild.id });
|
||||
const newGuildObj = new guildSchema({ guildId: id });
|
||||
|
||||
await newGuildObj
|
||||
.save()
|
||||
.then(async () => {
|
||||
logger?.silly(`Created guild: ${guild.id}`);
|
||||
logger?.silly(`Created guild: ${id}`);
|
||||
})
|
||||
.catch(async (error) => {
|
||||
logger?.error(`Error creating guild: ${guild.id} - ${error}`);
|
||||
logger?.error(`Error creating guild: ${id} - ${error}`);
|
||||
});
|
||||
|
||||
return newGuildObj;
|
||||
|
|
|
@ -2,7 +2,5 @@ import fs from "fs";
|
|||
const fsPromises = fs.promises;
|
||||
|
||||
export default async (path: string) => {
|
||||
return fsPromises.readdir(path).catch(async (err) => {
|
||||
throw new Error(`Could not list directory: ${path}`, err);
|
||||
});
|
||||
return fsPromises.readdir(path);
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { token, intents } from "./config/discord";
|
||||
|
||||
import { Client } from "discord.js"; // discord.js
|
||||
import { Client, Collection } from "discord.js"; // discord.js
|
||||
|
||||
import * as managers from "./managers";
|
||||
|
||||
|
@ -11,6 +11,9 @@ const main = async () => {
|
|||
intents,
|
||||
});
|
||||
|
||||
// Create command collection
|
||||
client.commands = new Collection();
|
||||
|
||||
await managers.start(client);
|
||||
|
||||
// Authorize with Discord's API
|
||||
|
|
35
src/jobs/keepDataUpToDate/index.ts
Normal file
35
src/jobs/keepDataUpToDate/index.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { Client, Guild } from "discord.js";
|
||||
import logger from "../../logger";
|
||||
import dropGuild from "../../helpers/dropGuild";
|
||||
import fetchGuild from "../../helpers/fetchGuild";
|
||||
|
||||
import guildSchema from "../../models/guild";
|
||||
|
||||
export const options = {
|
||||
schedule: "0 0 1 * *", // https://crontab.guru/
|
||||
};
|
||||
|
||||
export const execute = async (client: Client) => {
|
||||
const guildsDB = await guildSchema.find();
|
||||
const guildsDiscord = client.guilds.cache;
|
||||
|
||||
const shouldNotExist = guildsDB
|
||||
.filter((x) => !guildsDiscord.some((y) => y.id === x.guildId))
|
||||
.map((z) => z.guildId);
|
||||
|
||||
const shouldExist = guildsDiscord
|
||||
.filter((x) => !guildsDB.some((y) => y.guildId === x.id))
|
||||
.map((z) => z.id);
|
||||
|
||||
if (shouldNotExist) {
|
||||
shouldNotExist.forEach(async (x) => {
|
||||
await dropGuild(x);
|
||||
});
|
||||
}
|
||||
|
||||
if (shouldExist) {
|
||||
shouldExist.forEach(async (x) => {
|
||||
await fetchGuild(x);
|
||||
});
|
||||
}
|
||||
};
|
|
@ -5,31 +5,65 @@ import logger from "../../logger";
|
|||
import { ICommand } from "../../interfaces/Command";
|
||||
|
||||
export const register = async (client: Client) => {
|
||||
client.commands = new Collection();
|
||||
|
||||
// Get name of directories containing commands
|
||||
const commandNames = await listDir("plugins/commands");
|
||||
if (!commandNames) throw new Error("📦 No commands available");
|
||||
|
||||
if (!commandNames) throw new Error("Could not list commands");
|
||||
const amountOfCommands = commandNames.length;
|
||||
let importedCommandAmount = 0;
|
||||
logger.info(`📦 Trying to load ${amountOfCommands} commands`);
|
||||
|
||||
logger.info(`Loading ${commandNames.length} commands`);
|
||||
const importCommand = async (commandName: string) => {
|
||||
// Import command from plugins/commands
|
||||
const command: ICommand = await import(
|
||||
`../../plugins/commands/${commandName}`
|
||||
);
|
||||
if (!command)
|
||||
throw new Error(`📦 No command found while importing "${commandName}"`);
|
||||
if (!command.builder)
|
||||
throw new Error(
|
||||
`📦 No command builder found while importing "${commandName}"`
|
||||
);
|
||||
if (!command.execute)
|
||||
throw new Error(
|
||||
`📦 No command execute found while importing "${commandName}"`
|
||||
);
|
||||
if (!command.moduleData)
|
||||
throw new Error(
|
||||
`📦 No command moduleData found while importing "${commandName}"`
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
commandNames.map(async (commandName) => {
|
||||
const command: ICommand = await import(
|
||||
`../../plugins/commands/${commandName}`
|
||||
).catch(async (e) => {
|
||||
throw new Error(`Could not load command: ${commandName}`, e);
|
||||
// Add command to collection
|
||||
client.commands.set(command.builder.name, command);
|
||||
importedCommandAmount += 1;
|
||||
};
|
||||
|
||||
// Send log message when it's done loading commands
|
||||
const doneImporting = async () => {
|
||||
if (importedCommandAmount !== amountOfCommands) {
|
||||
return logger.warn(
|
||||
`📦 Failed importing ${
|
||||
amountOfCommands - importedCommandAmount
|
||||
} of ${amountOfCommands} commands`
|
||||
);
|
||||
}
|
||||
|
||||
return logger.info(`📦 Managed to load all commands`);
|
||||
};
|
||||
|
||||
// Start importing commands
|
||||
commandNames.forEach(async (commandName: string, index: number) => {
|
||||
await importCommand(commandName)
|
||||
.then(async () => {
|
||||
logger.debug(`📦 Imported the "${commandName}" command`);
|
||||
})
|
||||
.catch(async (err) => {
|
||||
logger.error(err);
|
||||
});
|
||||
|
||||
client.commands.set(command.builder.name, command);
|
||||
|
||||
logger.verbose(`${command.builder.name} loaded`);
|
||||
})
|
||||
)
|
||||
.then(async () => {
|
||||
logger.info(`Finished loading commands.`);
|
||||
})
|
||||
.catch(async (err) => {
|
||||
throw new Error(`Could not load commands: ${err}`);
|
||||
});
|
||||
// If done importing
|
||||
if (index + 1 === amountOfCommands) {
|
||||
await doneImporting();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
|
|
@ -1,27 +1,6 @@
|
|||
// 3rd party dependencies
|
||||
import mongoose from "mongoose";
|
||||
|
||||
// Dependencies
|
||||
import logger from "../../logger";
|
||||
|
||||
// Configuration
|
||||
import { url } from "../../config/database";
|
||||
|
||||
export const connect = async () => {
|
||||
await mongoose
|
||||
.connect(url)
|
||||
.then(async (connection) => {
|
||||
logger.info(`Connected to database: ${connection.connection.name}`);
|
||||
})
|
||||
.catch(async (e) => {
|
||||
logger.error("Could not connect to database", e);
|
||||
});
|
||||
|
||||
mongoose.connection.on("error", async (error) => {
|
||||
logger.error(`${error}`);
|
||||
});
|
||||
|
||||
mongoose.connection.on("warn", async (warning) => {
|
||||
logger.warn(warning);
|
||||
});
|
||||
await mongoose.connect(url);
|
||||
};
|
||||
|
|
|
@ -6,15 +6,35 @@ import logger from "../../logger";
|
|||
|
||||
export const register = async (client: Client) => {
|
||||
const eventNames = await listDir("plugins/events");
|
||||
if (!eventNames) return;
|
||||
if (!eventNames) throw new Error("📦 No events available");
|
||||
|
||||
for await (const eventName of eventNames) {
|
||||
const amountOfEvents = eventNames.length;
|
||||
let importedEventAmount = 0;
|
||||
logger.info(`📦 Trying to load ${amountOfEvents} events`);
|
||||
|
||||
const importEvent = async (eventName: string) => {
|
||||
// Import event from plugins/events
|
||||
const event: IEvent = await import(`../../plugins/events/${eventName}`);
|
||||
const eventExecutor = async (...args: Promise<void>[]) =>
|
||||
event.execute(...args).catch(async (err) => {
|
||||
if (!event)
|
||||
throw new Error(`📦 No event found while importing "${eventName}"`);
|
||||
if (!event.options)
|
||||
throw new Error(
|
||||
`📦 No event options found while importing "${eventName}"`
|
||||
);
|
||||
if (!event.execute)
|
||||
throw new Error(
|
||||
`📦 No event execute found while importing "${eventName}"`
|
||||
);
|
||||
|
||||
// Register event
|
||||
const eventExecutor = async (...args: Promise<void>[]) => {
|
||||
await event.execute(...args).catch(async (err) => {
|
||||
logger.error(`${err}`);
|
||||
});
|
||||
if (!event.options?.type) return;
|
||||
};
|
||||
|
||||
if (!event.options?.type)
|
||||
throw new Error(`📦 No event type found while importing "${eventName}"`);
|
||||
|
||||
switch (event.options.type) {
|
||||
case "once":
|
||||
|
@ -25,5 +45,49 @@ export const register = async (client: Client) => {
|
|||
client.on(eventName, eventExecutor);
|
||||
break;
|
||||
}
|
||||
}
|
||||
importedEventAmount += 1;
|
||||
};
|
||||
|
||||
// Send log message when it's done loading events
|
||||
const doneImporting = async () => {
|
||||
if (importedEventAmount !== amountOfEvents) {
|
||||
return logger.warn(
|
||||
`📦 Failed importing ${
|
||||
amountOfEvents - importedEventAmount
|
||||
} of ${amountOfEvents} events`
|
||||
);
|
||||
}
|
||||
|
||||
return logger.info(`📦 Managed to load all events`);
|
||||
};
|
||||
|
||||
eventNames.forEach(async (eventName: string, index: number) => {
|
||||
await importEvent(eventName).then(async () => {
|
||||
logger.debug(`📦 Imported the "${eventName}" event`);
|
||||
});
|
||||
|
||||
// If done importing
|
||||
if (index + 1 === amountOfEvents) {
|
||||
await doneImporting();
|
||||
}
|
||||
});
|
||||
|
||||
// for await (const eventName of eventNames) {
|
||||
// const event: IEvent = await import(`../../plugins/events/${eventName}`);
|
||||
// const eventExecutor = async (...args: Promise<void>[]) =>
|
||||
// event.execute(...args).catch(async (err) => {
|
||||
// logger.error(`${err}`);
|
||||
// });
|
||||
// if (!event.options?.type) return;
|
||||
|
||||
// switch (event.options.type) {
|
||||
// case "once":
|
||||
// client.once(eventName, eventExecutor);
|
||||
// break;
|
||||
|
||||
// case "on":
|
||||
// client.on(eventName, eventExecutor);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
|
|
@ -8,22 +8,19 @@ import listDir from "../../helpers/listDir";
|
|||
import schedule from "node-schedule";
|
||||
|
||||
export const start = async (client: Client) => {
|
||||
logger.info("Starting schedule manager...");
|
||||
logger.info("⏰ Started job management");
|
||||
|
||||
const jobNames = await listDir("jobs");
|
||||
if (!jobNames) return logger.info("No jobs found");
|
||||
if (!jobNames) return logger.warn("No available jobs found");
|
||||
|
||||
await Promise.all(
|
||||
jobNames.map(async (jobName) => {
|
||||
const job: IJob = await import(`../../jobs/${jobName}`);
|
||||
|
||||
schedule.scheduleJob(job.options.schedule, async () => {
|
||||
logger.info(`Executed job ${jobName}!`);
|
||||
logger.verbose(`⏰ Performed the job "${jobName}"`);
|
||||
await job.execute(client);
|
||||
});
|
||||
})
|
||||
).then(async () => {
|
||||
const list = schedule.scheduledJobs;
|
||||
logger.silly(list);
|
||||
});
|
||||
);
|
||||
};
|
||||
|
|
|
@ -58,7 +58,7 @@ const guildSchema = new Schema<IGuild>(
|
|||
},
|
||||
timeout: {
|
||||
type: Number,
|
||||
default: 5000,
|
||||
default: 5,
|
||||
},
|
||||
workRate: {
|
||||
type: Number,
|
||||
|
@ -66,7 +66,7 @@ const guildSchema = new Schema<IGuild>(
|
|||
},
|
||||
workTimeout: {
|
||||
type: Number,
|
||||
default: 900000,
|
||||
default: 900,
|
||||
},
|
||||
},
|
||||
embeds: {
|
||||
|
@ -118,7 +118,7 @@ const guildSchema = new Schema<IGuild>(
|
|||
},
|
||||
timeout: {
|
||||
type: Number,
|
||||
default: 5000,
|
||||
default: 5,
|
||||
},
|
||||
},
|
||||
welcome: {
|
||||
|
|
|
@ -43,7 +43,7 @@ export default {
|
|||
return logger?.silly(`Guild is null`);
|
||||
}
|
||||
|
||||
const guildDB = await fetchGuild(guild);
|
||||
const guildDB = await fetchGuild(guild.id);
|
||||
|
||||
await cooldown.command(interaction, guildDB?.credits?.workTimeout);
|
||||
|
||||
|
|
|
@ -11,10 +11,13 @@ export const options: IEventOptions = {
|
|||
export const execute = async (guild: Guild) => {
|
||||
const { client } = guild;
|
||||
|
||||
logger?.silly(`Added to guild: ${guild.name} (${guild.id})`);
|
||||
if (!client.user)
|
||||
throw new Error("Discord API client user is not available.");
|
||||
|
||||
await fetchGuild(guild);
|
||||
logger.silly(
|
||||
`${client.user.username} joined guild: ${guild.name} (${guild.id})`
|
||||
);
|
||||
|
||||
await fetchGuild(guild.id);
|
||||
await updatePresence(client);
|
||||
|
||||
logger.silly(`guildCreate: ${guild}`);
|
||||
};
|
||||
|
|
|
@ -16,7 +16,7 @@ export const execute = async (guild: Guild) => {
|
|||
|
||||
logger?.silly(`Deleted from guild: ${guild.name} (${guild.id})`);
|
||||
|
||||
await dropGuild(guild);
|
||||
await dropGuild(guild.id);
|
||||
await updatePresence(client);
|
||||
|
||||
logger.silly(`guildDelete: ${guild}`);
|
||||
|
|
|
@ -17,7 +17,7 @@ export default {
|
|||
const { id: guildId } = guild;
|
||||
const { id: userId } = author;
|
||||
|
||||
const guildData = await fetchGuild(guild);
|
||||
const guildData = await fetchGuild(guild.id);
|
||||
const userData = await fetchUser(author, guild);
|
||||
|
||||
if (content.length < guildData.credits.minimumLength) return;
|
||||
|
|
|
@ -14,7 +14,7 @@ export default {
|
|||
if (author.bot) return;
|
||||
if (channel?.type !== "GUILD_TEXT") return;
|
||||
|
||||
const guildData = await fetchGuild(guild);
|
||||
const guildData = await fetchGuild(guild.id);
|
||||
const userData = await fetchUser(author, guild);
|
||||
|
||||
if (content.length < guildData.credits.minimumLength) return;
|
||||
|
|
Loading…
Add table
Reference in a new issue