Skip to content

Commit 6a2a8e6

Browse files
authored
Merge pull request #185 from tjjfvi/logs
Write bot logs to a (mod-only) #log channel
2 parents 0590efa + de3cac0 commit 6a2a8e6

File tree

12 files changed

+118
-7
lines changed

12 files changed

+118
-7
lines changed

.env.example

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,5 @@ GENERAL_HELP_CHANNEL=
2121
TIME_BEFORE_HELPER_PING=
2222

2323
SUGGESTIONS_CHANNEL=
24+
25+
LOG_CHANNEL=

src/env.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,5 @@ export const timeBeforeHelperPing = parseInt(
3434
);
3535

3636
export const suggestionsChannelId = process.env.SUGGESTIONS_CHANNEL!;
37+
38+
export const logChannelId = process.env.LOG_CHANNEL!;

src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { token, botAdmins } from './env';
22
import CookiecordClient from 'cookiecord';
33
import { Intents } from 'discord.js';
44
import { getDB } from './db';
5+
import { hookLog } from './log';
56

67
import { AutoroleModule } from './modules/autorole';
78
import { EtcModule } from './modules/etc';
@@ -51,7 +52,10 @@ for (const mod of [
5152
getDB(); // prepare the db for later
5253

5354
client.login(token);
54-
client.on('ready', () => console.log(`Logged in as ${client.user?.tag}`));
55+
client.on('ready', () => {
56+
console.log(`Logged in as ${client.user?.tag}`);
57+
hookLog(client);
58+
});
5559

5660
process.on('unhandledRejection', e => {
5761
console.error('Unhandled rejection', e);

src/log.ts

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import CookiecordClient from 'cookiecord';
2+
import { Channel, GuildMember, TextChannel, User } from 'discord.js';
3+
import { inspect } from 'util';
4+
import { logChannelId } from './env';
5+
6+
const logDebounceTime = 5000;
7+
const logMaxLength = 2000;
8+
9+
export async function hookLog(client: CookiecordClient) {
10+
const guild = client.guilds.cache.get(
11+
(await client.guilds.fetch()).first()!.id,
12+
)!;
13+
const channel = (await guild.channels.fetch(logChannelId)) as TextChannel;
14+
let curLogText = '';
15+
let timeout: NodeJS.Timeout | null = null;
16+
const origLog = console.log;
17+
console.log = (...args) => {
18+
origLog(...args);
19+
postLog(args);
20+
};
21+
const origError = console.error;
22+
console.error = (...args) => {
23+
origError(...args);
24+
postLog(['[ERROR]', ...args]);
25+
};
26+
console.log('Writing logs to', channel);
27+
function argToString(arg: unknown) {
28+
if (typeof arg === 'string') return arg;
29+
return inspect(arg);
30+
}
31+
function postLog(args: unknown[]) {
32+
curLogText += `[${new Date().toISOString()}] ${args
33+
.map(argToString)
34+
.join(' ')}\n`;
35+
if (timeout) clearTimeout(timeout);
36+
while (curLogText.length > logMaxLength) {
37+
const initial =
38+
curLogText.match(/^[^]{0,2000}\n/g)?.[0] ??
39+
curLogText.slice(0, 2000);
40+
curLogText = curLogText.slice(initial.length);
41+
postCodeblock(initial);
42+
}
43+
if (curLogText.trim().length)
44+
timeout = setTimeout(() => {
45+
postCodeblock(curLogText);
46+
curLogText = '';
47+
}, logDebounceTime);
48+
}
49+
async function postCodeblock(content: string) {
50+
channel.send(`\`\`\`ts\n${content}\n\`\`\``);
51+
}
52+
}
53+
54+
function defineCustomUtilInspect<T>(
55+
Cls: { new (...args: any): T; prototype: T },
56+
cb: (value: T) => string,
57+
) {
58+
// @ts-ignore
59+
Cls.prototype[inspect.custom] = function () {
60+
return cb(this);
61+
};
62+
}
63+
64+
const inspectUser = (user: User) =>
65+
`@${user.username}#${user.discriminator}/${user.id}`;
66+
defineCustomUtilInspect(User, inspectUser);
67+
defineCustomUtilInspect(GuildMember, member => inspectUser(member.user));
68+
69+
defineCustomUtilInspect(Channel, channel =>
70+
'name' in channel
71+
? `#${(channel as any).name}/${(channel as Channel).id}`
72+
: `#${channel.id}`,
73+
);

src/modules/autorole.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export class AutoroleModule extends Module {
2424
user,
2525
});
2626
await member.roles.add(ar.roleID);
27+
console.log('Gave role', ar.roleID, 'to', member);
2728
if (!reaction.users.cache.has(this.client.user!.id)) {
2829
await msg.react(reaction.emoji);
2930
}
@@ -47,6 +48,7 @@ export class AutoroleModule extends Module {
4748
user,
4849
});
4950
await member.roles.remove(ar.roleID);
51+
console.log('Removed role', ar.roleID, 'from', member);
5052
}
5153
}
5254
}

