diff --git a/src/commands/report.ts b/src/commands/report.ts index 35c6af3..f632e97 100644 --- a/src/commands/report.ts +++ b/src/commands/report.ts @@ -5,19 +5,26 @@ import { CommandsCollection } from "@/lib/managed-commands" import { logger } from "@/logger" import { modules } from "@/modules" import { fmt } from "@/utils/format" +import { ephemeral } from "@/utils/messages" import type { Role } from "@/utils/types" export const logReport = async (context: Filter | CommandScopedContext, repliedTo: Message) => { const reportSent = await modules.get("tgLogger").report(repliedTo, context.from) - await context.reply( - reportSent - ? fmt(({ b, n }) => [b`✅ Message reported!`, n`Moderators have been notified.`], { sep: "\n" }) - : fmt(({ b, n }) => [b`⚠️ Report not sent`, n`Please try again in a moment.`], { sep: "\n" }), - { - disable_notification: false, - reply_parameters: { message_id: repliedTo.message_id }, - } - ) + + let msg: string = "" + if (reportSent === "SENT") + msg = fmt(({ b, n }) => [b`✅ Message reported!`, n`Moderators have been notified.`], { sep: "\n" }) + else if (reportSent === "ALREADY_SENT") + msg = fmt(({ b, n }) => [b`☑️ Message already reported!`, n`Moderators have been notified.`], { sep: "\n" }) + else if (reportSent === "ERROR") + msg = fmt(({ b, n }) => [b`⚠️ Report not sent`, n`Please try again in a moment.`], { sep: "\n" }) + + const feedback = await context.reply(msg, { + disable_notification: false, + reply_parameters: { message_id: repliedTo.message_id }, + }) + + if (reportSent !== "SENT") void ephemeral(feedback) } export const report = new CommandsCollection().createCommand({ diff --git a/src/modules/tg-logger/index.ts b/src/modules/tg-logger/index.ts index 6492afb..92a179e 100644 --- a/src/modules/tg-logger/index.ts +++ b/src/modules/tg-logger/index.ts @@ -1,7 +1,9 @@ import { GrammyError, InlineKeyboard } from "grammy" import type { Message, User } from "grammy/types" import { Module } from "@/lib/modules" +import { RedisFallbackAdapter } from "@/lib/redis-fallback-adapter" import { logger } from "@/logger" +import { redis } from "@/redis" import { groupMessagesByChat, stripChatId } from "@/utils/chat" import { fmt, fmtChat, fmtDate, fmtUser } from "@/utils/format" import type { ModuleShared } from "@/utils/types" @@ -13,6 +15,8 @@ import { grantCreatedMenu, grantMessageMenu } from "./grants" import { getReportText, type Report, reportMenu } from "./report" import type * as Types from "./types" +type REPORT_RESULT = "SENT" | "ALREADY_SENT" | "ERROR" + type Topics = { actionRequired: number banAll: number @@ -36,6 +40,13 @@ const MOD_ACTION_TITLE = (props: ModerationAction) => })[props.action] export class TgLogger extends Module { + private reportStorage = new RedisFallbackAdapter({ + redis, + logger, + prefix: "report", + ttl: 900, + }) + constructor( public readonly groupId: number, private topics: Topics @@ -97,10 +108,15 @@ export class TgLogger extends Module { return [] } - public async report(message: Message, reporter: User): Promise { - if (message.from === undefined) return false // should be impossible + public async report(message: Message, reporter: User): Promise { + if (message.from === undefined) return "ERROR" // should be impossible const { invite_link } = await this.shared.api.getChat(message.chat.id) + const reportKey = `${message.chat.id}_${message.message_id}` + + if (await this.reportStorage.has(reportKey).catch(() => false)) return "ALREADY_SENT" + await this.reportStorage.write(reportKey, true).catch(() => {}) + const report: Report = { message, reporter } as Report const reportText = getReportText(report, invite_link) const reply_markup = await reportMenu(report) @@ -109,10 +125,10 @@ export class TgLogger extends Module { disable_notification: false, }) - if (!reportMsg) return false + if (!reportMsg) return "ERROR" await this.forward(this.topics.actionRequired, message.chat.id, [message.message_id]) - return true + return "SENT" } // NOTE: this does not delete the messages