Random messages, logging refactor

This commit is contained in:
James Shiffer 2023-10-08 19:10:47 -07:00
parent 81b75d3546
commit 2809c29c9a
4 changed files with 61 additions and 36 deletions

View File

@ -13,7 +13,16 @@ import {
TextChannel,
User
} from 'discord.js';
import { db, openDb, reactionEmojis, recordReaction, sync } from './util';
import {
db,
logInfo,
logError,
openDb,
reactionEmojis,
recordReaction,
sync
} from './util';
const client = new Client({
intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions],
@ -21,11 +30,12 @@ const client = new Client({
});
client.once(Events.ClientReady, async () => {
console.log('[bot] Ready.');
logInfo('[bot] Ready.');
for (let i = 0; i < reactionEmojis.length; ++i)
console.log(`[bot] config: reaction_${i + 1} = ${reactionEmojis[i]}`);
logInfo(`[bot] config: reaction_${i + 1} = ${reactionEmojis[i]}`);
});
async function onMessageReactionChanged(reaction: MessageReaction | PartialMessageReaction, user: User)
{
// When a reaction is received, check if the structure is partial
@ -34,7 +44,7 @@ async function onMessageReactionChanged(reaction: MessageReaction | PartialMessa
try {
await reaction.fetch();
} catch (error) {
console.error('[bot] Something went wrong when fetching the reaction:', error);
logError('[bot] Something went wrong when fetching the reaction:', error);
// Return as `reaction.message.author` may be undefined/null
return;
}
@ -44,14 +54,14 @@ async function onMessageReactionChanged(reaction: MessageReaction | PartialMessa
try {
await reaction.message.fetch();
} catch (error) {
console.error('[bot] Something went wrong when fetching the message:', error);
logError('[bot] Something went wrong when fetching the message:', error);
// Return as `reaction.message.author` may be undefined/null
return;
}
}
// Now the message has been cached and is fully available
console.log(`[bot] ${reaction.message.author.id}'s message reaction count changed: ${reaction.emoji.name}x${reaction.count}`);
logInfo(`[bot] ${reaction.message.author.id}'s message reaction count changed: ${reaction.emoji.name}x${reaction.count}`);
await recordReaction(<MessageReaction> reaction);
}
@ -70,13 +80,13 @@ async function scheduleRandomMessage(firstTime = false)
const channel = <TextChannel> await client.channels.fetch(process.env.MOTD_CHANNEL);
const randomMessage = await fetchMotd();
await channel.send(randomMessage);
console.log(`[bot] Sent MOTD: ${randomMessage}`);
logInfo(`[bot] Sent MOTD: ${randomMessage}`);
}
// wait between 2-8 hours
const timeoutMins = Math.random() * 360 + 120;
const scheduledTime = new Date();
scheduledTime.setMinutes(scheduledTime.getMinutes() + timeoutMins);
console.log(`[bot] Next MOTD: ${scheduledTime}`);
logInfo(`[bot] Next MOTD: ${scheduledTime}`);
setTimeout(scheduleRandomMessage, timeoutMins * 60 * 1000);
}
@ -84,12 +94,12 @@ client.on(Events.MessageReactionAdd, onMessageReactionChanged);
client.on(Events.MessageReactionRemove, onMessageReactionChanged);
async function startup() {
console.log("[db] Opening...");
logInfo("[db] Opening...");
await openDb();
console.log("[db] Migrating...");
logInfo("[db] Migrating...");
await db.migrate();
console.log("[db] Ready.");
console.log("[bot] Logging in...");
logInfo("[db] Ready.");
logInfo("[bot] Logging in...");
await client.login(process.env.TOKEN);
await sync(client.guilds);
if (process.env.ENABLE_MOTD) {

View File

@ -5,7 +5,7 @@
*/
import { Client, Events, GatewayIntentBits, IntentsBitField, Partials } from 'discord.js';
import { db, openDb, reactionEmojis, sync } from './util';
import { db, logInfo, openDb, reactionEmojis, sync } from './util';
const client = new Client({
intents: [GatewayIntentBits.MessageContent, IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages],
@ -13,18 +13,18 @@ const client = new Client({
});
client.once(Events.ClientReady, async () => {
console.log('[bot] Ready.');
logInfo('[bot] Ready.');
for (let i = 0; i < reactionEmojis.length; ++i)
console.log(`[bot] config: reaction_${i + 1} = ${reactionEmojis[i]}`);
logInfo(`[bot] config: reaction_${i + 1} = ${reactionEmojis[i]}`);
});
async function startup() {
console.log("[db] Opening...");
logInfo("[db] Opening...");
await openDb();
console.log("[db] Migrating...");
logInfo("[db] Migrating...");
await db.migrate();
console.log("[db] Ready.");
console.log("[bot] Logging in...");
logInfo("[db] Ready.");
logInfo("[bot] Logging in...");
await client.login(process.env.TOKEN);
await sync(client.guilds);
process.exit(0);

View File

@ -15,6 +15,19 @@ import { ScoreboardMessageRow } from '../models';
const reactionEmojis: string[] = process.env.REACTIONS.split(',');
let db: Database = null;
function logInfo(...data) {
console.log(`[${new Date()}] ${data.join(' ')}`);
}
function logWarn(...data) {
console.warn(`[${new Date()}] ${data.join(' ')}`);
}
function logError(...data) {
console.error(`[${new Date()}] ${data.join(' ')}`);
}
async function openDb() {
db = await open({
filename: 'db.sqlite',
@ -38,14 +51,14 @@ function userAvatarPath(user: User)
async function downloadUserAvatar(user: User)
{
console.log(`[bot] Downloading ${user.id}'s avatar...`);
logInfo(`[bot] Downloading ${user.id}'s avatar...`);
const file = createWriteStream(userAvatarPath(user));
return new Promise<void>(resolve => {
httpGet(user.displayAvatarURL(), res => {
res.pipe(file);
file.on('finish', () => {
file.close();
console.log(`[bot] Finished downloading ${user.id}'s avatar.`);
logInfo(`[bot] Finished downloading ${user.id}'s avatar.`);
resolve();
});
});
@ -72,7 +85,7 @@ async function refreshUserReactionTotalCount(user: User, emoji_idx: number)
if (!existsSync(userAvatarPath(user))) {
await downloadUserAvatar(user);
}
console.log(`[bot] Refreshed ${user.id}'s ${reactionEmojis[emoji_idx - 1]} count.`);
logInfo(`[bot] Refreshed ${user.id}'s ${reactionEmojis[emoji_idx - 1]} count.`);
}
async function recordReaction(reaction: MessageReaction)
@ -95,9 +108,9 @@ async function recordReaction(reaction: MessageReaction)
reaction.message.id
);
await refreshUserReactionTotalCount(reaction.message.author, emojiIdx);
console.log(`[bot] Recorded ${reaction.emoji.name}x${reaction.count} in database.`);
logInfo(`[bot] Recorded ${reaction.emoji.name}x${reaction.count} in database.`);
} catch (error) {
console.error('[bot] Something went wrong when updating the database:', error);
logError('[bot] Something went wrong when updating the database:', error);
return;
}
}
@ -105,14 +118,14 @@ async function recordReaction(reaction: MessageReaction)
async function sync(guilds: GuildManager) {
const guild = await guilds.fetch(process.env.GUILD);
if (!guild) {
console.error(`[bot] FATAL: guild ${guild.id} not found!`);
logError(`[bot] FATAL: guild ${guild.id} not found!`);
return 1;
}
console.log(`[bot] Entered guild ${guild.id}`);
logInfo(`[bot] Entered guild ${guild.id}`);
const channels = await guild.channels.fetch();
const textChannels = <Collection<string, GuildTextBasedChannel>> channels.filter(c => c && 'messages' in c && c.isTextBased);
for (const [id, textChannel] of textChannels) {
console.log(`[bot] Found text channel ${id}`);
logInfo(`[bot] Found text channel ${id}`);
const oldestMsg = await db.get<ScoreboardMessageRow>(
'SELECT * FROM messages WHERE guild = ? AND channel = ? ORDER BY id ASC LIMIT 1',
guild.id,
@ -136,15 +149,16 @@ async function sync(guilds: GuildManager) {
newMessagesAfter = await textChannel.messages.fetch({ after, limit: 100 });
messagesCount += newMessagesAfter.size;
console.log(`[bot] [${id}] Fetched ${messagesCount} messages (+${newMessagesBefore.size} older, ${newMessagesAfter.size} newer)`);
logInfo(`[bot] [${id}] Fetched ${messagesCount} messages (+${newMessagesBefore.size} older, ${newMessagesAfter.size} newer)`);
const reactions = newMessagesBefore.flatMap<MessageReaction>(m => m.reactions.cache)
const reactions = newMessagesBefore
.flatMap<MessageReaction>(m => m.reactions.cache)
.concat(newMessagesAfter.flatMap<MessageReaction>(m => m.reactions.cache));
for (const [_, reaction] of reactions) {
await recordReaction(reaction);
}
reactionsCount += reactions.size;
console.log(`[bot] [${id}] Recorded ${reactionsCount} reactions (+${reactions.size}).`);
logInfo(`[bot] [${id}] Recorded ${reactionsCount} reactions (+${reactions.size}).`);
if (newMessagesBefore.size > 0) {
before = newMessagesBefore.last().id;
@ -153,11 +167,11 @@ async function sync(guilds: GuildManager) {
after = newMessagesAfter.first().id;
}
} while (newMessagesBefore.size === 100 || newMessagesAfter.size === 100);
console.log(`[bot] [${id}] Done.`);
logInfo(`[bot] [${id}] Done.`);
} catch (err) {
console.warn(`[bot] [${id}] Failed to fetch messages and reactions: ${err}`);
logWarn(`[bot] [${id}] Failed to fetch messages and reactions: ${err}`);
}
}
}
export { db, clearDb, openDb, reactionEmojis, recordReaction, sync };
export { db, clearDb, logError, logInfo, logWarn, openDb, reactionEmojis, recordReaction, sync };

View File

@ -8,6 +8,7 @@ import { Database, open } from 'sqlite';
import express = require('express');
import 'dotenv/config';
import { ScoreboardMessageRow, ScoreboardUserRow } from './models';
import { logInfo } from './discord/util';
const app = express();
app.use(express.static('public'));
@ -36,8 +37,8 @@ app.get('/', async (req, res) => {
});
app.listen(port, async () => {
console.log('[web] Opening database...');
logInfo('[web] Opening database...');
db = await openDb();
console.log('[web] Database ready.');
console.log(`[web] Listening on port ${port}`);
logInfo('[web] Database ready.');
logInfo(`[web] Listening on port ${port}`);
});