feat(library): generic per-type sync engine + resolve
This commit is contained in:
parent
c14da19c47
commit
278f009a9b
5 changed files with 571 additions and 13 deletions
|
|
@ -4,6 +4,7 @@ import { syncFolder, withRateLimitRetry, TmdbRateLimitError, type SyncDeps, type
|
|||
import { fetchDetail, searchTitle, type HttpJsonFn } from 'packages/obsidian/src/watchlist/tmdb';
|
||||
import { obsidianFetch } from 'packages/obsidian/src/utils/Utils';
|
||||
import { parseNote, noteTmdbRef, stripQuotes } from 'packages/obsidian/src/watchlist/parse';
|
||||
import { patchFrontmatter } from 'packages/obsidian/src/watchlist/patchFrontmatter';
|
||||
import { resolveNote } from 'packages/obsidian/src/watchlist/resolve';
|
||||
|
||||
export interface ResolveReport {
|
||||
|
|
@ -13,18 +14,6 @@ export interface ResolveReport {
|
|||
errors: { path: string; error: string }[];
|
||||
}
|
||||
|
||||
function patchFrontmatter(content: string, tmdbId: string, mediaType: string): string {
|
||||
const insert = `tmdb_id: ${tmdbId}\nmedia_type: ${mediaType}`;
|
||||
const fmMatch = /^---\n([\s\S]*?)\n---/.exec(content);
|
||||
if (fmMatch) {
|
||||
const inner = fmMatch[1];
|
||||
const typeLine = /^type:.*$/m.exec(inner);
|
||||
const newInner = typeLine ? inner.slice(0, typeLine.index + typeLine[0].length) + '\n' + insert + inner.slice(typeLine.index + typeLine[0].length) : insert + '\n' + inner;
|
||||
return content.slice(0, fmMatch.index) + '---\n' + newInner + '\n---' + content.slice(fmMatch.index + fmMatch[0].length);
|
||||
}
|
||||
return `---\ntype: watchlist_item\n${insert}\n---\n\n` + content;
|
||||
}
|
||||
|
||||
export function shouldNotifySync(quiet: boolean, written: number, errorCount: number): boolean {
|
||||
return !quiet || written > 0 || errorCount > 0;
|
||||
}
|
||||
|
|
@ -146,7 +135,7 @@ export class WatchlistController {
|
|||
report.resolved++;
|
||||
const mediaType = result.isMovie ? 'Movie' : 'TV Series';
|
||||
deps.log(`${dryRun ? '[dry] ' : ''}resolved ${note.path} -> tmdb_id ${result.tmdbId} (${result.matchedTitle})`);
|
||||
if (!dryRun) await deps.writeNote(note.path, patchFrontmatter(content, result.tmdbId, mediaType));
|
||||
if (!dryRun) await deps.writeNote(note.path, patchFrontmatter(content, { tmdb_id: result.tmdbId, media_type: mediaType }, { defaultType: 'watchlist_item' }));
|
||||
}
|
||||
await deps.sleep(250);
|
||||
} catch (e) {
|
||||
|
|
|
|||
24
packages/obsidian/src/watchlist/patchFrontmatter.ts
Normal file
24
packages/obsidian/src/watchlist/patchFrontmatter.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* Insert frontmatter key: value patches into note content, right after the `type:` line
|
||||
* when frontmatter exists (or prepended before the rest of the frontmatter when there's
|
||||
* no `type:` line). When the note has no frontmatter block at all, a new one is created,
|
||||
* optionally seeded with `defaultType`.
|
||||
*
|
||||
* Shared by watchlist's resolveMissingIds and the library resolve engine.
|
||||
*/
|
||||
export function patchFrontmatter(content: string, patches: Record<string, string>, opts: { defaultType?: string } = {}): string {
|
||||
const insert = Object.entries(patches)
|
||||
.map(([k, v]) => `${k}: ${v}`)
|
||||
.join('\n');
|
||||
const fmMatch = /^---\n([\s\S]*?)\n---/.exec(content);
|
||||
if (fmMatch) {
|
||||
const inner = fmMatch[1];
|
||||
const typeLine = /^type:.*$/m.exec(inner);
|
||||
const newInner = typeLine
|
||||
? inner.slice(0, typeLine.index + typeLine[0].length) + '\n' + insert + inner.slice(typeLine.index + typeLine[0].length)
|
||||
: insert + '\n' + inner;
|
||||
return content.slice(0, fmMatch.index) + '---\n' + newInner + '\n---' + content.slice(fmMatch.index + fmMatch[0].length);
|
||||
}
|
||||
const typeLine = opts.defaultType ? `type: ${opts.defaultType}\n` : '';
|
||||
return `---\n${typeLine}${insert}\n---\n\n` + content;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue