V0.1.1 release, close to actual release. Bug & security fixes/improvements.
This commit is contained in:
155
agent2_batch5_9.md
Normal file
155
agent2_batch5_9.md
Normal file
@@ -0,0 +1,155 @@
|
||||
# Verification Report: Batches 5–9
|
||||
|
||||
## Batch 5 — Review Action Buttons
|
||||
|
||||
**Item 1: `finalize_upload` sends keyboard with [ Approve ], [ Ignore ], [ Blackl. ], [ Ban ], [ Ban/BL u. ]**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-bot/src/main.rs:1494–1507`
|
||||
- **Evidence:**
|
||||
```rust
|
||||
let keyboard = InlineKeyboardMarkup::new(vec![
|
||||
vec![
|
||||
InlineKeyboardButton::callback("[ Approve ]", format!("v1:fwd:approve:{}", submission_id)),
|
||||
InlineKeyboardButton::callback("[ Ignore ]", format!("v1:fwd:ignore:{}", submission_id)),
|
||||
],
|
||||
vec![
|
||||
InlineKeyboardButton::callback("[ Blackl. ]", format!("v1:fwd:blk:{}", submission_id)),
|
||||
InlineKeyboardButton::callback("[ Ban ]", format!("v1:fwd:ban:{}", submission_id)),
|
||||
InlineKeyboardButton::callback("[ Ban/BL u. ]", format!("v1:fwd:banblk:{}", submission_id)),
|
||||
],
|
||||
]);
|
||||
```
|
||||
|
||||
**Item 2: `handle_forward_callback` handles `ban`, `banblk`, `blk`, `approve`, `ignore` actions**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-bot/src/main.rs:1873–2121`
|
||||
- **Evidence:** `match action` arm covers all five actions:
|
||||
- `"approve"` → lines 1899–2053
|
||||
- `"ignore"` → lines 2054–2065
|
||||
- `"blk"` → lines 2066–2077
|
||||
- `"ban"` → lines 2078–2094
|
||||
- `"banblk"` → lines 2095–2114
|
||||
|
||||
**Item 3: Permission check (`is_admin_in_chat` on review group) is present**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-bot/src/main.rs:1901–1905`
|
||||
- **Evidence:**
|
||||
```rust
|
||||
if !is_admin_in_chat(bot, ChatId(forward_def.review_group_id), UserId(user_id as u64)).await {
|
||||
bot.send_message(chat_id, "Unauthorized.").await?;
|
||||
return Ok(());
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Batch 6 — GLOBAL_BAN
|
||||
|
||||
**Item 1: `GroupsConfig` has `global_ban: bool`**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-config/src/lib.rs:66–73`
|
||||
- **Evidence:**
|
||||
```rust
|
||||
pub struct GroupsConfig {
|
||||
pub admin_group_ids: Vec<i64>,
|
||||
pub review_group_ids: Vec<i64>,
|
||||
#[serde(default = "default_global_ban")]
|
||||
pub global_ban: bool,
|
||||
}
|
||||
fn default_global_ban() -> bool { false }
|
||||
```
|
||||
|
||||
**Item 2: `propagate_punishment` checks `ctx.config.groups.global_ban`**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-bot/src/main.rs:2270–2272`
|
||||
- **Evidence:**
|
||||
```rust
|
||||
async fn propagate_punishment(...) {
|
||||
if !ctx.config.groups.global_ban {
|
||||
return;
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
**Item 3: Punishment commands (`/sban`, `/smute`, `/mute`, `/pban`, `/kick`) call `propagate_punishment`**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Lines:**
|
||||
- `/sban` → `main.rs:600`
|
||||
- `/smute` → `main.rs:629`
|
||||
- `/mute` → `main.rs:654`
|
||||
- `/pban` → `main.rs:675`
|
||||
- `/kick` → `main.rs:697`
|
||||
- **Evidence:** Each command inserts a local punishment row, then immediately calls `propagate_punishment(&bot, &ctx, chat_id, target_id, "...", ...).await;`.
|
||||
|
||||
---
|
||||
|
||||
## Batch 9 — Username Tracking
|
||||
|
||||
**Item 1: `UserRepo::ensure_exists` logs username changes to configurable path**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-db/src/repos.rs:15–41`
|
||||
- **Evidence:**
|
||||
```rust
|
||||
pub async fn ensure_exists(&self, id: i64, username: Option<&str>, first_name: &str, chat_id: i64, uname_changes_path: Option<&str>) -> Result<()> {
|
||||
...
|
||||
if let (Some(path), Some(ref old)) = (uname_changes_path, old_username) {
|
||||
if old.as_str() != username.unwrap_or("") {
|
||||
Self::log_username_change(id, chat_id, Some(old.as_str()), username, path);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
```
|
||||
`log_username_change` appends a JSON line with timestamp, user_id, chat_id, old, and new usernames.
|
||||
|
||||
**Item 2: `uname_changes_path` is in config**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Line:** `crates/cgcx-config/src/lib.rs:19–20, 27`
|
||||
- **Evidence:**
|
||||
```rust
|
||||
#[serde(default = "default_uname_changes_path")]
|
||||
pub uname_changes_path: String,
|
||||
fn default_uname_changes_path() -> String { "data/uname_changes.json".to_string() }
|
||||
```
|
||||
Also used in bot at `main.rs:389`:
|
||||
```rust
|
||||
user_repo.ensure_exists(user_id, user.username.as_deref(), &user.first_name, chat_id.0, Some(&ctx.config.uname_changes_path)).await?;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Batch 7 — Show/Hide Author
|
||||
|
||||
**Item 1: Upload options include `toggle_author` callback**
|
||||
- **Status:** ✅ PASS
|
||||
- **File/Lines:** `crates/cgcx-bot/src/main.rs:1008–1014, 1346–1364`
|
||||
- **Evidence:**
|
||||
- Callback handler:
|
||||
```rust
|
||||
"toggle_author" => {
|
||||
let new_options = UploadOptions { show_author: !options.show_author, ..options };
|
||||
...
|
||||
}
|
||||
```
|
||||
- Keyboard button:
|
||||
```rust
|
||||
InlineKeyboardButton::callback("[ Toggle Author ]", "v1:opt:toggle_author"),
|
||||
```
|
||||
- Display text:
|
||||
```rust
|
||||
let author_text = if options.show_author { "Show author: <b>Yes</b>" } else { "Show author: <b>No</b>" };
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Batch | Feature | Status |
|
||||
|-------|---------|--------|
|
||||
| 5 | Review action buttons (keyboard + handler + permission check) | ✅ PASS |
|
||||
| 6 | GLOBAL_BAN config + propagation | ✅ PASS |
|
||||
| 7 | Show/Hide Author toggle | ✅ PASS |
|
||||
| 9 | Username change tracking | ✅ PASS |
|
||||
|
||||
**No issues found.** All inspected features are implemented and correctly wired.
|
||||
Reference in New Issue
Block a user