mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-08-04 07:21:32 -07:00
feat(anime): add anime browser powered by Aniyomi extensions
- Add `subminer anime` / `--anime` and a tray entry to open a browser that searches installed Aniyomi extension sources, shows cover art and episodes, and plays into mpv with overlay/mining attached - Add an Extensions tab to add repos and install/update/remove sources, and per-source settings for sources needing config - Support searching all sources at once with streaming, per-source results and status - Prefer Japanese audio/subtitle tracks from the source and keep the primary subtitle slot reserved for Japanese - Fix window/tray/Dock handling so the browser and mpv can be switched between without quitting the app or losing the Dock icon - Add anime.repos, anime.extensionsDir, anime.preferredQuality config keys (no bundled repos or discovery)
This commit is contained in:
@@ -3,6 +3,7 @@ import * as path from 'node:path';
|
||||
import { MPV_LAUNCH_MODE_VALUES, parseMpvLaunchMode } from '../../shared/mpv-launch-mode';
|
||||
import { ResolveContext } from './context';
|
||||
import { asBoolean, asNumber, asString, isObject } from './shared';
|
||||
import { isValidRepoUrl } from '../../anime-bridge/extension-repo';
|
||||
|
||||
function normalizeExternalProfilePath(value: string): string {
|
||||
const trimmed = value.trim();
|
||||
@@ -343,6 +344,51 @@ export function applyIntegrationConfig(context: ResolveContext): void {
|
||||
warn('mpv', src.mpv, resolved.mpv, 'Expected object.');
|
||||
}
|
||||
|
||||
if (isObject(src.anime)) {
|
||||
const extensionsDir = asString(src.anime.extensionsDir);
|
||||
if (extensionsDir !== undefined) {
|
||||
resolved.anime.extensionsDir = normalizeExternalProfilePath(extensionsDir);
|
||||
} else if (src.anime.extensionsDir !== undefined) {
|
||||
warn(
|
||||
'anime.extensionsDir',
|
||||
src.anime.extensionsDir,
|
||||
resolved.anime.extensionsDir,
|
||||
'Expected string.',
|
||||
);
|
||||
}
|
||||
|
||||
const preferredQuality = asString(src.anime.preferredQuality);
|
||||
if (preferredQuality !== undefined) {
|
||||
resolved.anime.preferredQuality = preferredQuality.trim();
|
||||
} else if (src.anime.preferredQuality !== undefined) {
|
||||
warn(
|
||||
'anime.preferredQuality',
|
||||
src.anime.preferredQuality,
|
||||
resolved.anime.preferredQuality,
|
||||
'Expected string.',
|
||||
);
|
||||
}
|
||||
|
||||
if (Array.isArray(src.anime.repos)) {
|
||||
const repos: string[] = [];
|
||||
for (const entry of src.anime.repos) {
|
||||
const url = asString(entry)?.trim();
|
||||
// Rejecting here rather than at fetch time keeps a bad entry from
|
||||
// silently doing nothing, and blocks plain http downgrades.
|
||||
if (url !== undefined && isValidRepoUrl(url)) {
|
||||
if (!repos.includes(url)) repos.push(url);
|
||||
} else {
|
||||
warn('anime.repos[]', entry, null, 'Expected an https URL to a .json index file.');
|
||||
}
|
||||
}
|
||||
resolved.anime.repos = repos;
|
||||
} else if (src.anime.repos !== undefined) {
|
||||
warn('anime.repos', src.anime.repos, resolved.anime.repos, 'Expected array of strings.');
|
||||
}
|
||||
} else if (src.anime !== undefined) {
|
||||
warn('anime', src.anime, resolved.anime, 'Expected object.');
|
||||
}
|
||||
|
||||
if (isObject(src.jellyfin)) {
|
||||
const enabled = asBoolean(src.jellyfin.enabled);
|
||||
if (enabled !== undefined) {
|
||||
|
||||
Reference in New Issue
Block a user