/* * Copyright (C) 2026 Fluxer Contributors * * This file is part of Fluxer. * * Fluxer is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Fluxer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Fluxer. If not, see . */ import {createMessageID, type MessageID, type UserID} from '@fluxer/api/src/BrandedTypes'; import {BatchBuilder, fetchMany, fetchOne} from '@fluxer/api/src/database/Cassandra'; import type {RecentMentionRow} from '@fluxer/api/src/database/types/UserTypes'; import {RecentMention} from '@fluxer/api/src/models/RecentMention'; import {RecentMentions, RecentMentionsByGuild} from '@fluxer/api/src/Tables'; import {generateSnowflake} from '@fluxer/snowflake/src/Snowflake'; const FETCH_RECENT_MENTION_CQL = RecentMentions.selectCql({ where: [RecentMentions.where.eq('user_id'), RecentMentions.where.eq('message_id')], limit: 1, }); const createFetchRecentMentionsQuery = (limit: number) => RecentMentions.selectCql({ where: [RecentMentions.where.eq('user_id'), RecentMentions.where.lt('message_id', 'before_message_id')], limit, }); export class RecentMentionRepository { async getRecentMention(userId: UserID, messageId: MessageID): Promise { const mention = await fetchOne(FETCH_RECENT_MENTION_CQL, { user_id: userId, message_id: messageId, }); return mention ? new RecentMention(mention) : null; } async listRecentMentions( userId: UserID, includeEveryone: boolean = true, includeRole: boolean = true, includeGuilds: boolean = true, limit: number = 25, before?: MessageID, ): Promise> { const fetchLimit = Math.max(limit * 2, 50); const query = createFetchRecentMentionsQuery(fetchLimit); const params: {user_id: UserID; before_message_id: MessageID} = { user_id: userId, before_message_id: before || createMessageID(generateSnowflake()), }; const allMentions = await fetchMany(query, params); const filteredMentions = allMentions.filter((mention) => { if (!includeEveryone && mention.is_everyone) return false; if (!includeRole && mention.is_role) return false; if (!includeGuilds && mention.guild_id != null) return false; return true; }); return filteredMentions.slice(0, limit).map((mention) => new RecentMention(mention)); } async createRecentMention(mention: RecentMentionRow): Promise { const batch = new BatchBuilder(); batch.addPrepared(RecentMentions.upsertAll(mention)); batch.addPrepared( RecentMentionsByGuild.insert({ user_id: mention.user_id, guild_id: mention.guild_id, message_id: mention.message_id, channel_id: mention.channel_id, is_everyone: mention.is_everyone, is_role: mention.is_role, }), ); await batch.execute(); return new RecentMention(mention); } async createRecentMentions(mentions: Array): Promise { if (mentions.length === 0) { return; } const batch = new BatchBuilder(); for (const mention of mentions) { batch.addPrepared(RecentMentions.upsertAll(mention)); batch.addPrepared( RecentMentionsByGuild.insert({ user_id: mention.user_id, guild_id: mention.guild_id, message_id: mention.message_id, channel_id: mention.channel_id, is_everyone: mention.is_everyone, is_role: mention.is_role, }), ); } await batch.execute(); } async deleteRecentMention(mention: RecentMention): Promise { const batch = new BatchBuilder(); batch.addPrepared(RecentMentions.deleteByPk({user_id: mention.userId, message_id: mention.messageId})); batch.addPrepared( RecentMentionsByGuild.deleteByPk({ user_id: mention.userId, guild_id: mention.guildId, message_id: mention.messageId, }), ); await batch.execute(); } async deleteAllRecentMentions(userId: UserID): Promise { const mentions = await fetchMany<{guild_id: bigint; message_id: bigint}>( RecentMentions.selectCql({ columns: ['guild_id', 'message_id'], where: RecentMentions.where.eq('user_id'), }), { user_id: userId, }, ); const batch = new BatchBuilder(); batch.addPrepared(RecentMentions.delete({where: RecentMentions.where.eq('user_id')}).bind({user_id: userId})); for (const mention of mentions) { batch.addPrepared( RecentMentionsByGuild.deleteByPk({ guild_id: mention.guild_id, user_id: userId, message_id: mention.message_id, }), ); } if (batch) { await batch.execute(); } } }