Skip to content

Commit 8f1ba63

Browse files
committed
write logs to log channel
1 parent 0590efa commit 8f1ba63

File tree

4 files changed

+82
-1
lines changed

4 files changed

+82
-1
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+
);

0 commit comments

Comments
 (0)