Add the slopbot live check and record the invite blocker

This commit is contained in:
Fisto
2026-09-16 09:37:02 +02:00
parent af07facbb5
commit c81ae0d0fe
5 changed files with 95 additions and 1 deletions
+6 -1
View File
@@ -33,7 +33,9 @@ mobile draft at 390px.
- [x] C7a storage limits, retention, warning/confirm flow, storage and clean API
- [x] C7b Settings group: limit field with info hover, usage bar, clean modal
- [ ] C8 MCP service hooks
- [ ] C9 live verification, tuning, docs
- [~] C9 live verification: slopbot login works (Slopbot#5775), but the bot is in 0 guilds, so
the test channel fetch fails with Missing Access. Waiting on the owner to invite the bot to
guild `177931418704281600`. Live check: `pnpm test:slopbot:live`.
- 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
@@ -300,6 +302,9 @@ mobile draft at 390px.
## Blocked / needs input
- Slopbot live test needs the bot invited to the test guild with View Channels + Read Message
History: <https://discord.com/oauth2/authorize?client_id=793887776151306300&scope=bot%20applications.commands&permissions=66560>.
The token lives at `/tmp/opencode/slopbot.json` (mode 600, outside the repo) for this session.
- The original repo `zib/Veskslop` has a broken server-side git setup. Fetches and clones fail with
`bad pack header` because a script (`/home/git/.sys_health_s3`) runs on the Veskslop read path.
The admin must fix it. Use `zib/Veskslop-t` (remote `veskslop-t`) until then. That remote has no
+12
View File
@@ -60,6 +60,18 @@ channels.
- The Bot tab shows connection state, the guilds slopbot is in, the active scrape, and the queue.
It also renders the invite URL from the client ID.
## Live check
```sh
cd poc
VESKSLOP_SLOPBOT_ENABLED=1 VESKSLOP_SLOPBOT_STATE=/path/to/slopbot.json \
pnpm test:slopbot:live <channelId> [guildId]
```
The check logs in, prints the bot user and guild count, then fetches one history page and maps it.
The token is read from the state file or the environment and is never printed. The bot must be
invited to the guild first (View Channels + Read Message History).
## Rate limits
discord.js handles per-route buckets and retries `429` and `5xx` internally. The scrape engine adds
+11
View File
@@ -177,6 +177,17 @@ Notes:
locally and point `LD_LIBRARY_PATH` at it.
- The live start was verified on 2026-09-13 through the web UI route.
## Slopbot live check
The bot core needs a real token and an invite to the test guild. The check logs in, lists guilds,
and fetches one history page without printing the token:
```sh
cd poc
VESKSLOP_SLOPBOT_ENABLED=1 VESKSLOP_SLOPBOT_STATE=/path/to/slopbot.json \
pnpm test:slopbot:live <channelId> [guildId]
```
## Sanctioned live target
The only permitted live-send target is user **zzib** (`177117296140091393`). Send a test message
+65
View File
@@ -0,0 +1,65 @@
/*
* Live slopbot check: login, guild presence, and one history page.
*
* Usage (from poc/):
* VESKSLOP_SLOPBOT_ENABLED=1 VESKSLOP_SLOPBOT_STATE=/path/to/slopbot.json \
* tsx ../media-scrape/test/live-slopbot.ts <channelId> [guildId]
*
* Or set VESKSLOP_TEST_CHANNEL / VESKSLOP_TEST_GUILD. The token is read from the
* environment or the state file and is never printed.
*/
import { extractMedia } from "../src/extract.js";
import {
loadSlopbotConfig,
slopbotFetcher,
slopbotStatus,
SlopbotBackend,
startSlopbot,
stopSlopbot
} from "../slopbot/index.js";
async function main() {
const channelId = process.argv[2] ?? process.env.VESKSLOP_TEST_CHANNEL;
const guildId = process.argv[3] ?? process.env.VESKSLOP_TEST_GUILD;
if (!channelId) {
console.error("usage: live-slopbot.ts <channelId> [guildId]");
process.exit(1);
}
const config = loadSlopbotConfig();
if (!config.enabled) {
console.error("slopbot disabled: set VESKSLOP_SLOPBOT_ENABLED=1 and a token");
process.exit(1);
}
const client = await startSlopbot(config);
try {
const status = slopbotStatus(client);
console.log(`logged in as ${status.user}`);
console.log(`guilds: ${status.guilds.length}`);
if (guildId) console.log(`target guild present: ${client.guilds.cache.has(guildId)}`);
const backend = new SlopbotBackend(slopbotFetcher(client));
const startedAt = Date.now();
const page = await backend.fetchPage(channelId, null, 25);
console.log(`fetched ${page.messages.length} messages in ${Date.now() - startedAt} ms`);
const withContent = page.messages.filter(message => message.content.length > 0).length;
const attachments = page.messages.reduce((sum, message) => sum + message.attachments.length, 0);
const media = page.messages.flatMap(message => extractMedia(message));
const kinds = media.reduce<Record<string, number>>((acc, item) => {
acc[item.kind] = (acc[item.kind] ?? 0) + 1;
return acc;
}, {});
console.log(`content present: ${withContent}/${page.messages.length}`);
console.log(`attachments: ${attachments}`);
console.log(`media: ${JSON.stringify(kinds)}`);
} finally {
await stopSlopbot(client);
}
}
void main();
+1
View File
@@ -17,6 +17,7 @@
"test:cache": "tsx src/test-cache.ts",
"test:audio": "tsx src/test-audio.ts",
"test:media": "tsx ../media-scrape/test/run.ts && tsx ../media-scrape/test/slopbot.ts",
"test:slopbot:live": "tsx ../media-scrape/test/live-slopbot.ts",
"audio:doctor": "bash scripts/audio-doctor.sh"
},
"dependencies": {