Live-verify the puppet DM path and expose the backend choice

This commit is contained in:
Fisto
2026-09-16 10:53:51 +02:00
parent 9113bafe28
commit b94031d816
6 changed files with 45 additions and 12 deletions
+8 -4
View File
@@ -38,10 +38,14 @@ mobile draft at 390px.
by the Media tab. Live run 2026-09-16: scrape `...-20260916083401` fetched the 784 KB
attachment; storage counted actual bytes.
- [~] C9 live verification. Slopbot path verified live on 2026-09-16: login Slopbot#5775, guild
`177931418704281600`, test channel `1549681689222053988`. Links scrape `...-20260916075150`:
done, 1 page, 17 messages, 4 images + 13 videos, 0 errors. Download scrape `...-20260916083401`:
done, 1 file. Still owed: preview caching (C11), the puppet `message.fetch` field check, a real
429 observation, and pacing tuning.
`177931418704281600`. Test channel links scrape: 17 messages, 4 images + 13 videos, 0 errors;
download scrape fetched the 784 KB attachment. Large channel `gernal_chut`: 11 pages, 1088
messages, 96 images + 1 GIF + 203 videos, 0 errors (no 429 at the current pacing). Puppet path
verified live on a group DM (`zıbb & fred`) and a 1:1 DM: backend `puppet`, done, 0 errors.
The puppet field check is done too: the group DM returned attachments plus mapped embeds
(YouTube, Instagram), and the large slopbot channel produced YouTube, Gfycat, Imgur, Steam,
and Twitch embeds alongside attachments. Still owed: preview caching (C11) and a stress walk
on the second guild (`559346566754729995`, channel `559346566754729997`).
- Flextalk voice profile, end to end. The profile window is a movable panel that recenters on each
open; it carries the character sliders with engine defaults and +/-2 snapping, five named
presets, radio-kit effects (high-pass 40-400 Hz, echo 0-100, word mode with a gap in ms), and
+7 -4
View File
@@ -2,10 +2,13 @@
Status: design approved 2026-09-16. The engine, the slopbot backend, the `scrape media` command,
the `/api/media/*` routes, storage limits with retention, the Settings group, the MCP tools, and
the byte downloader are implemented (C3-C8, C10). The Media and Bot tabs are C6. Live-verified on
the test channel: links mode produced 17 messages (4 images, 13 videos) with no errors, and
download mode fetched the attachment (784 KB) and served it locally. Remaining: preview caching
(C11), the puppet `message.fetch` field check, and a 429 observation. Checkpoints live in
the byte downloader are implemented (C3-C8, C10). The Media and Bot tabs are C6. Live-verified:
- slopbot on the test channel: 17 messages (4 images, 13 videos), 0 errors.
- slopbot on a larger channel: 11 pages, 1088 messages (96 images, 1 GIF, 203 videos), 0 errors.
- puppet on a group DM and a 1:1 DM: done, 0 errors, backend `puppet`.
Remaining: preview caching (C11) and a 429 observation on a very large walk. Checkpoints live in
[CURRENT.md](../CURRENT.md).
The media archive saves the media history of a channel. A trusted user runs `scrape media` in the
+1 -1
View File
@@ -254,7 +254,7 @@ replaceable.
| GET | `/api/media/scrapes` | none | Every scrape with state and counters |
| GET | `/api/media/status` | none | Slopbot connection state and the scrape list |
| GET | `/api/media/storage` | none | Usage against the limit, per-kind sizes, `nearLimit`; marks old scrapes when over |
| POST | `/api/media/scrape` | `channelId`, `guildId?`, `mode?`, `confirm?` | Start a media scrape. Near the limit: `409` with code `MEDIA_LIMIT` unless `confirm: true` |
| POST | `/api/media/scrape` | `channelId`, `guildId?`, `mode?`, `backend?`, `confirm?` | Start a media scrape. `backend` is `auto` (default), `slopbot`, or `puppet`. Near the limit: `409` with code `MEDIA_LIMIT` unless `confirm: true` |
| POST | `/api/media/scrape/stop` | `id` | Stop a media scrape |
| POST | `/api/media/clean` | `ids?` | Delete the given scrapes, or every scrape when `ids` is absent |
| GET | `/api/logs` | `limit` | The persistent action log |
+19
View File
@@ -95,6 +95,25 @@
});
}
}
// DMs and group DMs: the bot cannot see them, so they always use the puppet.
try {
const dms = await window.VK.api.get("/api/dms?limit=50");
for (const dm of dms ?? []) {
const names = (dm.recipients ?? [])
.map(recipient => recipient.username)
.filter(Boolean)
.join(", ");
state.channels.push({
id: dm.id,
guildId: null,
label: `${dm.name || names || "DM"} (${dm.type === 3 ? "group DM" : "DM"})`
});
}
} catch {
// no cached DMs yet
}
state.loadedChannels = true;
} catch {
state.channels = [];
+6 -2
View File
@@ -770,11 +770,15 @@ function buildServer(): McpServer {
.enum(["links", "download"])
.optional()
.describe("links indexes URLs (default); download fetches attachment bytes"),
backend: z
.enum(["auto", "slopbot", "puppet"])
.optional()
.describe("auto (default) picks slopbot for its guilds, the client otherwise"),
confirm: z.boolean().optional().describe("Accept the near-limit warning")
}
},
async ({ channelId, guildId, mode, confirm }) =>
jsonText(await media.startScrape({ channelId, guildId: guildId ?? null, mode, confirm }))
async ({ channelId, guildId, mode, backend, confirm }) =>
jsonText(await media.startScrape({ channelId, guildId: guildId ?? null, mode, backend, confirm }))
);
server.registerTool(
+4 -1
View File
@@ -802,8 +802,11 @@ export function startWebUi(deps: WebUiDeps): WebUiHandle {
const mode = req.body?.mode === "download" ? "download" : "links";
const guildId = req.body?.guildId ? String(req.body.guildId) : null;
const confirm = req.body?.confirm === true;
const requested = String(req.body?.backend ?? "auto");
const backend =
requested === "slopbot" || requested === "puppet" ? requested : "auto";
const scrape = await deps.media.startScrape({ channelId, guildId, mode, confirm });
const scrape = await deps.media.startScrape({ channelId, guildId, mode, confirm, backend });
deps.getPuppet()?.appendAction({
type: "media",
action: "scrape",