mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-28 06:22:45 -08:00
Fix anilist updater import
This commit is contained in:
@@ -1,76 +0,0 @@
|
|||||||
import * as childProcess from "child_process";
|
|
||||||
|
|
||||||
const SECRET_COMMAND_PATTERN = /^\((.*)\)$/s;
|
|
||||||
const COMMAND_CACHE = new Map<string, string>();
|
|
||||||
const COMMAND_PENDING = new Map<string, Promise<string>>();
|
|
||||||
|
|
||||||
function executeCommand(command: string): Promise<string> {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
childProcess.exec(command, { timeout: 10_000 }, (err, stdout) => {
|
|
||||||
if (err) {
|
|
||||||
reject(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
resolve(stdout);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function clearAnilistClientSecretCache(): void {
|
|
||||||
COMMAND_CACHE.clear();
|
|
||||||
COMMAND_PENDING.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
function resolveCommand(rawSecret: string): string | null {
|
|
||||||
const commandMatch = rawSecret.match(SECRET_COMMAND_PATTERN);
|
|
||||||
if (!commandMatch || commandMatch[1] === undefined) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = commandMatch[1].trim();
|
|
||||||
return command.length > 0 ? command : null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function resolveAnilistClientSecret(rawSecret: string): Promise<string> {
|
|
||||||
const trimmedSecret = rawSecret.trim();
|
|
||||||
if (trimmedSecret.length === 0) {
|
|
||||||
throw new Error("cannot authenticate without client secret");
|
|
||||||
}
|
|
||||||
|
|
||||||
const command = resolveCommand(trimmedSecret);
|
|
||||||
if (!command) {
|
|
||||||
return trimmedSecret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cachedValue = COMMAND_CACHE.get(trimmedSecret);
|
|
||||||
if (cachedValue !== undefined) {
|
|
||||||
return cachedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pending = COMMAND_PENDING.get(trimmedSecret);
|
|
||||||
if (pending !== undefined) {
|
|
||||||
return pending;
|
|
||||||
}
|
|
||||||
|
|
||||||
const promise = executeCommand(command)
|
|
||||||
.then((stdout) => {
|
|
||||||
const trimmed = stdout.trim();
|
|
||||||
if (!trimmed) {
|
|
||||||
throw new Error("secret command returned empty value");
|
|
||||||
}
|
|
||||||
COMMAND_CACHE.set(trimmedSecret, trimmed);
|
|
||||||
COMMAND_PENDING.delete(trimmedSecret);
|
|
||||||
return trimmed;
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
COMMAND_PENDING.delete(trimmedSecret);
|
|
||||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
||||||
if (errorMessage === "secret command returned empty value") {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
throw new Error(`secret command failed: ${errorMessage}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
COMMAND_PENDING.set(trimmedSecret, promise);
|
|
||||||
return promise;
|
|
||||||
}
|
|
||||||
16
src/main.ts
16
src/main.ts
@@ -209,6 +209,7 @@ const ANILIST_DEVELOPER_SETTINGS_URL = "https://anilist.co/settings/developer";
|
|||||||
const ANILIST_UPDATE_MIN_WATCH_RATIO = 0.85;
|
const ANILIST_UPDATE_MIN_WATCH_RATIO = 0.85;
|
||||||
const ANILIST_UPDATE_MIN_WATCH_SECONDS = 10 * 60;
|
const ANILIST_UPDATE_MIN_WATCH_SECONDS = 10 * 60;
|
||||||
const ANILIST_DURATION_RETRY_INTERVAL_MS = 15_000;
|
const ANILIST_DURATION_RETRY_INTERVAL_MS = 15_000;
|
||||||
|
const ANILIST_MAX_ATTEMPTED_UPDATE_KEYS = 1000;
|
||||||
|
|
||||||
let anilistCurrentMediaKey: string | null = null;
|
let anilistCurrentMediaKey: string | null = null;
|
||||||
let anilistCurrentMediaDurationSec: number | null = null;
|
let anilistCurrentMediaDurationSec: number | null = null;
|
||||||
@@ -864,6 +865,17 @@ function buildAnilistAttemptKey(mediaKey: string, episode: number): string {
|
|||||||
return `${mediaKey}::${episode}`;
|
return `${mediaKey}::${episode}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function rememberAnilistAttemptedUpdateKey(key: string): void {
|
||||||
|
anilistAttemptedUpdateKeys.add(key);
|
||||||
|
if (anilistAttemptedUpdateKeys.size <= ANILIST_MAX_ATTEMPTED_UPDATE_KEYS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const oldestKey = anilistAttemptedUpdateKeys.values().next().value;
|
||||||
|
if (typeof oldestKey === "string") {
|
||||||
|
anilistAttemptedUpdateKeys.delete(oldestKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function maybeRunAnilistPostWatchUpdate(): Promise<void> {
|
async function maybeRunAnilistPostWatchUpdate(): Promise<void> {
|
||||||
if (anilistUpdateInFlight) {
|
if (anilistUpdateInFlight) {
|
||||||
return;
|
return;
|
||||||
@@ -921,13 +933,13 @@ async function maybeRunAnilistPostWatchUpdate(): Promise<void> {
|
|||||||
guess.episode,
|
guess.episode,
|
||||||
);
|
);
|
||||||
if (result.status === "updated") {
|
if (result.status === "updated") {
|
||||||
anilistAttemptedUpdateKeys.add(attemptKey);
|
rememberAnilistAttemptedUpdateKey(attemptKey);
|
||||||
showMpvOsd(result.message);
|
showMpvOsd(result.message);
|
||||||
logger.info(result.message);
|
logger.info(result.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (result.status === "skipped") {
|
if (result.status === "skipped") {
|
||||||
anilistAttemptedUpdateKeys.add(attemptKey);
|
rememberAnilistAttemptedUpdateKey(attemptKey);
|
||||||
logger.info(result.message);
|
logger.info(result.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user