src/modules/etc.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ export class EtcModule extends Module {
136136
.catch(() => false);
137137
await confirmationMessage.delete();
138138
if (!proceed) return;
139-
await msg.react('☠️'),
140-
console.log(`
139+
await msg.react('☠️');
140+
process.stdout.write(`
141141
,--.
142142
{ }
143143
K, }

src/modules/handbook.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export class HandbookModule extends Module {
3737
return await sendWithMessageOwnership(msg, {
3838
embeds: [this.HANDBOOK_EMBED],
3939
});
40+
console.log('Searching algolia for', [text]);
4041
const data = await algolia.search<AlgoliaResult>([
4142
{
4243
indexName: ALGOLIA_INDEX_NAME,
@@ -47,6 +48,7 @@ export class HandbookModule extends Module {
4748
},
4849
},
4950
]);
51+
console.log('Algolia response:', data);
5052
const hit = data.results[0].hits[0];
5153
if (!hit)
5254
return await sendWithMessageOwnership(

src/modules/helpthread.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,12 @@ export class HelpThreadModule extends Module {
9090
async onNewQuestion(msg: Message) {
9191
if (!isHelpChannel(msg.channel)) return;
9292
if (msg.author.id === this.client.user!.id) return;
93+
console.log(
94+
'Received new question from',
95+
msg.author,
96+
'in',
97+
msg.channel,
98+
);
9399
this.updateHelpInfo(msg.channel);
94100
let thread = await msg.startThread({
95101
name: `[Open] Help ${msg.member?.nickname ?? msg.author.username}`,
@@ -100,6 +106,7 @@ export class HelpThreadModule extends Module {
100106
threadId: thread.id,
101107
ownerId: msg.author.id,
102108
}).save();
109+
console.log(`Created a new help thread for`, msg.author);
103110
}
104111

105112
// Used to differentiate automatic archive from bot archive
@@ -113,6 +120,7 @@ export class HelpThreadModule extends Module {
113120
this.manuallyArchivedThreads.delete(thread.id)
114121
)
115122
return;
123+
console.log(`Help thread expired:`, thread);
116124
await thread.send({ embeds: [threadExpireEmbed] });
117125
this.manuallyArchivedThreads.add(thread.id);
118126
await thread.setName(`[Closed] ${thread.name.replace(/\[.+?] /, '')}`);
@@ -137,6 +145,7 @@ export class HelpThreadModule extends Module {
137145
threadData.ownerId === msg.author.id ||
138146
msg.member?.permissions.has('MANAGE_MESSAGES')
139147
) {
148+
console.log(`Closing help thread:`, thread);
140149
await msg.react('✅');
141150
this.manuallyArchivedThreads.add(thread.id);
142151
await thread.setName(

src/modules/mod.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export class ModModule extends Module {
3131
await msg.channel.send(
3232
`${msg.author} We don't do job posts here; see <#${rulesChannelId}>`,
3333
);
34+
console.log('Deleted job post message from', msg.author);
3435
}
3536

3637
@listener({ event: 'messageCreate' })
@@ -53,6 +54,13 @@ export class ModModule extends Module {
5354
.then(member => void member.kick('Spam')),
5455
...recentMessageInfo.messages.map(msg => void msg.delete()),
5556
]);
57+
console.log(
58+
'Kicked',
59+
msg.author,
60+
'for spam and deleted',
61+
recentMessageInfo.messages.length,
62+
'identical messages',
63+
);
5664
}
5765
} else {
5866
recentMessages.set(messageIdentifier, {

src/modules/rep.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ export class RepModule extends Module {
7474
to: targetRU,
7575
}).save();
7676

77+
console.log('Gave one rep from', msg.author, 'to', user);
78+
7779
currentSent++;
7880
}
7981

@@ -123,6 +125,7 @@ export class RepModule extends Module {
123125
(await senderRU.sent()) + 1
124126
}/${this.MAX_REP} sent)`,
125127
);
128+
console.log('Gave one rep from', msg.author, 'to', targetMember.user);
126129
}
127130

128131
@command({

0 commit comments

Comments
 (0)