Clarify group-chat scraping and refresh puppet URLs via the core

This commit is contained in:
Fisto
2026-09-16 23:57:47 +02:00
parent 6c500f0cc5
commit 031da7d8b4
4 changed files with 94 additions and 41 deletions
+69 -35
View File
@@ -425,63 +425,97 @@ export class MediaService {
const meta = this.engine.get(scrapeId);
const item = this.getMediaItem(scrapeId, itemId);
if (!meta || !item) return null;
if (meta.backend !== "slopbot" || !meta.guildId || !this.bot) return null;
return this.refreshUrls(meta.id, meta.channelId, item);
return this.refreshUrls(meta, item);
}
/** Re-fetch the source message and update expired URLs. Returns the fresh playable URL. */
private async refreshUrls(
scrapeId: string,
channelId: string,
item: MediaRow
): Promise<string | null> {
/**
* Re-fetch the source message and update expired URLs. Returns the fresh playable URL.
* Slopbot scrapes use the bot REST; DM and group-DM scrapes go through the core bridge.
*/
private async refreshUrls(meta: ScrapeMeta, item: MediaRow): Promise<string | null> {
try {
const store = new ScrapeStore(scrapeDir(this.rootDir, scrapeId));
const store = new ScrapeStore(scrapeDir(this.rootDir, meta.id));
let messageId: string | null = null;
try {
messageId = store.sourceMessageId(item.id);
} finally {
store.close();
}
if (!messageId || !this.bot) return null;
const channel = await this.bot.channels.fetch(channelId);
if (!channel?.isTextBased()) return null;
const message = await channel.messages.fetch(messageId);
if (!messageId) return null;
const path = (url: string) => url.split("?")[0];
const attachment = [...message.attachments.values()].find(
candidate => path(candidate.url) === path(item.url)
);
if (attachment) {
const update = new ScrapeStore(scrapeDir(this.rootDir, scrapeId));
const saveAndReturn = (update: { url?: string; playUrl?: string | null }, fresh: string) => {
const writer = new ScrapeStore(scrapeDir(this.rootDir, meta.id));
try {
update.updateUrls(item.id, { url: attachment.url });
writer.updateUrls(item.id, update);
} finally {
update.close();
writer.close();
}
return fresh;
};
if (this.bot && meta.guildId && meta.backend === "slopbot") {
const channel = await this.bot.channels.fetch(meta.channelId);
if (channel?.isTextBased()) {
const message = await channel.messages.fetch(messageId);
const attachment = [...message.attachments.values()].find(
candidate => path(candidate.url) === path(item.url)
);
if (attachment) return saveAndReturn({ url: attachment.url }, attachment.url);
const embed = message.embeds.find(
candidate =>
(item.play_url &&
candidate.video?.url &&
path(candidate.video.url) === path(item.play_url)) ||
(candidate.video?.url && path(candidate.url ?? "") === path(item.url))
);
if (embed?.video?.url) {
return saveAndReturn(
{ playUrl: embed.video.url, url: embed.url ?? item.url },
embed.video.url
);
}
}
return attachment.url;
}
const embed = message.embeds.find(
candidate =>
(item.play_url && candidate.video?.url && path(candidate.video.url) === path(item.play_url)) ||
(candidate.video?.url && path(candidate.url ?? "") === path(item.url))
);
if (embed?.video?.url) {
const update = new ScrapeStore(scrapeDir(this.rootDir, scrapeId));
try {
update.updateUrls(item.id, { playUrl: embed.video.url, url: embed.url ?? item.url });
} finally {
update.close();
// The puppet path: the newest message below id+1 is exactly the target message.
const core = this.deps.getCore();
if (core && this.deps.isCoreConnected()) {
const result = (await core.fetchMessages(meta.channelId, 1, {
before: (BigInt(messageId) + 1n).toString()
})) as { messages?: Array<Record<string, any>> };
const message =
result?.messages?.find(candidate => candidate?.id === messageId) ??
result?.messages?.[0];
if (message) {
const attachment = (message.attachments ?? []).find(
(candidate: any) => candidate?.url && path(candidate.url) === path(item.url)
);
if (attachment?.url) return saveAndReturn({ url: attachment.url }, attachment.url);
const embed = (message.embeds ?? []).find(
(candidate: any) =>
(item.play_url &&
candidate?.videoUrl &&
path(candidate.videoUrl) === path(item.play_url)) ||
(candidate?.videoUrl && path(candidate.url ?? "") === path(item.url))
);
if (embed?.videoUrl) {
return saveAndReturn(
{ playUrl: embed.videoUrl, url: embed.url ?? item.url },
embed.videoUrl
);
}
}
return embed.video.url;
}
return null;
} catch (error) {
this.deps.log?.(`refresh failed for ${scrapeId}:${item.id}: ${String(error)}`);
this.deps.log?.(`refresh failed for ${meta.id}:${item.id}: ${String(error)}`);
return null;
}
}