Skip to content

Commit

Permalink
refactor: move “cron jobs” to their own files
Browse files Browse the repository at this point in the history
  • Loading branch information
tippfehlr committed Sep 21, 2024
1 parent 9d9a327 commit 46ed11f
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 119 deletions.
123 changes: 4 additions & 119 deletions src/modules/bot.ready.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import { client } from './bot';
import CommandHandler from './commandHandler';
import config from './config';
import { configureInfluxDB } from './metrics';
import { getUserCount, getRolesCount, db } from './db';
import { getUserCount, getRolesCount } from './db';
import { i18n, log } from './messages';
import { cron } from './cron';

import activityStats from './commands/activityStats';
import addActivityRole from './commands/addActivityRole';
import checkRoles, { checkRolesStandalone } from './commands/checkRoles';
import checkRoles from './commands/checkRoles';
import deleteActivityRole from './commands/deleteActivityRole';
import deleteStatusRole from './commands/deleteStatusRole';
import _export from './commands/export';
Expand Down Expand Up @@ -102,122 +103,6 @@ export function initClientReady() {
log.info(
`The bot is currently in ${client.guilds.cache.size} guilds with ${await getUserCount()} users and manages ${await getRolesCount()} roles`,
);

// checkroles:
// execute every 30 minutes
// check if the last check was more than 20 hours ago
checkGuilds();
setInterval(checkGuilds, 30 * 60 * 1000);

// membercount:
// execute every 24 hours
// check if the last update was more than 7 days ago
updateMemberCount();
setInterval(updateMemberCount, 24 * 60 * 60 * 1000);

// scheduled role actions:
// execute every 6 hours
// check for roles to add or remove in scheduledRoleActions
executeScheduledRoleActions();
setInterval(executeScheduledRoleActions, 6 * 60 * 60 * 1000);
cron();
});
}

const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

async function checkGuilds() {
const guildsToCheck = await db
.selectFrom('guilds')
.select('guildID')
.where('lastCheckRoles', '<', new Date(Date.now() - 20 * 60 * 60 * 1000))
.orderBy('lastCheckRoles asc')
.execute();
await client.guilds.fetch();
for (const { guildID } of guildsToCheck) {
await delay(30 * 1000);
const guild = client.guilds.cache.get(guildID);
if (guild) await checkRolesStandalone({ guild });
}
}

async function updateMemberCount() {
const guildsToUpdate = await db
.selectFrom('guilds')
.select(['guildID'])
.where(eb =>
eb.or([
eb('approxMemberCountLastUpdate', '<', new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)),
eb('approxMemberCountLastUpdate', 'is', null),
eb('approxMemberCount', 'is', null),
]),
)
.execute();
await client.guilds.fetch();
for (const dbGuild of guildsToUpdate) {
const guild = client.guilds.cache.get(dbGuild.guildID);
if (!guild) continue;
await guild.members.fetch();
await db
.updateTable('guilds')
.set({
approxMemberCount: guild.memberCount,
approxMemberCountLastUpdate: new Date(),
})
.where('guildID', '=', dbGuild.guildID)
.execute();
}
}

async function executeScheduledRoleActions() {
// ensure that only executed schedules get deleted.
// otherwise, this could start at 23:59 and end after midnight,
// deleting the schedules for the new day accidently.
const date = new Date();
const actionsDue = await db
.deleteFrom('scheduledRoleActions')
.where('scheduledDate', '<=', date)
.returning(['action', 'roleID', 'guildID', 'userID'])
.execute();
let stats = { added: 0, removed: 0 };

for (const action of actionsDue) {
if (action.action === 'add') {
const guild = await client.guilds.fetch(action.guildID);
if (!guild) continue;
const user = await guild.members.fetch(action.userID);
if (!user) continue;

try {
user.roles.add(action.roleID);
stats.added += 1;
} catch (error) {
log.error(
`scheduledRoleActions: should assign role ${action.roleID} to user ` +
`${user.nickname} (${user.id}) on guild ${guild.name} (${guild.id}) ` +
'but it (probably) doesn’t exist.',
error,
);
}
} else if (action.action === 'remove') {
const guild = await client.guilds.fetch(action.guildID);
if (1 || 2) {
}
if (!guild) continue;
const user = await guild.members.fetch(action.userID);
if (!user) continue;

try {
user.roles.remove(action.roleID);
stats.removed += 1;
} catch (error) {
log.error(
`scheduledRoleActions: should remove role ${action.roleID} to user ` +
`${user.nickname} (${user.id}) on guild ${guild.name} (${guild.id}) ` +
'but it (probably) doesn’t exist.',
error,
);
}
}
}
log.info(`scheduledRoleActions: added ${stats.added} and removed ${stats.removed} roles.`);
}
23 changes: 23 additions & 0 deletions src/modules/cron.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { checkGuilds } from './cron/checkRoles';
import { executeScheduledRoleActions } from './cron/scheduledRoleActions';
import { updateMemberCount } from './cron/updateMemberCount';

