5.5 KiB
5.5 KiB
Bot-Side Report Handling Compatibility Assessment (Batch 2)
1. Bot Report Format Details
Location: crates/cgcx-bot/src/main.rs:1720-1730
The bot constructs the forwarded report message as follows (HTML parse mode):
<b>[ NEW REPORT ]</b> #{report_id}
CXID: <code>{cxid}</code>
Reporter: <code>{reporter_id}</code>
Owner: <code>{content.user_id}</code>
Uploaded: <i>{YYYY-MM-DD HH:MM}</i>
Files: <b>1</b>
Notes:
report_idis the auto-incremented SQLite row ID returned byReportRepo::insert.cxidis extracted from the user’s message viaextract_cxid(text).reporter_idis the Telegramuser_idof the person reporting.content.user_idis the owner/uploader of the reported content.Files: <b>1</b>is hardcoded to1regardless of actual file count.
2. Inline Keyboard Layout Details
Location: crates/cgcx-bot/src/main.rs:1732-1742
The inline keyboard is a 2×2 grid:
| Row | Button Label | Callback Data |
|---|---|---|
| 1 | [ Rmv + Ban ] |
v1:admin:delblk:{report_id} |
| 1 | [ Delete Only ] |
v1:admin:del:{report_id} |
| 2 | [ Blacklist Only ] |
v1:admin:blk:{report_id} |
| 2 | [ Ignore ] |
v1:admin:ign:{report_id} |
These callbacks are handled by handle_admin_callback (main.rs:1745), which:
- Validates the user is an admin in the review group chat.
- Looks up the
Reportbyreport_id. - Performs the requested moderation action and resolves the report.
3. ReportRepo::insert Signature & Behavior
Location: crates/cgcx-db/src/repos.rs:426-433
pub async fn insert(
&self,
content_id: &ContentId,
reporter_user_id: i64,
reason: &str,
) -> Result<i64> {
let conn = self.conn.lock().await;
conn.execute(
"INSERT INTO reports (content_id, reporter_user_id, reason) VALUES (?1, ?2, ?3)",
params![content_id.as_str(), reporter_user_id, reason],
)?;
Ok(conn.last_insert_rowid())
}
- Returns
last_insert_rowid()(the generatedreport_id). - No additional validation inside the repo; the caller is responsible for ensuring
content_idexists.
4. Compatibility Assessment for Web Reports (reporter_user_id = 0)
❌ Critical Issue: Foreign Key Constraint Violation
Schema: migrations/001_init.sql:39-50
CREATE TABLE reports (
id INTEGER PRIMARY KEY AUTOINCREMENT,
content_id TEXT NOT NULL REFERENCES contents(id),
reporter_user_id INTEGER NOT NULL REFERENCES users(id),
reason TEXT NOT NULL,
...
);
Foreign key enforcement is enabled:
cgcx-db/src/lib.rs:21and:33both executePRAGMA foreign_keys = ON;.
Impact:
- Passing
reporter_user_id = 0toReportRepo::insertwill fail with a foreign key constraint violation because there is no user row withid = 0. - There is no anonymous/web user seed or special-case handling anywhere in the codebase.
⚠️ Secondary Issue: Reason Field Semantics
Location: crates/cgcx-bot/src/main.rs:1719
let report_id = report_repo.insert(&content_id, reporter_id, text).await?;
- In the bot flow,
textis the raw user message (a cxid or share link). The bot stores this raw cxid/link as thereason. - A web report API would naturally accept separate
cxidandreasonfields. If the server replicates the bot behavior by passing the cxid as the reason, the database will contain a machine ID instead of a human-readable report reason. - Recommendation: The server should pass the user-supplied human reason (or a placeholder like
"Web report") toReportRepo::insert, not the cxid.
⚠️ Tertiary Issue: Reporter Display
- The report message displays
Reporter: <code>{reporter_id}</code>. Ifreporter_id = 0, moderators will seeReporter: <code>0</code>, which is indistinguishable from a real user and not user-friendly. - Recommendation: Consider creating a dedicated anonymous/web reporter user (e.g.,
id = 0or a negative sentinel) with a recognizable username, or adjust the report template to show"Web"/"Anonymous"when the reporter is not a Telegram user.
5. Recommendations
- Create an anonymous/web reporter user row (e.g.,
id = 0or a dedicated negative ID) in theuserstable before any web report can be inserted, OR relax theNOT NULL/ foreign-key constraint onreporter_user_id(requires migration). - Update the server-side report endpoint to accept a separate
reasonfield and pass it toReportRepo::insert, rather than mirroring the bot’s cxid-as-reason behavior. - Align the report message template for web reports so that the
Reporter:line is meaningful (e.g.,"Reporter: Web"or"Reporter: Anonymous") instead of a raw numeric0. - Optional: Fix the hardcoded
Files: <b>1</b>in the bot template to use the actual file count fromContentFileRepo::list_by_content, so the server report and bot report are consistent.
6. Summary Table
| Aspect | Bot Behavior | Web Report Compatibility | Risk |
|---|---|---|---|
| Message format | HTML with hardcoded Files: 1 |
Server can replicate easily | Low (cosmetic) |
| Keyboard layout | 2×2 grid with v1:admin:*:{id} |
Fully compatible | None |
ReportRepo::insert |
Accepts any i64 for reporter_user_id |
Fails at runtime for 0 |
High |
reason field |
Stores raw cxid/link | Misleading if replicated verbatim | Medium |
| Reporter display | Raw numeric ID | 0 is uninformative |
Low |