fix: refresh complete reaction state
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"tasks": {
|
||||
"check": "deno fmt --check && deno lint && deno check src/index.ts && deno test",
|
||||
"start": "deno run --allow-env=TOKEN,CLIENT_ID,CONFIG_PATH,NODE_V8_COVERAGE,UNDICI_NO_FG,JEST_WORKER_ID,SHARDS,SHARD_COUNT,SHARDING_MANAGER,SHARDING_MANAGER_MODE,DISCORD_TOKEN,WS_NO_BUFFER_UTIL,WS_NO_UTF_8_VALIDATE --allow-net=discord.com,gateway.discord.gg --allow-read=./config.json,/data/config.json --allow-write=.,/data src/index.ts"
|
||||
"start": "deno run --allow-env=TOKEN,CLIENT_ID,CONFIG_PATH,NODE_V8_COVERAGE,UNDICI_NO_FG,JEST_WORKER_ID,SHARDS,SHARD_COUNT,SHARDING_MANAGER,SHARDING_MANAGER_MODE,DISCORD_TOKEN,WS_NO_BUFFER_UTIL,WS_NO_UTF_8_VALIDATE --allow-net=discord.com,gateway.discord.gg --allow-read=./config.json,./config.json.tmp,/data/config.json,/data/config.json.tmp --allow-write=.,/data src/index.ts"
|
||||
},
|
||||
"compilerOptions": {
|
||||
"lib": ["deno.window"]
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { EmbedBuilder, MessageReaction, PartialMessageReaction } from "discord.js";
|
||||
import { EmbedBuilder, Message } from "discord.js";
|
||||
|
||||
export default function awardEmbed(
|
||||
reaction: MessageReaction | PartialMessageReaction,
|
||||
message: Message,
|
||||
score: number,
|
||||
): EmbedBuilder {
|
||||
const message = reaction.message;
|
||||
const reactionSummary = message.reactions.cache
|
||||
.map((item) => `${item.emoji} ×${item.count}`)
|
||||
.join(" · ");
|
||||
|
||||
+68
-4
@@ -51,6 +51,7 @@ client.once(Events.ClientReady, (readyClient) => {
|
||||
`Logged in as ${readyClient.user.tag}; serving ${readyClient.guilds.cache.size} guild(s).`,
|
||||
);
|
||||
readyClient.user.setActivity("👑 awarding funny messages");
|
||||
void reconcileAwards().catch((error) => console.error("Failed to reconcile awards:", error));
|
||||
});
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
@@ -185,9 +186,13 @@ async function updateAward(
|
||||
reaction: MessageReaction | PartialMessageReaction,
|
||||
): Promise<void> {
|
||||
if (reaction.partial) await reaction.fetch();
|
||||
if (reaction.message.partial) await reaction.message.fetch();
|
||||
// Reaction gateway events only populate the cache entry that changed. Always fetch the
|
||||
// message so reactions that existed before this process started are included as well.
|
||||
const message = await reaction.message.fetch(true);
|
||||
await updateAwardForMessage(message);
|
||||
}
|
||||
|
||||
const message = reaction.message;
|
||||
async function updateAwardForMessage(message: Message): Promise<void> {
|
||||
const entry = watchedEntry(message);
|
||||
if (!message.guild || !entry) return;
|
||||
|
||||
@@ -225,7 +230,7 @@ async function updateAward(
|
||||
return;
|
||||
}
|
||||
|
||||
const payload = { embeds: [awardEmbed(reaction, score)] };
|
||||
const payload = { embeds: [awardEmbed(message, score)] };
|
||||
if (oldAward) {
|
||||
await oldAward.edit(payload);
|
||||
if (entry.awards[message.id] !== oldAward.id) {
|
||||
@@ -239,6 +244,65 @@ async function updateAward(
|
||||
}
|
||||
}
|
||||
|
||||
async function reconcileAwards(): Promise<void> {
|
||||
let reconciled = 0;
|
||||
for (const entry of entries) {
|
||||
if (!entry.output_channel) continue;
|
||||
|
||||
const guild = await client.guilds.fetch(entry.server).catch(() => undefined);
|
||||
if (!guild) continue;
|
||||
const outputChannel = await guild.channels.fetch(entry.output_channel).catch(() => undefined);
|
||||
if (!(outputChannel instanceof BaseGuildTextChannel)) continue;
|
||||
|
||||
const sourceChannels = new Map<string, string>();
|
||||
const recentAwards = await outputChannel.messages.fetch({ limit: 100 });
|
||||
for (const award of recentAwards.values()) {
|
||||
if (award.author.id !== client.user?.id) continue;
|
||||
const source = getSourceMessageLocation(award);
|
||||
if (source) sourceChannels.set(source.messageId, source.channelId);
|
||||
}
|
||||
|
||||
for (const [sourceMessageId, awardMessageId] of Object.entries(entry.awards)) {
|
||||
if (sourceChannels.has(sourceMessageId)) continue;
|
||||
const award = await outputChannel.messages.fetch(awardMessageId).catch(() => undefined);
|
||||
if (!award) continue;
|
||||
const source = getSourceMessageLocation(award);
|
||||
if (source?.messageId === sourceMessageId) {
|
||||
sourceChannels.set(sourceMessageId, source.channelId);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [sourceMessageId, sourceChannelId] of sourceChannels) {
|
||||
const sourceChannel = await guild.channels.fetch(sourceChannelId).catch(() => undefined);
|
||||
if (!(sourceChannel instanceof BaseGuildTextChannel)) continue;
|
||||
|
||||
const sourceMessage = await sourceChannel.messages.fetch({
|
||||
message: sourceMessageId,
|
||||
force: true,
|
||||
}).catch(() => undefined);
|
||||
if (!sourceMessage) continue;
|
||||
|
||||
await updateAwardForMessage(sourceMessage);
|
||||
reconciled++;
|
||||
}
|
||||
}
|
||||
if (reconciled > 0) console.log(`Reconciled ${reconciled} existing award(s).`);
|
||||
}
|
||||
|
||||
function getSourceMessageLocation(
|
||||
award: Message,
|
||||
): { channelId: string; messageId: string } | undefined {
|
||||
for (const embed of award.embeds) {
|
||||
for (const field of embed.fields) {
|
||||
const match = field.value.match(
|
||||
/https:\/\/discord\.com\/channels\/\d+\/(\d+)\/(\d+)/,
|
||||
);
|
||||
if (match) return { channelId: match[1], messageId: match[2] };
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function watchedEntry(message: Message | PartialMessage): Entry | undefined {
|
||||
const entry = entries.find((item) => item.server === message.guildId);
|
||||
if (!entry?.output_channel) return undefined;
|
||||
@@ -253,7 +317,7 @@ function listAllows(type: Type, values: string[], value: string): boolean {
|
||||
|
||||
async function getMessageScore(
|
||||
entry: Entry,
|
||||
message: Message | PartialMessage,
|
||||
message: Message,
|
||||
): Promise<number> {
|
||||
const reactionCounts = new Map<string, number>();
|
||||
for (const item of message.reactions.cache.values()) {
|
||||
|
||||
Reference in New Issue
Block a user