export function cron() {
// checkroles:
// execute every 30 minutes
// check if the last check was more than 20 hours ago
checkGuilds();
setInterval(checkGuilds, 30 * 60 * 1000);

// membercount:
// execute every 24 hours
// check if the last update was more than 7 days ago
updateMemberCount();
setInterval(updateMemberCount, 24 * 60 * 60 * 1000);

// scheduled role actions:
// execute every 6 hours
// check for roles to add or remove in scheduledRoleActions
executeScheduledRoleActions();
setInterval(executeScheduledRoleActions, 6 * 60 * 60 * 1000);
}
20 changes: 20 additions & 0 deletions src/modules/cron/checkRoles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { client } from '../bot';
import { checkRolesStandalone } from '../commands/checkRoles';
import { db } from '../db';

const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

export async function checkGuilds() {
const guildsToCheck = await db
.selectFrom('guilds')
.select('guildID')
.where('lastCheckRoles', '<', new Date(Date.now() - 20 * 60 * 60 * 1000))
.orderBy('lastCheckRoles asc')
.execute();
await client.guilds.fetch();
for (const { guildID } of guildsToCheck) {
await delay(30 * 1000);
const guild = client.guilds.cache.get(guildID);
if (guild) await checkRolesStandalone({ guild });
}
}
57 changes: 57 additions & 0 deletions src/modules/cron/scheduledRoleActions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { client } from '../bot';
import { db } from '../db';
import { log } from '../messages';

export async function executeScheduledRoleActions() {
// ensure that only executed schedules get deleted.
// otherwise, this could start at 23:59 and end after midnight,
// deleting the schedules for the new day accidently.
const date = new Date();
const actionsDue = await db
.deleteFrom('scheduledRoleActions')
.where('scheduledDate', '<=', date)
.returning(['action', 'roleID', 'guildID', 'userID'])
.execute();
let stats = { added: 0, removed: 0 };

for (const action of actionsDue) {
if (action.action === 'add') {
const guild = await client.guilds.fetch(action.guildID);
if (!guild) continue;
const user = await guild.members.fetch(action.userID);
if (!user) continue;

try {
user.roles.add(action.roleID);
stats.added += 1;
} catch (error) {
log.error(
`scheduledRoleActions: should assign role ${action.roleID} to user ` +
`${user.nickname} (${user.id}) on guild ${guild.name} (${guild.id}) ` +
'but it (probably) doesn’t exist.',
error,
);
}
} else if (action.action === 'remove') {
const guild = await client.guilds.fetch(action.guildID);
if (1 || 2) {
}
if (!guild) continue;
const user = await guild.members.fetch(action.userID);
if (!user) continue;

try {
user.roles.remove(action.roleID);
stats.removed += 1;
} catch (error) {
log.error(
`scheduledRoleActions: should remove role ${action.roleID} to user ` +
`${user.nickname} (${user.id}) on guild ${guild.name} (${guild.id}) ` +
'but it (probably) doesn’t exist.',
error,
);
}
}
}
log.info(`scheduledRoleActions: added ${stats.added} and removed ${stats.removed} roles.`);
}
30 changes: 30 additions & 0 deletions src/modules/cron/updateMemberCount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { client } from '../bot';
import { db } from '../db';

export async function updateMemberCount() {
const guildsToUpdate = await db
.selectFrom('guilds')
.select(['guildID'])
.where(eb =>
eb.or([
eb('approxMemberCountLastUpdate', '<', new Date(Date.now() - 7 * 24 * 60 * 60 * 1000)),
eb('approxMemberCountLastUpdate', 'is', null),
eb('approxMemberCount', 'is', null),
]),
)
.execute();
await client.guilds.fetch();
for (const dbGuild of guildsToUpdate) {
const guild = client.guilds.cache.get(dbGuild.guildID);
if (!guild) continue;
await guild.members.fetch();
await db
.updateTable('guilds')
.set({
approxMemberCount: guild.memberCount,
approxMemberCountLastUpdate: new Date(),
})
.where('guildID', '=', dbGuild.guildID)
.execute();
}
}

0 comments on commit 46ed11f

Please sign in to comment.