Skip to content

Commit 175abe2

Browse files
authored
Merge pull request #147 from GalvinPython/feat/guild-events
2 parents afbeedc + 67d0c18 commit 175abe2

File tree

9 files changed

+187
-2
lines changed

9 files changed

+187
-2
lines changed

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ TWITCH_CLIENT_SECRET='YOUR_TWITCH_CLIENT_SECRET'
1717
CONFIG_UPDATE_INTERVAL_YOUTUBE='10'
1818
CONFIG_UPDATE_INTERVAL_TWITCH='2'
1919
CONFIG_DISCORD_LOGS_CHANNEL='YOUR_DISCORD_LOGS_CHANNEL'
20+
CONFIG_DISCORD_WAIT_FOR_GUILD_CACHE_TIME='YOUR_TIME_IN_SECONDS'
2021

2122
# Postgres URLs
2223
POSTGRES_URL='postgresql://user:password@server:port/database'

src/config.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export interface Config {
44
updateIntervalYouTube: number;
55
updateIntervalTwitch: number;
66
databaseUrl: string | undefined;
7+
discordWaitForGuildCacheTime: number;
78
}
89

910
export const config: Config = {
@@ -16,6 +17,10 @@ export const config: Config = {
1617
databaseUrl: runningInDevMode
1718
? process.env?.POSTGRES_DEV_URL
1819
: process.env?.POSTGRES_URL,
20+
discordWaitForGuildCacheTime: process.env
21+
?.CONFIG_DISCORD_WAIT_FOR_GUILD_CACHE_TIME
22+
? parseInt(process.env?.CONFIG_DISCORD_WAIT_FOR_GUILD_CACHE_TIME) * 1000
23+
: 10_000,
1924
};
2025

2126
interface Env {

src/db/discord.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { db } from "./db";
66
import {
77
dbGuildYouTubeSubscriptionsTable,
88
dbGuildTwitchSubscriptionsTable,
9+
dbDiscordTable,
910
} from "./schema";
1011

1112
export async function checkIfGuildIsTrackingUserAlready(
@@ -280,3 +281,46 @@ export async function discordRemoveGuildTrackingChannel(
280281
return { success: false, data: [] };
281282
}
282283
}
284+
285+
// Add a new guild to track
286+
export async function discordAddNewGuild(
287+
guildId: string,
288+
): Promise<{ success: boolean; data: [] }> {
289+
console.log(`Adding new guild to track: ${guildId}`);
290+
291+
try {
292+
await db.insert(dbDiscordTable).values({
293+
guildId,
294+
allowedPublicSharing: false,
295+
isInServer: true,
296+
memberCount: 0,
297+
});
298+
299+
return { success: true, data: [] };
300+
} catch (error) {
301+
console.error("Error adding new guild to track:", error);
302+
303+
return { success: false, data: [] };
304+
}
305+
}
306+
307+
// "Remove" a guild from tracking
308+
// Basically just set isInServer to false for archival purposes
309+
export async function discordRemoveGuildFromTracking(
310+
guildId: string,
311+
): Promise<{ success: boolean; data: [] }> {
312+
console.log(`Removing guild from tracking: ${guildId}`);
313+
314+
try {
315+
await db
316+
.update(dbDiscordTable)
317+
.set({ isInServer: false })
318+
.where(eq(dbDiscordTable.guildId, guildId));
319+
320+
return { success: true, data: [] };
321+
} catch (error) {
322+
console.error("Error removing guild from tracking:", error);
323+
324+
return { success: false, data: [] };
325+
}
326+
}

src/db/schema.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export const dbDiscordTable = pgTable("discord", {
88
allowedPublicSharing: boolean("allowed_public_sharing").notNull().default(false),
99
feedrUpdatesChannelId: text("feedr_updates_channel_id"),
1010
isInServer: boolean("is_in_server").notNull().default(true),
11+
memberCount: integer("member_count").notNull().default(0),
1112
});
1213

1314
export const dbBlueskyTable = pgTable("bluesky", {

src/events/guildCreate.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Events } from "discord.js";
2+
3+
import client from "..";
4+
import { discordAddNewGuild } from "../db/discord";
5+
6+
client.on(Events.GuildCreate, async (guild) => {
7+
console.log(`Joined new guild: ${guild.name} (ID: ${guild.id})`);
8+
9+
// Add the new guild to tracking
10+
const result = await discordAddNewGuild(guild.id);
11+
12+
if (result.success) {
13+
console.log(`Successfully added guild ${guild.id} to tracking.`);
14+
} else {
15+
console.error(`Failed to add guild ${guild.id} to tracking.`);
16+
}
17+
});

src/events/guildDelete.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Events } from "discord.js";
2+
3+
import client from "..";
4+
import { discordRemoveGuildFromTracking } from "../db/discord";
5+
6+
client.on(Events.GuildDelete, async (guild) => {
7+
console.log(`Left guild: ${guild.name} (ID: ${guild.id})`);
8+
9+
// Remove the guild from tracking
10+
const result = await discordRemoveGuildFromTracking(guild.id);
11+
12+
if (result.success) {
13+
console.log(`Successfully removed guild ${guild.id} from tracking.`);
14+
} else {
15+
console.error(`Failed to remove guild ${guild.id} from tracking.`);
16+
}
17+
});

src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { env } from "./config.ts";
1515
import commandsMap from "./commands.ts";
1616
import { getTwitchToken } from "./utils/twitch/auth.ts";
17+
import updateGuildsOnStartup from "./utils/discord/updateGuildsOnStartup.ts";
1718

1819
if (!env.discordToken || env.discordToken === "YOUR_DISCORD_TOKEN") {
1920
throw new Error("You MUST provide a discord token in .env!");
@@ -75,6 +76,9 @@ await Promise.all(
7576
}),
7677
);
7778

79+
// Update the guilds on startup
80+
await updateGuildsOnStartup();
81+
7882
// Attempt the garbage collection every hour
7983
setInterval(
8084
() => {
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
// Checks for any guilds that may have been added/removed while the bot was offline
2+
import { eq } from "drizzle-orm";
3+
4+
import { dbDiscordTable } from "../../db/schema";
5+
import client from "../..";
6+
import { db } from "../../db/db";
7+
import { config } from "../../config";
8+
9+
export default async function () {
10+
console.log("Checking for guilds to update on startup...");
11+
12+
let currentGuilds: string[] = [];
13+
14+
// Keep checking every 10 seconds until currentGuilds is not empty
15+
while (currentGuilds.length === 0) {
16+
console.log("Waiting for guilds to load...");
17+
currentGuilds = client.guilds.cache.map((guild) => guild.id);
18+
if (currentGuilds.length === 0) {
19+
await new Promise((resolve) =>
20+
setTimeout(resolve, config.discordWaitForGuildCacheTime),
21+
);
22+
}
23+
}
24+
25+
// Get all the guilds from the database
26+
const data = await db.select().from(dbDiscordTable);
27+
28+
console.log(
29+
`Currently in ${currentGuilds.length} guilds, checking against ${data.length} in the database.`,
30+
);
31+
32+
// Find any guilds that are in the database but not in the current guilds
33+
const missingGuilds = data.filter(
34+
(guild) => !currentGuilds.includes(guild.guildId),
35+
);
36+
37+
// Find any guilds that are in the current guilds but not in the database
38+
const newGuilds = currentGuilds.filter(
39+
(id) => !data.some((guild) => guild.guildId === id),
40+
);
41+
42+
// Update the database for missing guilds
43+
try {
44+
await Promise.all(
45+
missingGuilds.map(async (guild) => {
46+
console.log(`Removing guild from tracking: ${guild.guildId}`);
47+
const result = await db
48+
.update(dbDiscordTable)
49+
.set({ isInServer: false })
50+
.where(eq(dbDiscordTable.guildId, guild.guildId))
51+
.returning();
52+
53+
if (result.length > 0) {
54+
console.log(
55+
`Successfully removed guild ${guild.guildId} from tracking.`,
56+
);
57+
} else {
58+
console.error(
59+
`Failed to remove guild ${guild.guildId} from tracking.`,
60+
);
61+
}
62+
}),
63+
);
64+
} catch (error) {
65+
console.error("Error while removing missing guilds:", error);
66+
}
67+
68+
try {
69+
await Promise.all(
70+
newGuilds.map(async (guildId) => {
71+
console.log(`Adding new guild to tracking: ${guildId}`);
72+
const result = await db
73+
.insert(dbDiscordTable)
74+
.values({
75+
guildId,
76+
allowedPublicSharing: false,
77+
feedrUpdatesChannelId: null,
78+
isInServer: true,
79+
memberCount: 0,
80+
})
81+
.returning();
82+
83+
if (result.length > 0) {
84+
console.log(
85+
`Successfully added guild ${guildId} to tracking.`,
86+
);
87+
} else {
88+
console.error(
89+
`Failed to add guild ${guildId} to tracking.`,
90+
);
91+
}
92+
}),
93+
);
94+
} catch (error) {
95+
console.error("Error while adding new guilds:", error);
96+
}
97+
}

src/utils/youtube/fetchLatestUploads.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
import type { Platform } from "../../types/types.d.ts";
2-
1+
import { Platform } from "../../types/types.d";
32
import {
43
dbGuildYouTubeSubscriptionsTable,
54
dbYouTubeTable,

0 commit comments

Comments
 (0)