No description
- PowerShell 100%
| tests | ||
| .gitignore | ||
| AGENTS.md | ||
| Import-PublicMetaDb.ps1 | ||
| PublicMetaDbImporter.psm1 | ||
| README.md | ||
PublicMetaDB Importer
Import-PublicMetaDb.ps1 imports watch history from Trakt and Simkl backups into PMDB.
It is designed for reliability first:
- preserves each distinct play instead of collapsing rewatches
- preserves known
watched_attimestamps - sends
watched_at: nullonly when the source is watched but the date is truly missing - fetches existing PMDB watch history first so reruns are idempotent
- uses PMDB retry metadata on
429responses - defaults to reactive pacing with no fixed client throttle
Supported Inputs
- Trakt
watched-history.json - Simkl backup JSON with top-level
movies,shows, andanime
Usage
Pass the API key directly:
powershell -ExecutionPolicy Bypass -File .\Import-PublicMetaDb.ps1 `
-InputPath .\TraktBackup\watched-history.json `
-ApiKey 'pm-YourApiKeyHere'
Let the importer auto-detect Simkl:
powershell -ExecutionPolicy Bypass -File .\Import-PublicMetaDb.ps1 `
-InputPath .\SimklBackup\SimklBackup.json `
-ApiKey 'pm-YourApiKeyHere'
Use the environment variable:
$env:PMDB_API_KEY = 'pm-YourApiKeyHere'
powershell -ExecutionPolicy Bypass -File .\Import-PublicMetaDb.ps1 `
-InputPath .\TraktBackup\watched-history.json
Dry run:
powershell -ExecutionPolicy Bypass -File .\Import-PublicMetaDb.ps1 `
-InputPath .\SimklBackup\SimklBackup.json `
-ApiKey 'pm-YourApiKeyHere' `
-DryRun
Explicit source and client throttle:
powershell -ExecutionPolicy Bypass -File .\Import-PublicMetaDb.ps1 `
-InputPath .\SimklBackup\SimklBackup.json `
-Source simkl `
-ApiKey 'pm-YourApiKeyHere' `
-RequestsPerSecond 5
Arguments
-InputPathrequired path to the source JSON file-Sourceauto,trakt, orsimkl; defaults toauto-ApiKeyPMDB API key; falls back toPMDB_API_KEY-BaseUrlPMDB base URL, defaults tohttps://publicmetadb.com-ReportPathoutput JSON report, defaults to.\import-report.json-MaxRetriestransient retry count, defaults to5-RequestsPerSecondoptional client-side pacing ceiling; defaults to0for reactive mode only-DryRuncomputes the import plan without posting new plays
Behavior
- Trakt:
- imports
action: "watch"andaction: "scrobble"rows - movies map to PMDB
media_type: "movie" - episodes map to PMDB
media_type: "tv"using the show TMDB ID plus season and episode
- imports
- Simkl:
- movies import one play from
last_watched_at - shows and anime import one play per
seasons[].episodes[]entry - anime is imported as PMDB
media_type: "tv" - season
0specials are supported - unwatched entries are skipped
- movies import one play from
- The importer never uses PMDB's legacy
?dedupe=truemode. - Id resolution order is fixed to verified PMDB-compatible fallbacks:
- Trakt movies: direct TMDB, then IMDb, then Trakt
- Trakt series: direct TMDB, then IMDb, then TVDB, then Trakt
- Simkl movies: direct TMDB, then IMDb, then TVDB
- Simkl series: direct TMDB, then IMDb, then TVDB
- Simkl anime: direct TMDB, then MAL, then AniList, then IMDb, then TVDB
- Simkl slug-style IDs such as
trakttvslug,traktmslug, andslugare intentionally not used for PMDB fallback lookup. - PMDB lookup
404responses are treated as candidate misses so the importer can continue to the next fallback.
Output
The report JSON includes:
- source format and source file
- dry-run status
- summary counts
- skipped rows
- parse failures
- unresolved ID failures
- PMDB API failures
Exit codes:
0when every supported row was already present or imported successfully1when any supported row failed, could not be resolved, or the run failed fatally
Tests
Run the automated test suite from the repo root:
Invoke-Pester -Path .\tests -EnableExit
The tests cover:
- source detection
- Trakt and Simkl normalization
- season
0specials handling - verified fallback ID ordering
- PMDB lookup
404miss handling - dry-run behavior
- exact-play idempotency
- explicit source mismatch failures
Invoke-Pester exits with 0 when the suite passes and a non-zero code when a test fails.