Skip to content

Commit 00a3758

Browse files
committed
refactor(sharding): simplify guilds, drop top.gg stats, sendGuildCount
1 parent 062659b commit 00a3758

6 files changed

Lines changed: 64 additions & 65 deletions

File tree

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
"packageManager": "bun@1.3.13",
1616
"scripts": {
1717
"start": "bun run --env-file=.env ./src/index.ts",
18-
"prestart": "bun run format && bun run lint",
1918
"dev": "bun run --env-file=.env.dev ./src/index.ts",
2019
"dev:watch": "bun run --watch --env-file=.env.dev ./src/index.ts",
2120
"build": "tsup ./src && tsc-alias",

src/app/discord/commands/public/subcommands/info.ts

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,16 @@ export default createSubCommand({
2626
const displayShardId = isSharded ? (shardId ?? 0) + 1 : 1;
2727
const displayShardCount = isSharded ? (shardCount ?? 1) : 1;
2828

29-
let guilds = 0;
30-
let members = 0;
31-
let channels = 0;
29+
const guilds =
30+
client.getCustomVariable<number>('totalGuildCount') ??
31+
client.guilds.cache.size;
3232

33-
if (client.shard) {
34-
const results = await client.shard.broadcastEval((c) => ({
35-
guilds: c.guilds.cache.size,
36-
members: c.guilds.cache.reduce((total, g) => total + g.memberCount, 0),
37-
channels: c.channels.cache.size,
38-
}));
33+
const members = client.guilds.cache.reduce(
34+
(total, guild) => total + guild.memberCount,
35+
0,
36+
);
3937

40-
guilds = results.reduce((a, b) => a + b.guilds, 0);
41-
members = results.reduce((a, b) => a + b.members, 0);
42-
channels = results.reduce((a, b) => a + b.channels, 0);
43-
} else {
44-
guilds = client.guilds.cache.size;
45-
members = client.guilds.cache.reduce(
46-
(total, guild) => total + guild.memberCount,
47-
0,
48-
);
49-
channels = client.channels.cache.size;
50-
}
38+
const channels = client.channels.cache.size;
5139

5240
const uptimeTimestamp = Math.floor(
5341
(Date.now() - (client.uptime ?? 0)) / 1000,

src/app/discord/events/clientReady.ts

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
import { createEvent } from '@base';
2-
import { env } from '@env';
32
import { logger } from '@fx/utils/logger.js';
4-
import { isShardManager } from '@basedir/discord/client/bot/sharding.js';
53
import { loadWorkers } from '@basedir/discord/client/bot/loaders.js';
64
import { preloadBlacklistCache } from '@basedir/discord/client/bot/middleware.js';
75
import { ActivityType } from 'discord.js';
8-
import { AutoPoster } from 'topgg-autoposter';
96
import { MusicController } from '@basedir/music/MusicController.js';
107
import type { KoxikClient } from '@basedir/discord/client/bot/CustomClient.js';
118
import { setupMusicPresence } from '@app/discord/utils/musicPresence.js';
@@ -41,27 +38,27 @@ export default createEvent({
4138
type: ActivityType.Watching,
4239
},
4340
{
44-
name: `slash commands`,
41+
name: 'slash commands',
4542
type: ActivityType.Listening,
4643
},
4744
{
48-
name: `async dreams`,
45+
name: 'async dreams',
4946
type: ActivityType.Playing,
5047
},
5148
{
52-
name: `TypeScript thoughts`,
49+
name: 'TypeScript thoughts',
5350
type: ActivityType.Competing,
5451
},
5552
{
56-
name: `online… probably`,
53+
name: 'online… probably',
5754
type: ActivityType.Playing,
5855
},
5956
];
6057
};
6158

6259
let index = 0;
6360

64-
setInterval(async () => {
61+
setInterval(() => {
6562
if (musicController.musicModeActive) return;
6663

6764
const statuses = getStatuses();
@@ -74,25 +71,6 @@ export default createEvent({
7471
index++;
7572
}, 60_000);
7673

77-
if (env.TOPGG_TOKEN) {
78-
if (process.env.KOXIK_SHARD === 'true') {
79-
const report = () => {
80-
if (!process.send) return;
8174

82-
process.send({
83-
type: 'GUILD_COUNT',
84-
shardId: Number(process.env.SHARD_ID),
85-
count: client.guilds.cache.size,
86-
});
87-
};
88-
89-
report();
90-
setInterval(report, 30 * 60 * 1000);
91-
} else if (!isShardManager()) {
92-
AutoPoster(env.TOPGG_TOKEN!, client).on('posted', () => {
93-
logger.success('Posted stats on top.gg!');
94-
});
95-
}
96-
}
9775
},
9876
});

src/core/base/discord/client/KoxikClient.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { env } from '@env';
33
import { logger } from '@fx/utils/logger.js';
44
import { initSentry, Sentry } from '@basedir/sentry/index.js';
55
import {
6-
type Client,
76
type ClientEvents,
87
GatewayIntentBits,
98
Partials,
@@ -36,8 +35,10 @@ import type {
3635

3736
import {
3837
getShardData,
38+
isShardManager,
3939
resolveSharding,
4040
applySharding,
41+
sendGuildCount,
4142
} from './bot/sharding.js';
4243

4344
export function resolveRegisterTypes(
@@ -71,6 +72,18 @@ export function createBot(options: BotOptions) {
7172
applySharding(resolved);
7273
}
7374

75+
if (isShardManager()) {
76+
return {
77+
client: undefined as never,
78+
createCommand: undefined as never,
79+
createEvent: undefined as never,
80+
createSubCommand: undefined as never,
81+
createSubCommandGroup: undefined as never,
82+
createResponder: undefined as never,
83+
registerResponder: undefined as never,
84+
};
85+
}
86+
7487
const { shardId, shardCount, isMainShard, isPM2Cluster } = getShardData();
7588

7689
const clientOptions: any = {
@@ -99,14 +112,6 @@ export function createBot(options: BotOptions) {
99112
: [],
100113
);
101114

102-
if (shardId !== undefined && shardCount !== undefined) {
103-
(client as unknown as Record<string, unknown>).shard = {
104-
ids: [shardId],
105-
count: shardCount,
106-
broadcastEval: async (fn: (c: Client) => unknown) => [await fn(client)],
107-
};
108-
}
109-
110115
const commands = new Map<string, Command>();
111116
const registeredEvents = new Set<string>();
112117

@@ -137,6 +142,13 @@ export function createBot(options: BotOptions) {
137142
`Connected as ${client.user?.tag ?? 'unknown'} (shard ${shardId ?? 0})`,
138143
);
139144

145+
sendGuildCount(client.guilds.cache.size);
146+
setInterval(() => {
147+
sendGuildCount(client.guilds.cache.size);
148+
}, 5 * 60 * 1000);
149+
client.on('guildCreate', () => sendGuildCount(client.guilds.cache.size));
150+
client.on('guildDelete', () => sendGuildCount(client.guilds.cache.size));
151+
140152
if (!isMainShard) {
141153
logger.info('Not main shard - loading commands only');
142154
} else {

src/core/base/discord/client/bot/interactionHandler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { ReplyBuilder } from './ReplyBuilder.js';
1010
import { getResponders } from './registry.js';
1111
import { isShardManager } from './sharding.js';
1212
import type { Command, ComponentInteraction, InteractionMap } from './types.js';
13+
import { getShardData } from './sharding.js';
1314

1415
export function checkInteractionGlobal(id: string): Promise<boolean> {
1516
return new Promise((resolve) => {
@@ -109,10 +110,9 @@ export function setupInteractionHandler(
109110
if (!command) return;
110111
if (!(await checkInteractionGlobal(interaction.id))) return;
111112

112-
if (interaction.guildId && client.shard) {
113-
const shardId = client.shard.ids[0];
114-
const shardCount = client.options.shardCount ?? 1;
113+
const { shardId, shardCount } = getShardData();
115114

115+
if (interaction.guildId && shardId !== undefined && shardCount !== undefined) {
116116
const guildShard =
117117
Number(BigInt(interaction.guildId) >> 22n) % shardCount;
118118

src/core/base/discord/client/bot/sharding.ts

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,28 @@ export function isShardManager(): boolean {
1515

1616
function postToTopGg() {
1717
if (!topGgApi) return;
18+
if (guildCounts.size !== topGgTotalShards) return;
19+
20+
console.log(guildCounts);
1821

1922
let total = 0;
23+
2024
for (const count of guildCounts.values()) {
2125
total += count;
2226
}
23-
if (total === 0) return;
27+
28+
console.log({
29+
total,
30+
shards: guildCounts.size,
31+
});
2432

2533
topGgApi
26-
.postStats({ serverCount: total, shardCount: topGgTotalShards })
27-
.then(() => console.log('[Koxik] Posted stats on top.gg!'))
28-
.catch((err) => console.error('[Koxik] Top.GG post failed:', err));
34+
.postStats({
35+
serverCount: total,
36+
shardCount: topGgTotalShards,
37+
})
38+
.then(() => console.log(`[Koxik] Posted ${total} guilds to top.gg!`))
39+
.catch(console.error);
2940
}
3041

3142
function startTopGGPosting(totalShards: number) {
@@ -102,9 +113,14 @@ export function setupSharding() {
102113
typeof msg.count === 'number'
103114
) {
104115
guildCounts.set(msg.shardId, msg.count);
116+
105117
broadcastTotalGuildCount();
106-
postToTopGg();
118+
119+
if (guildCounts.size === topGgTotalShards) {
120+
postToTopGg();
121+
}
107122
}
123+
108124
break;
109125
}
110126
}
@@ -128,6 +144,12 @@ export function setupSharding() {
128144
return true;
129145
}
130146

147+
export function sendGuildCount(count: number) {
148+
const { shardId } = getShardData();
149+
if (shardId === undefined || !process.send) return;
150+
process.send({ type: 'GUILD_COUNT', shardId, count });
151+
}
152+
131153
export function getShardData() {
132154
const isPM2Cluster =
133155
process.env.KOXIK_PM2_SHARD === 'true' || process.env.pm_id !== undefined;

0 commit comments

Comments
 (0)