Skip to content

Commit

Permalink
Make emote-logging user-independent
Browse files Browse the repository at this point in the history
  • Loading branch information
twobiers committed Jul 19, 2024
1 parent 78eb5b4 commit d3fa541
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 41 deletions.
8 changes: 4 additions & 4 deletions src/commands/emoteStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,19 @@ import * as emoteLogging from "../service/emoteLogging.js";

export default class EmoteStatsCommand implements ApplicationCommand {
name = "emote-stats";
description = "Schickt dir deine persönlichen Emote-Statistiken.";
description = "Schickt Emote-Statistiken.";

applicationCommand = new SlashCommandBuilder()
.setName(this.name)
.setDescription(this.description);

async handleInteraction(command: CommandInteraction, context: BotContext): Promise<void> {
const stats = await emoteLogging.getUserStats(command.user, 10);
const stats = await emoteLogging.getGlobalStats(10);
const totalEmotes = Math.sumPrecise(stats.map(s => s.count)) | 0;
await command.reply({
embeds: [
{
title: "Deine Emote-Statistiken",
title: "Emote-Statistiken",
author: {
name: command.user.username,
icon_url: command.user.displayAvatarURL(),
Expand All @@ -28,7 +28,7 @@ export default class EmoteStatsCommand implements ApplicationCommand {
value: `${s.count} mal`,
})),
footer: {
text: `Du hast insgesamt ${totalEmotes} Emotes verwendet.`,
text: `Es wurden insgesamt ${totalEmotes} Emotes verwendet.`,
},
},
],
Expand Down
10 changes: 4 additions & 6 deletions src/handler/logEmotesReactionHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@ import * as emoteLogging from "../service/emoteLogging.js";
export default {
displayName: "Log Emotes Reaction Handler",
async execute(reactionEvent, invoker, context, reactionWasRemoved) {
return;

// biome-ignore lint/correctness/noUnreachable: Deactivated due to privacy concerns
if (invoker.bot) {
return;
}

// Not supported
if (reactionWasRemoved) {
await emoteLogging.processReactionRemove(reactionEvent, invoker, context);
} else {
await emoteLogging.processReactionAdd(reactionEvent, invoker, context);
return;
}

await emoteLogging.processReactionAdd(reactionEvent, context);
},
} satisfies ReactionHandler;
20 changes: 3 additions & 17 deletions src/service/emoteLogging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,7 @@ import * as emoteService from "./emoteService.js";

import log from "@log";

export async function processReactionAdd(
reactionEvent: MessageReaction,
invoker: User,
_context: BotContext,
) {
export async function processReactionAdd(reactionEvent: MessageReaction, _context: BotContext) {
const message = reactionEvent.message;
if (!message.inGuild()) {
return;
Expand All @@ -37,19 +33,9 @@ export async function processReactionAdd(
parsedEmote.animated,
emoteService.getEmoteUrl(parsedEmote),
message,
invoker,
);
}

export async function processReactionRemove(
reactionEvent: MessageReaction,
invoker: User,
_context: BotContext,
) {
// TODO: Implement
log.info({ emoji: reactionEvent.emoji }, "Reaction removed");
}

export async function processMessage(message: ProcessableMessage, context: BotContext) {
const emotes = emoteService.extractEmotesFromMessage(message.content);
for (const emote of emotes) {
Expand Down Expand Up @@ -96,6 +82,6 @@ export async function persistCurrentGuildEmotes(context: BotContext) {
}
}

export async function getUserStats(user: User, limit: number) {
return dbEmote.getUsage(user, limit | 0);
export async function getGlobalStats(limit: number) {
return dbEmote.getGlobalUsage(limit | 0);
}
5 changes: 0 additions & 5 deletions src/storage/db/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,6 @@ export interface EmoteUseTable extends AuditedTable {

messageGuildId: ColumnType<Snowflake, Snowflake, never>;
channelId: ColumnType<Snowflake, Snowflake, never>;
messageId: ColumnType<Snowflake, Snowflake, never>;
emoteId: ColumnType<number, number, never>;
usedByUserId: ColumnType<Snowflake, Snowflake, never>;
usedByUserName: string;
isReaction: boolean;

deletedAt: ColumnType<string | null, null, string | null>; // TODO: Date is not supported by the DB driver
}
10 changes: 1 addition & 9 deletions src/storage/emote.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ export async function logMessageUse(
// not using emote.guild.id because the emote can originate from a different server
messageGuildId: message.guildId,
channelId: message.channelId,
messageId: message.id,
emoteId: existingEmote.id,
usedByUserId: message.author.id,
usedByUserName: message.author.displayName,
isReaction: false,
})
.execute();
Expand All @@ -38,7 +35,6 @@ export async function logReactionUse(
isAnimated: boolean,
url: string,
message: Message<true>,
invoker: User,
ctx = db(),
) {
await ctx.transaction().execute(async ctx => {
Expand All @@ -49,10 +45,7 @@ export async function logReactionUse(
// not using emote.guild.id because the emote can originate from a different server
messageGuildId: message.guildId,
channelId: message.channelId,
messageId: message.id,
emoteId: existingEmote.id,
usedByUserId: invoker.id,
usedByUserName: invoker.displayName,
isReaction: true,
})
.execute();
Expand Down Expand Up @@ -107,11 +100,10 @@ export async function markAsDeleted(emoteId: Emote["id"], ctx = db()): Promise<v
.execute();
}

export async function getUsage(user: User, limit: number, ctx = db()) {
export async function getGlobalUsage(limit: number, ctx = db()) {
return await ctx
.selectFrom("emoteUse")
.innerJoin("emote", "emote.id", "emoteUse.emoteId")
.where("usedByUserId", "=", user.id)
.groupBy("emote.emoteId")
.select([
"emote.emoteId",
Expand Down
43 changes: 43 additions & 0 deletions src/storage/migrations/06-emote-private.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { sql, type Kysely } from "kysely";

export async function up(db: Kysely<any>) {
db.schema.dropTable("emoteUse");

await db.schema
.createTable("emoteUse")
.addColumn("id", "integer", c => c.primaryKey().autoIncrement())
.addColumn("messageGuildId", "text", c => c.notNull())
.addColumn("channelId", "text", c => c.notNull())
.addColumn("emoteId", "integer", c => c.notNull())
.addColumn("isReaction", "boolean", c => c.notNull())
.addColumn("createdAt", "timestamp", c => c.notNull().defaultTo(sql`current_timestamp`))
.addColumn("updatedAt", "timestamp", c => c.notNull().defaultTo(sql`current_timestamp`))
.execute();

await db.schema
.createIndex("emoteUse_emoteId_isReaction_deletedAt")
.on("emoteUse")
.columns(["emoteId", "isReaction", "deletedAt"])
.unique()
.execute();

await createUpdatedAtTrigger(db, "emoteUse");
}

function createUpdatedAtTrigger(db: Kysely<any>, tableName: string) {
return sql
.raw(`
create trigger ${tableName}_updatedAt
after update on ${tableName} for each row
begin
update ${tableName}
set updatedAt = current_timestamp
where id = old.id;
end;
`)
.execute(db);
}

export async function down(_db: Kysely<any>) {
throw new Error("Not supported lol");
}

0 comments on commit d3fa541

Please sign in to comment.