发布咸鱼喵喵截图辅助工具公开版

This commit is contained in:
2026-10-03 01:16:35 +08:00
commit 178e1d8714
26 changed files with 5694 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
// 发布版专用。全文索引只存在于内存,不读写台词文件。
class StoryCache {
constructor(cdp, ops, triggers, { retryMs = 3000, maxAttempts = 4, now = Date.now } = {}) {
Object.assign(this, { cdp, ops, triggers, retryMs, maxAttempts, now });
this.revision = 0;
this.reset();
}
key() {
return this.cdp.ws?.readyState === 1 && this.cdp.sessionId
? `${this.cdp.port}:${this.cdp.generation}:${this.cdp.sessionId}` : null;
}
reset(key = null) {
this.connection = key;
this.index = null;
this.pending = null;
this.attempts = 0;
this.nextTryAt = 0;
this.error = '';
this.at = 0;
++this.revision;
}
sync() {
const key = this.key();
if (key !== this.connection) this.reset(key);
return key;
}
status() {
const key = this.sync();
const loaded = !!this.index;
return {
state: !key ? 'disconnected' : loaded ? 'ready' : this.pending ? 'loading'
: this.error ? (this.attempts >= this.maxAttempts ? 'error' : 'retrying') : 'waiting',
loaded, revision: this.revision, connection: key, error: this.error,
attempts: this.attempts, at: this.at,
count: loaded ? Object.keys(this.index).length : 0,
triggersWithLine: loaded ? this.triggers.filter(t => this.index[String(t.storyId)]).length : 0,
};
}
get(id) { this.sync(); return this.index?.[String(id)] || null; }
async ensure({ force = false } = {}) {
let key = this.sync();
if (!key) {
if (!(await this.cdp.isAlive())) return null;
try { await this.cdp.connect(); } catch { this.sync(); return null; }
key = this.sync();
}
if (!key) return null;
if (this.pending) return this.pending;
if (force) { this.reset(key); }
else if (this.index || this.attempts >= this.maxAttempts || this.now() < this.nextTryAt) return this.index;
const revision = this.revision;
++this.attempts;
const task = (async () => {
try {
const result = await this.cdp.evalJson(this.ops.readStoryIndex());
if (this.key() !== key || this.revision !== revision) return null;
if (!result?.ok || !result.index || !Object.keys(result.index).length) {
throw new Error(result?.error || '故事表尚未就绪或没有可读台词');
}
this.index = result.index;
this.error = '';
this.at = this.now();
++this.revision;
return this.index;
} catch (e) {
if (this.key() !== key || this.revision !== revision) return null;
this.error = String(e.message || e);
this.nextTryAt = this.now() + this.retryMs;
++this.revision;
return null;
}
})();
this.pending = task;
try { return await task; }
finally { if (this.pending === task) this.pending = null; }
}
}
module.exports = { StoryCache };