Random messages, logging refactor
This commit is contained in:
		
							parent
							
								
									81b75d3546
								
							
						
					
					
						commit
						2809c29c9a
					
				| @ -13,7 +13,16 @@ import { | |||||||
|     TextChannel, |     TextChannel, | ||||||
|     User |     User | ||||||
| } from 'discord.js'; | } 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({ | const client = new Client({ | ||||||
|     intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions], |     intents: [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions], | ||||||
| @ -21,11 +30,12 @@ const client = new Client({ | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| client.once(Events.ClientReady, async () => { | client.once(Events.ClientReady, async () => { | ||||||
|     console.log('[bot] Ready.'); |     logInfo('[bot] Ready.'); | ||||||
|     for (let i = 0; i < reactionEmojis.length; ++i) |     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) | async function onMessageReactionChanged(reaction: MessageReaction | PartialMessageReaction, user: User) | ||||||
| { | { | ||||||
|     // When a reaction is received, check if the structure is partial
 |     // When a reaction is received, check if the structure is partial
 | ||||||
| @ -34,7 +44,7 @@ async function onMessageReactionChanged(reaction: MessageReaction | PartialMessa | |||||||
|         try { |         try { | ||||||
|             await reaction.fetch(); |             await reaction.fetch(); | ||||||
|         } catch (error) { |         } 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 as `reaction.message.author` may be undefined/null
 | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| @ -44,14 +54,14 @@ async function onMessageReactionChanged(reaction: MessageReaction | PartialMessa | |||||||
|         try { |         try { | ||||||
|             await reaction.message.fetch(); |             await reaction.message.fetch(); | ||||||
|         } catch (error) { |         } 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 as `reaction.message.author` may be undefined/null
 | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Now the message has been cached and is fully available
 |     // 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); |     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 channel = <TextChannel> await client.channels.fetch(process.env.MOTD_CHANNEL); | ||||||
|         const randomMessage = await fetchMotd(); |         const randomMessage = await fetchMotd(); | ||||||
|         await channel.send(randomMessage); |         await channel.send(randomMessage); | ||||||
|         console.log(`[bot] Sent MOTD: ${randomMessage}`); |         logInfo(`[bot] Sent MOTD: ${randomMessage}`); | ||||||
|     } |     } | ||||||
|     // wait between 2-8 hours
 |     // wait between 2-8 hours
 | ||||||
|     const timeoutMins = Math.random() * 360 + 120; |     const timeoutMins = Math.random() * 360 + 120; | ||||||
|     const scheduledTime = new Date(); |     const scheduledTime = new Date(); | ||||||
|     scheduledTime.setMinutes(scheduledTime.getMinutes() + timeoutMins); |     scheduledTime.setMinutes(scheduledTime.getMinutes() + timeoutMins); | ||||||
|     console.log(`[bot] Next MOTD: ${scheduledTime}`); |     logInfo(`[bot] Next MOTD: ${scheduledTime}`); | ||||||
|     setTimeout(scheduleRandomMessage, timeoutMins * 60 * 1000); |     setTimeout(scheduleRandomMessage, timeoutMins * 60 * 1000); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -84,12 +94,12 @@ client.on(Events.MessageReactionAdd, onMessageReactionChanged); | |||||||
| client.on(Events.MessageReactionRemove, onMessageReactionChanged); | client.on(Events.MessageReactionRemove, onMessageReactionChanged); | ||||||
| 
 | 
 | ||||||
| async function startup() { | async function startup() { | ||||||
|     console.log("[db] Opening..."); |     logInfo("[db] Opening..."); | ||||||
|     await openDb(); |     await openDb(); | ||||||
|     console.log("[db] Migrating..."); |     logInfo("[db] Migrating..."); | ||||||
|     await db.migrate(); |     await db.migrate(); | ||||||
|     console.log("[db] Ready."); |     logInfo("[db] Ready."); | ||||||
|     console.log("[bot] Logging in..."); |     logInfo("[bot] Logging in..."); | ||||||
|     await client.login(process.env.TOKEN); |     await client.login(process.env.TOKEN); | ||||||
|     await sync(client.guilds); |     await sync(client.guilds); | ||||||
|     if (process.env.ENABLE_MOTD) { |     if (process.env.ENABLE_MOTD) { | ||||||
|  | |||||||
| @ -5,7 +5,7 @@ | |||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| import { Client, Events, GatewayIntentBits, IntentsBitField, Partials } from 'discord.js'; | 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({ | const client = new Client({ | ||||||
|     intents: [GatewayIntentBits.MessageContent, IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages], |     intents: [GatewayIntentBits.MessageContent, IntentsBitField.Flags.Guilds, IntentsBitField.Flags.GuildMessages], | ||||||
| @ -13,18 +13,18 @@ const client = new Client({ | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| client.once(Events.ClientReady, async () => { | client.once(Events.ClientReady, async () => { | ||||||
|     console.log('[bot] Ready.'); |     logInfo('[bot] Ready.'); | ||||||
|     for (let i = 0; i < reactionEmojis.length; ++i) |     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() { | async function startup() { | ||||||
|     console.log("[db] Opening..."); |     logInfo("[db] Opening..."); | ||||||
|     await openDb(); |     await openDb(); | ||||||
|     console.log("[db] Migrating..."); |     logInfo("[db] Migrating..."); | ||||||
|     await db.migrate(); |     await db.migrate(); | ||||||
|     console.log("[db] Ready."); |     logInfo("[db] Ready."); | ||||||
|     console.log("[bot] Logging in..."); |     logInfo("[bot] Logging in..."); | ||||||
|     await client.login(process.env.TOKEN); |     await client.login(process.env.TOKEN); | ||||||
|     await sync(client.guilds); |     await sync(client.guilds); | ||||||
|     process.exit(0); |     process.exit(0); | ||||||
|  | |||||||
| @ -15,6 +15,19 @@ import { ScoreboardMessageRow } from '../models'; | |||||||
| const reactionEmojis: string[] = process.env.REACTIONS.split(','); | const reactionEmojis: string[] = process.env.REACTIONS.split(','); | ||||||
| let db: Database = null; | 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() { | async function openDb() { | ||||||
|     db = await open({ |     db = await open({ | ||||||
|         filename: 'db.sqlite', |         filename: 'db.sqlite', | ||||||
| @ -38,14 +51,14 @@ function userAvatarPath(user: User) | |||||||
| 
 | 
 | ||||||
| async function downloadUserAvatar(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)); |     const file = createWriteStream(userAvatarPath(user)); | ||||||
|     return new Promise<void>(resolve => { |     return new Promise<void>(resolve => { | ||||||
|         httpGet(user.displayAvatarURL(), res => { |         httpGet(user.displayAvatarURL(), res => { | ||||||
|             res.pipe(file); |             res.pipe(file); | ||||||
|             file.on('finish', () => { |             file.on('finish', () => { | ||||||
|                 file.close(); |                 file.close(); | ||||||
|                 console.log(`[bot] Finished downloading ${user.id}'s avatar.`); |                 logInfo(`[bot] Finished downloading ${user.id}'s avatar.`); | ||||||
|                 resolve(); |                 resolve(); | ||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| @ -72,7 +85,7 @@ async function refreshUserReactionTotalCount(user: User, emoji_idx: number) | |||||||
|     if (!existsSync(userAvatarPath(user))) { |     if (!existsSync(userAvatarPath(user))) { | ||||||
|         await downloadUserAvatar(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) | async function recordReaction(reaction: MessageReaction) | ||||||
| @ -95,9 +108,9 @@ async function recordReaction(reaction: MessageReaction) | |||||||
|             reaction.message.id |             reaction.message.id | ||||||
|         ); |         ); | ||||||
|         await refreshUserReactionTotalCount(reaction.message.author, emojiIdx); |         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) { |     } catch (error) { | ||||||
|         console.error('[bot] Something went wrong when updating the database:', error); |         logError('[bot] Something went wrong when updating the database:', error); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -105,14 +118,14 @@ async function recordReaction(reaction: MessageReaction) | |||||||
| async function sync(guilds: GuildManager) { | async function sync(guilds: GuildManager) { | ||||||
|     const guild = await guilds.fetch(process.env.GUILD); |     const guild = await guilds.fetch(process.env.GUILD); | ||||||
|     if (!guild) { |     if (!guild) { | ||||||
|         console.error(`[bot] FATAL: guild ${guild.id} not found!`); |         logError(`[bot] FATAL: guild ${guild.id} not found!`); | ||||||
|         return 1; |         return 1; | ||||||
|     } |     } | ||||||
|     console.log(`[bot] Entered guild ${guild.id}`); |     logInfo(`[bot] Entered guild ${guild.id}`); | ||||||
|     const channels = await guild.channels.fetch(); |     const channels = await guild.channels.fetch(); | ||||||
|     const textChannels = <Collection<string, GuildTextBasedChannel>> channels.filter(c => c && 'messages' in c && c.isTextBased); |     const textChannels = <Collection<string, GuildTextBasedChannel>> channels.filter(c => c && 'messages' in c && c.isTextBased); | ||||||
|     for (const [id, textChannel] of textChannels) { |     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>( |         const oldestMsg = await db.get<ScoreboardMessageRow>( | ||||||
|             'SELECT * FROM messages WHERE guild = ? AND channel = ? ORDER BY id ASC LIMIT 1', |             'SELECT * FROM messages WHERE guild = ? AND channel = ? ORDER BY id ASC LIMIT 1', | ||||||
|             guild.id, |             guild.id, | ||||||
| @ -136,15 +149,16 @@ async function sync(guilds: GuildManager) { | |||||||
| 
 | 
 | ||||||
|                 newMessagesAfter = await textChannel.messages.fetch({ after, limit: 100 }); |                 newMessagesAfter = await textChannel.messages.fetch({ after, limit: 100 }); | ||||||
|                 messagesCount += newMessagesAfter.size; |                 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)); |                     .concat(newMessagesAfter.flatMap<MessageReaction>(m => m.reactions.cache)); | ||||||
|                 for (const [_, reaction] of reactions) { |                 for (const [_, reaction] of reactions) { | ||||||
|                     await recordReaction(reaction); |                     await recordReaction(reaction); | ||||||
|                 } |                 } | ||||||
|                 reactionsCount += reactions.size; |                 reactionsCount += reactions.size; | ||||||
|                 console.log(`[bot] [${id}] Recorded ${reactionsCount} reactions (+${reactions.size}).`); |                 logInfo(`[bot] [${id}] Recorded ${reactionsCount} reactions (+${reactions.size}).`); | ||||||
| 
 | 
 | ||||||
|                 if (newMessagesBefore.size > 0) { |                 if (newMessagesBefore.size > 0) { | ||||||
|                     before = newMessagesBefore.last().id; |                     before = newMessagesBefore.last().id; | ||||||
| @ -153,11 +167,11 @@ async function sync(guilds: GuildManager) { | |||||||
|                     after = newMessagesAfter.first().id; |                     after = newMessagesAfter.first().id; | ||||||
|                 } |                 } | ||||||
|             } while (newMessagesBefore.size === 100 || newMessagesAfter.size === 100); |             } while (newMessagesBefore.size === 100 || newMessagesAfter.size === 100); | ||||||
|             console.log(`[bot] [${id}] Done.`); |             logInfo(`[bot] [${id}] Done.`); | ||||||
|         } catch (err) { |         } 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 }; | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ import { Database, open } from 'sqlite'; | |||||||
| import express = require('express'); | import express = require('express'); | ||||||
| import 'dotenv/config'; | import 'dotenv/config'; | ||||||
| import { ScoreboardMessageRow, ScoreboardUserRow } from './models'; | import { ScoreboardMessageRow, ScoreboardUserRow } from './models'; | ||||||
|  | import { logInfo } from './discord/util'; | ||||||
| 
 | 
 | ||||||
| const app = express(); | const app = express(); | ||||||
| app.use(express.static('public')); | app.use(express.static('public')); | ||||||
| @ -36,8 +37,8 @@ app.get('/', async (req, res) => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| app.listen(port, async () => { | app.listen(port, async () => { | ||||||
|     console.log('[web] Opening database...'); |     logInfo('[web] Opening database...'); | ||||||
|     db = await openDb(); |     db = await openDb(); | ||||||
|     console.log('[web] Database ready.'); |     logInfo('[web] Database ready.'); | ||||||
|     console.log(`[web] Listening on port ${port}`); |     logInfo(`[web] Listening on port ${port}`); | ||||||
| }); | }); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user