Compare commits

...

155 Commits

Author SHA1 Message Date
Miguel Palhas bce3d3823d feat(api): move title files on root change
Changing a movie's or series' root previously rewrote root_id and left
the files behind, so the §7.4 layout stopped describing the disk and
the root's policy applied to a library the files were not in. Series
had no root control at all.

All roots share one ZFS dataset, so the move is a rename of the title
folder into the new root, never a copy — hardlinks and the seeding
torrent survive it (§7.3). Disk first, row second: a destination that
already holds the folder is a 409, a failed rename leaves the row
unchanged, and a title with nothing on disk moves with no filesystem
work. media_files rows are rewritten in the same transaction as the
root_id, and a successful move triggers the §7.5 Jellyfin refresh.

Issue #228

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-25 09:55:18 +01:00
Miguel Palhas c64c572781 refactor(arr): give arr-api its own jellyfin client
arr-daemon depends on arr-api, so a handler in arr-api can never
reach the daemon's private JellyfinClient. Move it into arr-api and
attach an instance to AppState, so a manual subtitle write can ask
for the same refresh import already does (#195).
2026-08-25 09:47:53 +01:00
Miguel Palhas 8c3e1c4a92 Merge milestone 'Size bands and waivers'
ci / web (push) Successful in 45s
e2e / e2e (push) Successful in 1m30s
ci / rust (push) Successful in 1m38s
A size band is now a rate: floor and target scale by the series'
minutes per episode against a 45-minute reference, so a short-form
show is no longer judged against an hour of video. Shipped band
values are unchanged — the reference runtime is chosen so they keep
their meaning. A missing runtime scales by one, and movies are never
scaled.

A size rejection can also be waived. The override relaxes the floor
for one title into a waiver rather than lifting it, so the release
stays out of automatic grabbing and imports on the record (§5.7).

The runtime migration is numbered 0026 to leave 0024 and 0025 to the
concurrent subtitles milestone; two files claiming one version do not
conflict in git and would have reached main unnoticed.

Closes #208, #209, #210
2026-08-24 22:51:55 +01:00
Miguel Palhas bb2708f7ee chore(db): renumber the runtime migration to 0026
The concurrent subtitles milestone carries 0024_subtitles.sql and
0025_subtitle_settings.sql. Two migrations claiming version 24 do not
conflict in git — the filenames differ — so both would land on main and
sqlx would see a duplicate version. Renumbering here is the half that
does not depend on the other milestone acting.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 22:47:18 +01:00
Miguel Palhas 5c5b1e234c Merge #209: scale size bands by episode runtime
Closes #209
2026-08-24 22:47:11 +01:00
Miguel Palhas 917aa4fa76 feat: scale size bands by episode runtime
Implements #209 per §5.5 as amended by #208: a band's floor and target
are rates against a 45-minute reference runtime, scaled by the series'
minutes per episode. A missing or zero runtime applies the bands
unscaled, and movies are never scaled. The runtime is stored on the
series row (new migration), filled on add and by the metadata refresh,
which never blanks a known value against TMDB's frequently-empty
episode_run_time. Composes with #210: allow_below_floor waives against
the scaled floor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 22:45:55 +01:00
Miguel Palhas 024786f356 Merge #210: let a size rejection be waived
Closes #210
2026-08-24 22:16:01 +01:00
Miguel Palhas f0d45996a0 Merge #208: size bands scale with episode runtime
Closes #208
2026-08-24 22:16:01 +01:00
Miguel Palhas 9fee07f080 feat: let a size rejection be waived
A release below §5.5's floor was rejected with no way through, so a
policy wrong about one title left three Rick and Morty S09 packs
visible and none grabbable.

`allow_below_floor` relaxes the floor for one title into a soft fail,
never a pass: the release is waived, so automatic grabbing still skips
it and the import records a §5.7 waiver. The deck offers the one click
on a rejected row where the rule has an override, which is exactly what
§9.3's override is for.

Stored verdicts are re-derived when a title's overrides change — the
deck and the daemon's grab gate both read that column, so without it
the row the operator just acted on would keep reading `rejected`.

Closes #210

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 22:15:14 +01:00
Miguel Palhas bd52941a6d docs: size bands scale with episode runtime
A band's floor and target now read as a rate against a 45-minute
reference runtime, scaled by the series' per-episode runtime from
TMDB. Missing or zero runtime falls back to the reference, keeping
today's behaviour. Movies are explicitly unscaled. Closes the axis
question in #208; #209 implements it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 21:53:32 +01:00
Miguel Palhas 405358bf24 Merge milestone 'Season packs'
e2e / e2e (push) Successful in 1m16s
ci / web (push) Successful in 1m41s
ci / rust (push) Successful in 1m48s
Size bands describe one episode, so a pack's size is divided by the
episodes it covers before the floor and target are applied — a 2160p
pack no longer loses to a 1080p one on a penalty that scaled with
season length.

A failed pack grab now quiets the pack lane on the shared §6.2 backoff
curve instead of disabling it forever, and a manual season search
waives the window. The season deck names which state it is actually in
rather than blaming backoff for a sweep that was never going to run.

Closes #179, #180, #181, #182
2026-08-24 21:31:38 +01:00
Miguel Palhas 93c064701c Merge #182: name the season deck's real state
Closes #182
2026-08-24 21:27:42 +01:00
Miguel Palhas d474909ab5 Merge #180: score season packs per episode
Closes #180
2026-08-24 21:27:42 +01:00
Miguel Palhas 1e03873209 feat(web): name the season deck's real state
An empty season deck was three truths wearing one message, and the one
it chose to blame was wrong: a season on the per-episode lane sat on
"sweeping indexers…" for the full wait and then blamed a backoff for a
pack search that was never going to run.

`GET /api/series/{id}/seasons/{n}/pack-state` says which lane the
season takes and why, from `season_grab_reason` in arr-core, plus the
failed-pack tally and when #181's window reopens. Seasons gain
`last_pack_search_at`, written only by a season-scoped sweep, so a
pack search that ran and found nothing is a settled answer rather than
a pending one.

The deck then says the true thing in each case, and a season held off
the pack lane by a failure offers the retry that waives its window.

Refs #182
2026-08-24 20:14:48 +01:00
Miguel Palhas 2286cba862 feat(core): score season packs per episode
A size band describes one episode (DESIGN.md §5.5), so both the target
penalty and the floor now compare a release's size divided by the number
of episodes it covers. The caller supplies the count — arr-core has no
IO. Movies and unknown counts divide by one, so movie scoring is
unchanged and pinned by test.

Closes #180

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 20:10:23 +01:00
Miguel Palhas 577eef3f31 Merge #181: retry season packs after backoff
Closes #181
2026-08-24 19:52:40 +01:00
Miguel Palhas a5fd543561 Merge #179: size bands are per episode
Closes #179
2026-08-24 19:52:40 +01:00
Miguel Palhas dc6c25f582 fix(daemon): retry season packs after backoff
A failed season-pack grab held the season off the pack lane forever:
pack_hard_failed was a bare EXISTS over failed grabs, so one bad
torrent disabled pack search for good, against §6.2's "it never gives
up entirely, it goes quiet".

The guard now rides the shared backoff curve (backoff_elapsed, 1h → 6h
→ 1d → 3d, capped 7d), counting failed pack grabs as attempts and
anchoring on the latest one's grabbed_at. Both the targeted and RSS
lanes agree. A manual season search waives the window outright — the
season deck is §6.2's escape hatch.

Closes #181.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 19:51:28 +01:00
Miguel Palhas 0c2ba6ff15 docs(design): size bands are per episode
A release covering several episodes is measured by size divided by the
episode count, for the target penalty and the floor alike. An unknown
count divides by one, which fails toward rejecting rather than grabbing.

Refs #179
2026-08-24 19:42:04 +01:00
Miguel Palhas a3897df0ab fix(db): keep migration checksums stable
ci / web (push) Successful in 38s
ci / rust (push) Successful in 1m4s
e2e / e2e (push) Successful in 1m14s
Issue #155 removed the sqlx 0.8 rebuild workarounds by editing migrations
0007, 0014 and 0021 in place. Editing an applied migration changes its
checksum, and `migrate()` refuses to run when one no longer matches what
`_sqlx_migrations` recorded, so the daemon exited on startup against any
database that had already applied them — production included.

The sqlx 0.9 bump is the fix and survives: a new migration can carry
`-- no-transaction` so `PRAGMA foreign_keys = OFF` holds and a table
rebuild stops cascade-deleting its children. Only the retroactive cleanup
of migrations that already ran is reverted, along with #153's
`CHECK (title <> '')`, which rode on the 0021 edit and needs a migration
of its own rather than a rewrite of history.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 19:14:42 +01:00
Miguel Palhas 83a0b247c9 Merge milestone 'Reliability and first run'
ci / web (push) Successful in 38s
e2e / e2e (push) Successful in 1m30s
ci / rust (push) Successful in 1m45s
Closes #155, #158, #168, #176, #177
2026-08-24 19:05:27 +01:00
Miguel Palhas 74cf82489b Merge #177: distinguish pending refresh from empty
Closes #177
2026-08-24 19:00:29 +01:00
Miguel Palhas b2147fe7b9 feat(web): tell pending seasons from settled empty 2026-08-24 18:59:15 +01:00
Miguel Palhas dc145ae2c1 Merge #158: bound the TMDB response cache
Closes #158
2026-08-24 18:59:01 +01:00
Miguel Palhas 3261741415 fix(meta): bound the TMDB response cache on disk
Closes #158
2026-08-24 18:56:59 +01:00
Miguel Palhas 998717b578 Merge #168: search survives a down TMDB
Closes #168
2026-08-24 18:53:21 +01:00
Miguel Palhas ddf1c5fd93 fix(api): search survives a down TMDB and errors name the upstream 2026-08-24 18:52:15 +01:00
Miguel Palhas 88a353dc68 Merge #176: refresh metadata on add
Closes #176
2026-08-24 18:41:48 +01:00
Miguel Palhas f954db9830 Merge #155: bump sqlx to 0.9, honour no-transaction
Closes #155
2026-08-24 18:41:48 +01:00
Miguel Palhas 93a3485c50 fix(db): drop 0.8 rebuild workarounds, enforce title
With sqlx 0.9 honouring `-- no-transaction`, 0007 loses its
movie_releases_backup stash like 0014 did, and 0021 gains
the CHECK (title <> '') that #153 abandoned because the 0.8
migrator could not run a rebuild with foreign keys off. The
rebuild test now enters at migration 6 so the child links
ride through all three rebuilds, and a new test proves the
'' -> 'TBA' backfill and the rejection of new empty titles.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 18:39:22 +01:00
Miguel Palhas d8797e1996 feat(daemon): refresh metadata on add
The metadata lane runs daily, so a series added a moment ago showed no
seasons for up to 24 hours and a movie had no digital release date —
the field §6.2 gates targeted search on.

AppState now carries a MetadataCommand channel alongside the movie,
episode and season ones. Both create handlers send on it after the row
is committed, and a new daemon lane drains it. Its own task rather than
an arm of manual::run: a refresh against TMDB can take a while and must
not sit in front of an operator's manual search.

The add never waits on TMDB and never fails because of it. A refresh
that fails leaves metadata_refreshed_at NULL, which is what the daily
sweep already treats as due, so the title is retried rather than lost.
A command naming a title deleted in between finds no row and does
nothing. METADATA_INTERVAL is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 18:12:10 +01:00
Miguel Palhas ef4722e1dd fix(db): bump sqlx to 0.9, honour no-transaction
sqlx-sqlite 0.8 ignored Migration.no_tx and wrapped every
migration in a transaction, where PRAGMA foreign_keys = OFF
is a no-op — so any table rebuild cascade-deleted children.
0.9 honours `-- no-transaction`, so 0014 drops its
movie_releases_backup / episode_releases_backup workaround
and runs the plain rebuild recipe with foreign keys off.
A migration test rebuilds both parents from a pre-0014
database and asserts the child link rows survive.

Closes #155

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 18:10:53 +01:00
Miguel Palhas e9806d7a84 Merge origin/main
ci / web (push) Successful in 1m9s
e2e / e2e (push) Successful in 2m3s
ci / rust (push) Successful in 2m12s
2026-08-24 17:21:54 +01:00
Miguel Palhas 70e9e17136 Merge milestone 'Removal and navigation'
Closes #169, #170, #171, #172, #173, #174, #175
2026-08-24 17:21:45 +01:00
Miguel Palhas a6af920e39 Merge #175: removal controls for series, seasons, episodes
Closes #175
2026-08-24 17:14:00 +01:00
Miguel Palhas 7c30928907 feat(web): series, season and episode removal
Series detail exposes DELETE /api/series/{id} through the movie
removePanel, generalised over endpoints and file rollup instead of
copied. Season headers and on-disk episode rows get the settings
armed-delete control wired to #174's file endpoints, worded for what
they do: files go, wanted clears, the row stays listed.

Closes #175

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 17:09:46 +01:00
Miguel Palhas d5fc790839 docs: drop area/web Fable routing rule
ci / web (push) Successful in 48s
e2e / e2e (push) Successful in 1m36s
ci / rust (push) Successful in 1m42s
The rule justified pinning area/web issues to Fable 5 by saying they go
through the impeccable skill. That skill is symlinked into codex as well,
so it says nothing about which model to use. area/web now routes by
difficulty label like every other area; line 47 already requires
impeccable for anything that decides how something looks.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 16:55:23 +01:00
Miguel Palhas 3dda666273 Merge #174: delete files and untrack a season or episode
Closes #174
2026-08-24 16:45:21 +01:00
Miguel Palhas 64e28e5930 feat: remove files for one season or episode
DELETE /api/series/{id}/seasons/{n}/files and
DELETE /api/episodes/{id}/files unlink what the scope covers, drop the
matching media_files rows and clear wanted, in one action. 204 on
success, 404 for an unknown season or episode, and a scope with nothing
on disk still clears intent.

Season and episode rows stay: TMDB owns that metadata and the next
refresh would recreate them.

The three scopes share one unlink path. A whole series still resolves to
its title folder (§7.4, atomic); a season or episode resolves to the
recorded file and nothing else, so a narrow call cannot reach a sibling.
The intent clear goes through arr_core::tracking::apply_tracked(false),
the same §4.1 rule #171 landed.

An episode whose file just went is set back to 'missing' when it was
'available', matching what a failed import already does. Closes #174.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-24 16:43:53 +01:00
Miguel Palhas f3336d066e Merge #172: search returns titles only
Closes #172
2026-08-24 16:40:44 +01:00
Miguel Palhas 27525302b2 Merge #173: library is the homepage
Closes #173
2026-08-24 16:40:38 +01:00
Miguel Palhas 4b89245f00 fix(api): drop episode rows from unified search
Search returns titles only (§9.2, amended): the episode branch of the
library query, its json_each token machinery, and the SPA's episode
row rendering are removed. Deep links to episode releases stay.

Fixes #172
2026-08-24 16:39:48 +01:00
Miguel Palhas 7ef24088a5 feat(web): library homepage, chain in settings
Implements the §9.7 shell rulings (issue #173): "/" renders the library
and the board route is gone — every former board target (Esc, cleared
search, detail parent routes, the not-found fallback) lands on the
library. The signal chain moves into /settings as its first section,
lamps still driven by the health poll; the master lamp stays on the
rail. The wordmark is now a real anchor that navigates home.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-24 16:39:07 +01:00
Miguel Palhas 4a611a6794 Merge #171: untracking a season clears wanted
Closes #171
2026-08-24 16:32:02 +01:00
Miguel Palhas 9e003823c6 feat: untracking a season clears its wanted 2026-08-24 16:31:09 +01:00
Miguel Palhas 205855fa7f Merge #170: centre deck column chips in their box
Closes #170
2026-08-24 16:29:25 +01:00
Miguel Palhas fada2ff89a fix(web): centre deck chips in their boxes 2026-08-24 16:28:42 +01:00
Miguel Palhas 60642d8709 Merge #169: amend DESIGN.md for four rulings
Closes #169
2026-08-24 16:21:03 +01:00
Miguel Palhas c37031207e docs: amend DESIGN.md for four rulings
Untracking a season now clears its episodes' wanted flag, unified search
returns titles only, the library is the homepage and the signal chain moves
into settings, and the wordmark links home.

Refs #169
2026-08-24 16:20:13 +01:00
Miguel Palhas 869e3af9c8 Merge milestone 'Feedback pass'
ci / web (push) Successful in 36s
e2e / e2e (push) Successful in 1m10s
ci / rust (push) Successful in 1m19s
Nine issues from a hands-on pass over the deployed build.

Behaviour: adding a series no longer tracks its whole back catalogue
(auto_track applies from the second refresh onward); a series-title
query no longer returns every episode of that series; seasons and
episodes come back newest-first.

UI: cast comes off title detail; buttons and chips share one 2rem
geometry; state chips carry the ramp (green satisfied, amber gap,
violet active, neutral idle); the header drops its verdict line and
sits on the content width; season and episode rows lose their search
button and the deck sweeps itself when opened empty.

DESIGN.md 4.1, 4.2, 9.2 and 9.6 amended first; every other issue
implements against the amended text.

Closes #159, #160, #161, #162, #163, #164, #165, #166, #167
2026-08-24 15:26:12 +01:00
Miguel Palhas e509c37649 Merge #167: tv deck sweeps on open when empty 2026-08-24 15:14:53 +01:00
Miguel Palhas 8a672c1dcf feat(web): tv deck sweeps on open when empty
Drop the standalone search button from season and episode rows; the
deck is the one control. An empty deck fires a targeted sweep on
open and reports progress in place; a deck with results never sweeps
on open. re-search inside the deck forces a fresh sweep.
2026-08-24 14:42:29 +01:00
Miguel Palhas fb03fc3808 Merge #166: lamp-only header on the content width 2026-08-24 14:38:03 +01:00
Miguel Palhas 1add26b7f7 Merge #165: state ramp on status and counts chips 2026-08-24 14:38:03 +01:00
Miguel Palhas fa5d876c09 chore(web): sync design.json to the state ramp
The token system still mirrored the pre-amendment palette and carried
the rule 'Don't colour complete green or incomplete amber', which now
contradicts DESIGN.md 4.2 and would have had the next session revert
the ramp. Drops the four --status-* tokens no rule consumes any more;
satisfaction reuses --signal-ok and a gap --signal-warn.

Committed by the blitz orchestrator: the authoring session wedged.
2026-08-24 14:37:52 +01:00
Miguel Palhas 0cb8111678 fix(web): pin the version readout to the rail edge 2026-08-24 14:36:18 +01:00
Miguel Palhas d1d6b4f9a0 feat(web): lamp-only header on the content width
Drops #master-verdict entirely - element, .rail-verdict rules and every
line that wrote into it. The lamp is the only header signal; the
unreachable detail moves onto the board's arr module so nothing is lost.
Rail contents move into .rail-inner capped at the deck's 68rem and
centred, leaving the panel full-bleed.

Committed by the blitz orchestrator: the authoring session wedged with
the work complete on disk and stopped accepting input.
2026-08-24 14:36:18 +01:00
Miguel Palhas 2dbb0f48f7 feat(web): state ramp on status and counts chips
Per amended DESIGN.md §4.2: green --signal-ok for on disk/complete,
amber --signal-warn for wanted-but-missing, violet --status-airing for
downloading, neutral for untracked and waiting. Stars go amber. Words
stay in every chip; verdict chips untouched.
2026-08-24 13:57:17 +01:00
Miguel Palhas 8221ea633c Merge #163: drop cast from title detail 2026-08-24 12:34:34 +01:00
Miguel Palhas 7d4ddb7331 refactor(web): drop cast from title detail
DESIGN.md §9.6 no longer carries cast (#163). Removes the cast
sections, the MetadataCastMember schema and field from both metadata
responses, and every .cast-* rule. arr-meta keeps CastMember and the
credits append; the TMDB call is unchanged.
2026-08-24 12:34:00 +01:00
Miguel Palhas ed39b1ca49 Merge #164: one control geometry for buttons and chips 2026-08-24 12:12:08 +01:00
Miguel Palhas 1a4394cf0d feat(web): one control geometry for buttons and chips
Buttons, chips, toggles and the search input converge on --control-h
2rem with --text-xs shared, and .control becomes an inline-flex so
anchor text centres in the title-detail action bar. Chip colour is
untouched (#165 owns it). Verified in agent-browser at 1440px, 46rem
and 40rem; the release deck keeps its column widths and does not
scroll horizontally.
2026-08-24 12:11:08 +01:00
Miguel Palhas 4d5cc120d1 fix(api): newest-first season and episode order
DESIGN.md §9.6 now puts the current season at the top: seasons
descend by number within a series (season 0 lands last under plain
numeric descending) and episodes descend within each season. Changed
the two queries in load_seasons; the SPA renders this order as given.

arr-compat checked and untouched: it reads seasons with its own
ORDER BY number query straight from the database, never through
arr-api, and SeasonResource carries season_number, which Jellyseerr
matches on rather than position. Sonarr's real API also returns
seasons ascending, so the shim keeps the contract it emulates.

The existing vanished-flag test indexed seasons positionally; it now
looks them up by number so it tests the flag, not the order. New test
asserts [2, 1, 0] for seasons and descending episodes within each.
.sqlx regenerated via just db-prepare. just ci green locally.
2026-08-24 12:09:52 +01:00
Miguel Palhas 2c293e7f60 fix(api): episode rows need a token beyond series title
Per amended DESIGN.md 9.2, an episode row now also requires at
least one query token to match the episode title on its own, so
a series-title-only query lists the series and no episodes.
2026-08-24 11:59:18 +01:00
Miguel Palhas 8f7373d73d fix(core): auto-track skips the seeding refresh
A series' first metadata refresh reveals its whole back catalogue, and
apply_auto_track flagged every season as new — adding Rick and Morty
tracked S01-S09 and wanted 91 episodes (#160).

Per DESIGN.md 4.1 the rule applies from the second refresh onward.
The caller passes whether metadata_refreshed_at is set; arr-core stays
IO-free and decides. Wired through the daemon's daily refresh and the
API's create-season endpoint.
2026-08-24 11:40:44 +01:00
Miguel Palhas 2495895717 docs: record five rulings from the deployed build 2026-08-24 11:28:05 +01:00
Miguel Palhas 40620d93b4 fix(web): series page loads; cast art falls back
ci / web (push) Successful in 34s
e2e / e2e (push) Successful in 57s
ci / rust (push) Successful in 1m9s
2026-08-24 03:21:42 +01:00
Miguel Palhas 1c351eb867 Merge #151: library poster grid with list toggle
Closes #151
2026-08-24 03:05:59 +01:00
Miguel Palhas a6cdd0ab0b feat(web): library poster grid with list toggle 2026-08-24 03:04:06 +01:00
Miguel Palhas 365c2a7587 Merge #148: rich search result rows
Closes #148
2026-08-24 01:57:25 +01:00
Miguel Palhas 07741c80fe feat(web): rich search rows (#148)
Every search row — library and TMDB alike — gains a w92 poster
thumbnail with a same-size blank fallback, a TMDB rating chip
(hidden when there are no votes), and a trailer chip that resolves
GET /api/trailer on click only, opening the tab inside the handler.
Episode hits carry the series' TMDB id so their chip resolves too.
2026-08-24 01:55:00 +01:00
Miguel Palhas 82b294ab1b Merge #150: series detail metadata header
Closes #150
2026-08-24 00:40:22 +01:00
Miguel Palhas ed210b29d3 feat(web): series detail metadata header 2026-08-24 00:37:53 +01:00
Miguel Palhas b413718fd1 fix(web): unrated movies show no rating 2026-08-24 00:01:17 +01:00
Miguel Palhas 9a03fc9963 Merge #149: movie detail page
Closes #149
2026-08-24 00:00:22 +01:00
Miguel Palhas fdaaeccb40 feat(web): movie detail page at /movies/{id} 2026-08-24 00:00:18 +01:00
Miguel Palhas be2c5f7e3c Merge #147: posters and ratings on search results
Closes #147
2026-08-23 22:45:49 +01:00
Miguel Palhas 5e2bb5dff7 feat(api): carry poster and rating through search and lists
Widen the unified search so both §9.2 halves can render a thumbnail
and a rating: TMDB results gain vote_average/vote_count from the
search bodies, library results read the #145 artwork columns, and
episodes take their series' art. GET /api/movies and /api/series gain
the same two fields for the #151 grid. Mirrors in web updated.
2026-08-23 22:45:08 +01:00
Miguel Palhas 30382585ea fix(meta,api): detail ratings are optional too 2026-08-23 22:26:04 +01:00
Miguel Palhas c9e73cb23c Merge #156: unrated titles store NULL
Closes #156
2026-08-23 22:24:05 +01:00
Miguel Palhas 8af85606a0 test(api): match detail call by its appended resources 2026-08-23 22:22:14 +01:00
Miguel Palhas 08e3c7bce7 fix(meta): store unrated titles as NULL, not zero
TMDB reports vote_average: 0 where no rating exists (#156). Normalise
it to None at the arr-meta edge, like non_empty does for "", and let
the Option flow through the daemon refresh and API add paths so the
nullable columns from #145 do their job.
2026-08-23 22:21:57 +01:00
Miguel Palhas 22f5d6b463 Merge #146: title metadata endpoints
Closes #146
2026-08-23 22:19:03 +01:00
Miguel Palhas 60fcc9f3d5 feat(api): metadata endpoints for library titles 2026-08-23 22:17:51 +01:00
Miguel Palhas b59e30dbdb Merge #145: store poster, backdrop and rating
Closes #145
2026-08-23 22:13:37 +01:00
Miguel Palhas 8478c0f8a9 feat(db): store poster, backdrop and rating on titles
§9.6 keeps rich detail out of the database except for the three fields
pure-SQL views need. Adds poster_path, backdrop_path and vote_average to
movies and series, written by the daily metadata refresh in both lanes
and filled at add time from the TMDB response the create flows already
fetch.
2026-08-23 22:12:05 +01:00
Miguel Palhas 82f87d61f1 Merge #144: trailer endpoint by TMDB id
Closes #144
2026-08-23 22:04:42 +01:00
Miguel Palhas 80a63ea2e1 feat(api): resolve trailer chips by TMDB id 2026-08-23 22:03:04 +01:00
Miguel Palhas 9bd037d1b6 Merge #143: rich title detail in arr-meta
Closes #143
2026-08-23 21:34:00 +01:00
Miguel Palhas cbb21418a4 feat(meta): rich detail calls for movies and series
movie_detail/series_detail fetch credits, videos and external ids in
one upstream request via append_to_response; cast is truncated to the
top 10 billed in the crate and a trailer is chosen by rule (official
YouTube trailer, any YouTube trailer, YouTube teaser, none).
movie_videos/series_videos serve #144's search-row chip from the
videos endpoint alone. Everything rides the existing 24h cache.
2026-08-23 21:33:17 +01:00
Miguel Palhas 689487bf82 Merge #142: DESIGN.md title detail surface
Closes #142
2026-08-23 21:23:45 +01:00
Miguel Palhas 2e4e1e7547 docs(design): title detail and enriched search rows 2026-08-23 21:22:50 +01:00
Miguel Palhas 1acdcaca23 Merge TV tracking milestone
ci / web (push) Successful in 27s
e2e / e2e (push) Successful in 2m5s
ci / rust (push) Successful in 2m9s
Closes the phase/6-tv gap set: daily series metadata refresh, tracked-season
intent, RSS episode and season-pack matching, season release decks, the TV
attention queue, and the series detail view. 27 issues.

See milestone 'TV tracking'.
2026-08-23 21:10:52 +01:00
Miguel Palhas 26dd0dc5d3 Merge #153: placeholder for empty episode titles
Closes #153
2026-08-23 20:58:09 +01:00
Miguel Palhas e9a5095557 feat(api): reject empty episode titles 2026-08-23 20:55:30 +01:00
Miguel Palhas 0ed0791fd4 fix(db): backfill empty episode titles to TBA 2026-08-23 20:55:16 +01:00
Miguel Palhas 23f5781714 feat(meta): substitute TBA for unnamed episodes 2026-08-23 20:55:16 +01:00
Miguel Palhas 877dbae7cb Merge #152: URL-addressed TV release decks
Closes #152
2026-08-23 20:49:01 +01:00
Miguel Palhas cf36a4302c feat(web): route season and episode release decks 2026-08-23 20:44:28 +01:00
Miguel Palhas 06a68372e6 feat(api): expose series and season on episodes 2026-08-23 20:44:28 +01:00
Miguel Palhas 4762f2612f feat(web): show the vanished flag on seasons 2026-08-23 20:32:30 +01:00
Miguel Palhas 468f31f0b0 Merge #141: expose seasons.vanished on the API
Closes #141
2026-08-23 20:31:13 +01:00
Miguel Palhas 571ec42e92 feat(api): expose seasons.vanished (#141)
Season objects from the series endpoints now carry the conflict flag
#137 writes, the way episodes already do.
2026-08-23 20:27:34 +01:00
Miguel Palhas db72cb4bcd docs: use agent-browser for the visual pass 2026-08-23 20:24:00 +01:00
Miguel Palhas d5013d4ca8 Merge #129: series detail view
Closes #129
2026-08-23 20:21:15 +01:00
Miguel Palhas 7f9729fb57 style(web): issue refs without hex-looking hashes 2026-08-23 20:18:51 +01:00
Miguel Palhas e335a1be73 style(api): drop needless raw string hashes 2026-08-23 20:13:54 +01:00
Miguel Palhas 82100ef7ab feat(web): series detail view with season and episode decks 2026-08-23 20:12:06 +01:00
Miguel Palhas 6826170431 feat(web): series data layer and /series route 2026-08-23 20:12:06 +01:00
Miguel Palhas 4efc7b1833 fix(web): token linter ignores comments 2026-08-23 19:54:42 +01:00
Miguel Palhas 353608ae63 Merge #140: name episodes in the attention queue
Closes #140
2026-08-23 19:52:48 +01:00
Miguel Palhas d86d975073 fix(web): drop issue refs that trip the token linter 2026-08-23 19:51:52 +01:00
Miguel Palhas 9129728622 refactor(api): extract attention merge helpers 2026-08-23 19:48:59 +01:00
Miguel Palhas e4c115803b style: fix test formatting 2026-08-23 19:46:16 +01:00
Miguel Palhas 1d31ea7d1b feat(web): render SxxEyy chips in attention queues 2026-08-23 19:45:33 +01:00
Miguel Palhas 7f7f26dbc7 feat(api): name attention episodes and seasons 2026-08-23 19:45:33 +01:00
Miguel Palhas 11d2952863 Merge #137: reconcile whole seasons removed upstream
Closes #137
2026-08-23 19:36:37 +01:00
Miguel Palhas 00ff4db26a style: cargo fmt 2026-08-23 19:35:07 +01:00
Miguel Palhas 409967eef6 feat(daemon): reconcile vanished seasons (#137) 2026-08-23 19:34:55 +01:00
Miguel Palhas 943f18cdf5 feat(db): add seasons.vanished conflict flag 2026-08-23 19:34:55 +01:00
Miguel Palhas 1af73caa34 Merge #133: render TV lanes in the attention queue
Closes #133
2026-08-23 19:27:35 +01:00
Miguel Palhas 71cbb9269b fix(web): reword comment that tripped the token gate 2026-08-23 19:26:43 +01:00
Miguel Palhas 160c00c77f feat(web): render tv lanes in attention queues 2026-08-23 19:23:19 +01:00
Miguel Palhas 779d4b8504 Merge #139: episode tag beats a movie id match
Closes #139
2026-08-23 19:17:47 +01:00
Miguel Palhas 64e711feec fix(core): guard movie id lane against episode tags 2026-08-23 19:13:49 +01:00
Miguel Palhas a378b22306 Merge #134: satisfied titles leave the attention queue
Closes #134
2026-08-23 19:09:15 +01:00
Miguel Palhas 04b2688330 Merge #124: match RSS results against wanted episodes
Closes #124
2026-08-23 19:09:15 +01:00
Miguel Palhas 91414a043f chore: regenerate sqlx query data 2026-08-23 19:07:29 +01:00
Miguel Palhas a28b455fff fix: gate hard-fail attention on unsatisfied titles 2026-08-23 19:07:29 +01:00
Miguel Palhas 9df120b92a feat(daemon): match RSS results to wanted episodes
One feed pass now serves films and episodes alike. A
single-episode release grabs its open episode directly; a season
pack only grabs when season_grab_mode allows packs for that
season (§14, #117), and when it wins, the singles stand down.
Blocked series keep matching RSS (§6.3) and nothing here touches
the targeted-search backoff (§6.2).
2026-08-23 19:07:00 +01:00
Miguel Palhas 03e7774869 Merge #136: resolve IMDb ids to series as well
Closes #136
2026-08-23 19:01:42 +01:00
Miguel Palhas fea1a04c75 feat(api): surface series for IMDb id searches 2026-08-23 18:59:35 +01:00
Miguel Palhas 3956617d41 feat(meta): resolve IMDb ids against series too 2026-08-23 18:59:35 +01:00
Miguel Palhas d8316ae0c8 feat(api): series files keyed by episode id 2026-08-23 18:41:36 +01:00
Miguel Palhas 127338fd4d Merge #132: drain manual episode and season commands
Closes #132
2026-08-23 18:27:43 +01:00
Miguel Palhas 695f1882be Merge #128: series delete unlinks its files
Closes #128
2026-08-23 18:25:56 +01:00
Miguel Palhas 8a77049fdb feat(daemon): drain all manual command channels 2026-08-23 18:24:50 +01:00
Miguel Palhas 39e6bce2a0 feat(daemon): manual episode/season triggers 2026-08-23 18:24:50 +01:00
Miguel Palhas b0f56f59aa fix(api): delete series files and media_files rows 2026-08-23 18:23:41 +01:00
Miguel Palhas 1eac85c427 Merge #131: derive status from the episode's own season number
Closes #131
2026-08-23 18:21:34 +01:00
Miguel Palhas 50b68e24b6 api: derive status from episode season numbers
with_status drops its seasons slice for the same reason as
derive_series_status; tv_by_series no longer loads seasons at all.
Offline query data regenerated.
2026-08-23 18:18:26 +01:00
Miguel Palhas 69263da4f3 daemon: populate season_number on refreshed episodes 2026-08-23 18:18:26 +01:00
Miguel Palhas b51386e004 core: carry season number on Episode
derive_series_status identified specials by looking the episode's
season up in a parallel seasons slice, so a caller passing an
incomplete slice silently reverted to pre-#118 behaviour. The season
number now rides on each episode and the slice is gone.
2026-08-23 18:18:26 +01:00
Miguel Palhas 17949c0848 Merge #138: close title boundary on plural season ranges
Closes #138
2026-08-23 18:17:19 +01:00
Miguel Palhas 4f848c27f0 fix(parse): close title on spelled-out season ranges 2026-08-23 18:12:47 +01:00
Miguel Palhas e4c49b75de Merge #130: add a series from unified search
Closes #130
2026-08-23 18:05:45 +01:00
Miguel Palhas 00d0ec7f16 Merge #135: fix season-pack name parsing
Closes #135
2026-08-23 18:05:39 +01:00
Miguel Palhas adfc60154d Merge #122: reconcile episodes that vanish upstream
Closes #122
2026-08-23 18:05:39 +01:00
Miguel Palhas 8d79c7c378 fix(parse): pack titles and degenerate ranges
COMPLETE before the season tag was weak junk, so it stayed in
the title and exact-title matching failed silently (#135). It
now closes the boundary wherever it lands.

S01-S01 produced no claim because the dash-range branch required
last > season; a degenerate range is one season's pack, matching
the rule match_episode lifted.
2026-08-23 18:02:39 +01:00
Miguel Palhas 34ccbeeb5a feat(api): expose vanished flag on episodes 2026-08-23 18:01:41 +01:00
Miguel Palhas 8b9a6d5a16 feat(daemon): reconcile episodes that vanish upstream 2026-08-23 17:59:45 +01:00
Miguel Palhas 3bcc612f9a feat(db): flag episodes that vanish upstream 2026-08-23 17:59:41 +01:00
Miguel Palhas 384e260d72 Merge #121: daily series metadata refresh
Closes #121
2026-08-23 17:47:46 +01:00
Miguel Palhas 0c58aae707 feat(daemon): daily series metadata refresh lane 2026-08-23 17:45:09 +01:00
Miguel Palhas 808145d73b feat(db): stamp series metadata refresh time 2026-08-23 17:45:09 +01:00
257 changed files with 24286 additions and 3946 deletions
+8 -8
View File
@@ -123,7 +123,7 @@
},
"scale": {
"displayName": "Type scale",
"purpose": "Seven fixed steps as tokens: --text-2xs 0.6875rem (micro-labels), --text-xs 0.75rem (details, chips), --text-sm 0.8125rem (readouts, controls), --text-base 1rem (body), --text-md 1.0625rem (module names), --text-lg 1.3125rem (master module), --text-xl 1.625rem (wordmark). Components never carry a literal font-size."
"purpose": "Seven fixed steps as tokens: --text-2xs 0.6875rem (micro-labels), --text-xs 0.75rem (details, chips, controls), --text-sm 0.8125rem (readouts), --text-base 1rem (body), --text-md 1.0625rem (module names), --text-lg 1.3125rem (master module), --text-xl 1.625rem (wordmark). Components never carry a literal font-size. One control geometry: buttons and chips share --control-h 2rem and --text-xs, so a season line reads as one system."
}
},
"shadows": [
@@ -189,7 +189,7 @@
"refersTo": "ground",
"description": "The §9.3 column unit: a small machined panel holding one mono value (score, resolution, source, HDR, audio, size, seeders). Fixed rhythm so columns align; never a soft pill.",
"html": "<span class=\"chip readout\">2160p</span>",
"css": ".chip { display: inline-flex; align-items: center; gap: var(--space-1); min-height: 1.375rem; padding: 0 var(--space-2); background: var(--panel-raised); border: 1px solid var(--line); border-radius: var(--radius); font-family: var(--font-readout); font-size: var(--text-xs); color: var(--ink-muted); }"
"css": ".chip { display: inline-flex; align-items: center; gap: var(--space-1); min-height: var(--control-h); padding: 0 var(--space-2); background: var(--panel-raised); border: 1px solid var(--line); border-radius: var(--radius); font-family: var(--font-readout); font-size: var(--text-xs); color: var(--ink-muted); }"
},
{
"name": "Verdict chip",
@@ -205,7 +205,7 @@
"refersTo": "status-channel",
"description": "Library status (§4.2): airing / incomplete / waiting / complete / ended. Informational, not severity — colour marks activity in one channel-violet family (airing brightest, incomplete, waiting dimmest), satisfaction is neutral (complete bright ink, ended faint). The mono word is always present.",
"html": "<span class=\"chip readout\" data-status=\"airing\">airing</span>",
"css": ".chip[data-status=\"airing\"] { color: var(--status-airing); border-color: oklch(from var(--status-airing) l c h / 45%); } .chip[data-status=\"incomplete\"] { color: var(--status-incomplete); } .chip[data-status=\"waiting\"] { color: var(--status-waiting); } .chip[data-status=\"complete\"] { color: var(--status-complete); } .chip[data-status=\"ended\"] { color: var(--status-ended); }"
"css": ".chip[data-status=\"airing\"] { color: var(--status-airing); border-color: oklch(from var(--status-airing) l c h / 45%); } .chip[data-status=\"incomplete\"] { color: var(--signal-warn); border-color: oklch(from var(--signal-warn) l c h / 55%); } .chip[data-status=\"complete\"], .chip[data-status=\"ended\"] { color: var(--signal-ok); border-color: oklch(from var(--signal-ok) l c h / 45%); } .chip[data-counts=\"complete\"] { color: var(--signal-ok); } .chip[data-counts=\"partial\"] { color: var(--signal-warn); }"
},
{
"name": "Module (channel strip)",
@@ -229,15 +229,15 @@
"refersTo": "accent",
"description": "The interactive element: mono uppercase, phosphor-cyan text, panel ground, ≥44px hit target. Cyan belongs to interaction only — never to status.",
"html": "<button type=\"button\" class=\"control\">probe</button>",
"css": ".control { min-height: 2.75rem; padding: 0 var(--space-4); font-family: var(--font-readout); text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent); background: var(--panel-raised); border: 1px solid var(--line-strong); border-radius: var(--radius); }"
"css": ".control { display: inline-flex; align-items: center; justify-content: center; min-height: var(--control-h); padding: 0 var(--space-4); font-family: var(--font-readout); font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.08em; color: var(--accent); background: var(--panel-raised); border: 1px solid var(--line-strong); border-radius: var(--radius); }"
},
{
"name": "Rail",
"kind": "nav",
"refersTo": "ground",
"description": "Full-width panel strip framing the board top (identity + verdict + controls) and bottom (readouts). Hairline-ruled, panel ground, inset highlight.",
"html": "<header class=\"rail\"><div class=\"rail-id\"><span class=\"lamp\" data-state=\"ok\" aria-hidden=\"true\"></span><h1 class=\"wordmark\">arr</h1></div><p class=\"rail-verdict readout\" data-tone=\"ok\">all signals nominal</p></header>",
"css": ".rail { display: flex; align-items: center; gap: var(--space-6); padding: var(--space-3) var(--space-6); border-bottom: 1px solid var(--line); background: var(--panel); box-shadow: inset 0 1px var(--highlight); }"
"description": "Full-width panel strip framing the board top (identity + controls) and bottom (readouts). Hairline-ruled, panel ground, inset highlight. Contents sit in a .rail-inner column capped at 68rem, centred — the panel stays full-bleed. The lamp beside the wordmark is the only header status signal.",
"html": "<header class=\"rail\"><div class=\"rail-inner\"><div class=\"rail-id\"><span class=\"lamp\" data-state=\"ok\" aria-hidden=\"true\"></span><h1 class=\"wordmark\">arr</h1></div></div></header>",
"css": ".rail { padding: var(--space-3) var(--space-6); border-bottom: 1px solid var(--line); background: var(--panel); box-shadow: inset 0 1px var(--highlight); } .rail-inner { display: flex; align-items: center; gap: var(--space-6); width: 100%; max-width: 68rem; margin-inline: auto; }"
}
],
"narrative": {
@@ -300,7 +300,7 @@
"Do take every colour, spacing and font-size from the :root tokens; the token check (web/scripts/check-tokens.mjs) fails CI on literals."
],
"donts": [
"Don't colour `complete` green or `incomplete` amber — library status is informational, not a severity ramp.",
"Colour state chips on the ramp — `complete` and `ended` green, `incomplete` and a partial count amber, `airing` and `downloading` violet, `waiting` and `untracked` neutral. The word stays in every chip, so state survives with colour removed.",
"Don't use fault red for a rejected release; red means the daemon itself is broken.",
"Don't introduce a second interactive hue or use cyan for a status.",
"Don't box content in soft-shadowed rounded cards or add glass/blur.",
+9 -3
View File
@@ -29,9 +29,15 @@ reads the library as derived status, not flags.
counts behind cyan show/hide toggles. Release name is a secondary
truncated line, full string plus indexer/date/bytes on row expand. Every
waived/rejected row carries a verdict chip naming the rule. Grab is its
own control per row; on a waived row it is "waive + grab" and writes the
per-title override (rule→override mapping in releases.ts — bookkeeping,
never policy; verdicts always come from the API). Esc steps back one
own control per row; where the rule that failed has an override it reads
"waive + grab" and writes the per-title override (rule→override mapping in
releases.ts — bookkeeping, never policy; verdicts always come from the
API). A rejected row offers it too — §9.3's one click exists precisely for
the rule the operator disagrees with, and a size rejection (#210) is only
ever rejected. What the click produces stays a waiver: the row re-reads as
a dashed WAIVED, never eligible. When ELIGIBLE is empty and something is
waivable, its "none" line carries the count, so the way out is not folded
inside a collapsed bucket. Esc steps back one
layer: deck → search results → board.
- Removal (§7.4, issue 104): REMOVE is a quiet control in the deck head,
never a row affordance — a dense list is the wrong place for a delete.
@@ -1,74 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ? ORDER BY se.number, e.number",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "number!: i64",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "air_date",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "state!: String",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "search_attempts!: i64",
"ordinal": 8,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 9,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true,
false,
false,
false,
true,
false,
false,
false,
true
]
},
"hash": "024a22e1d6974b40f4fdd86e4ad732ce6de6e7c92b93bc3c835cc48a296021fb"
}
@@ -1,6 +1,6 @@
{
"db_name": "SQLite",
"query": "UPDATE movies SET metadata_refreshed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ?",
"query": "UPDATE movies SET metadata_refreshed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
@@ -8,5 +8,5 @@
},
"nullable": []
},
"hash": "de2153eefd6ec03ceeaf640d599271834cb06c94eda7a9956c5bd7399593c0ae"
"hash": "0516e88e07d3708ba4ccc52d7ba635d45e9d1b2c639b71102e241f50982502eb"
}
@@ -0,0 +1,33 @@
{
"db_name": "SQLite",
"query": "SELECT se.number AS \"number!: i64\", COUNT(e.id) AS \"episodes!: i64\"\n FROM seasons se LEFT JOIN episodes e ON e.season_id = se.id\n WHERE se.series_id = ?\n GROUP BY se.number",
"describe": {
"columns": [
{
"name": "number!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "episodes!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "05b52c731b198cc338c15afff3b0c22ee77649a368081580a1f13ff29288325d"
}
@@ -0,0 +1,86 @@
{
"db_name": "SQLite",
"query": "SELECT s.id AS \"series_id!: i64\", s.title AS \"series_title!: String\", s.tvdb_id AS series_tvdb_id, s.original_language,\n se.number AS \"season_number!: i64\", e.number AS \"episode_number!: i64\"\n FROM episodes e\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n WHERE e.id = ?",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "series_title!: String",
"ordinal": 1,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "series_tvdb_id",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tvdb_id"
}
}
},
{
"name": "original_language",
"ordinal": 3,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "episode_number!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
true,
true,
false,
false
]
},
"hash": "0618d006da5cdf0d86d851cce7ba1fcd279d4542e6aa1f8d8d80bf96746e1f33"
}
@@ -6,34 +6,59 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "media_files",
"name": "id"
}
}
},
{
"name": "path!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "path"
}
}
},
{
"name": "size!: i64",
"ordinal": 2,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "media_files",
"name": "size"
}
}
},
{
"name": "probed?: serde_json::Value",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "probed"
}
}
},
{
"name": "waiver?: String",
"ordinal": 4,
"type_info": "Null"
"type_info": "Null",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false,
false,
true,
@@ -6,12 +6,24 @@
{
"name": "normalised_name!: String",
"ordinal": 0,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "blacklist",
"name": "normalised_name"
}
}
},
{
"name": "infohash",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "blacklist",
"name": "infohash"
}
}
}
],
"parameters": {
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "INSERT INTO seasons (series_id, number, tracked) VALUES (?, ?, ?) RETURNING id",
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "id"
}
}
}
],
"parameters": {
"Right": 3
},
"nullable": [
null
]
},
"hash": "0aea0f15e8a03a37b5d9d32d3c7caffa70f9ec44f5a5da1dc0560f29f445ceab"
}
@@ -6,7 +6,8 @@
{
"name": "count!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
@@ -0,0 +1,28 @@
{
"db_name": "SQLite",
"query": "SELECT count(*) AS \"failures!: i64\",\n max(grabbed_at) AS \"last_failed_at?: String\"\n FROM grabs\n WHERE target_kind = 'season' AND target_id = ? AND state = 'failed'",
"describe": {
"columns": [
{
"name": "failures!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": "Expression"
},
{
"name": "last_failed_at?: String",
"ordinal": 1,
"type_info": "Text",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true
]
},
"hash": "0ca521a8dcb979cc90f5823eb3311d6a3ec1613976c52a8a7f8225e1dc06d162"
}
@@ -6,54 +6,108 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 5,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "last_searched_at"
}
}
},
{
"name": "digital_release",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "digital_release"
}
}
},
{
"name": "metadata_refreshed_at",
"ordinal": 8,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "metadata_refreshed_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false,
false,
true,
@@ -1,92 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE tmdb_id = ? OR NOT EXISTS (SELECT 1 FROM json_each(?) token WHERE title NOT LIKE '%' || token.value || '%' ESCAPE '\\') ORDER BY title, year, id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 12,
"type_info": "Text"
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "0e1cffb9b344a41af0cc64bbe79b2bf303aae47593eaf8df5908a1df1480e4f6"
}
@@ -6,24 +6,42 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "owners",
"name": "id"
}
}
},
{
"name": "name!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "owners",
"name": "name"
}
}
},
{
"name": "ntfy_topic!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "owners",
"name": "ntfy_topic"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
true,
false,
false,
false
]
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE movies\n SET title = ?, year = ?, original_language = ?, digital_release = ?,\n imdb_id = ?, poster_path = ?, backdrop_path = ?, vote_average = ?,\n metadata_refreshed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),\n search_attempts = 0, last_searched_at = NULL,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ? AND (\n title IS NOT ? OR year IS NOT ? OR original_language IS NOT ?\n OR digital_release IS NOT ? OR imdb_id IS NOT ?\n OR poster_path IS NOT ? OR backdrop_path IS NOT ?\n OR vote_average IS NOT ?\n )",
"describe": {
"columns": [],
"parameters": {
"Right": 17
},
"nullable": []
},
"hash": "0f0966881a69a9f4009df7b27ebeadce81719e044c8fb65ba404b45b70bf8d8c"
}
@@ -6,29 +6,53 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "id"
}
}
},
{
"name": "infohash!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "grabs",
"name": "infohash"
}
}
},
{
"name": "target_kind!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "grabs",
"name": "target_kind"
}
}
},
{
"name": "target_id!: i64",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "target_id"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
true,
false,
false,
false,
false
@@ -6,32 +6,68 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "roots",
"name": "id"
}
}
},
{
"name": "kind!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "kind"
}
}
},
{
"name": "audience!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "audience"
}
}
},
{
"name": "path!: String",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
},
{
"name": "policy_id!: i64",
"ordinal": 4,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "policies",
"name": "id"
}
}
},
{
"name": "policy_name!: String",
"ordinal": 5,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
}
],
"parameters": {
@@ -6,7 +6,13 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "releases",
"name": "id"
}
}
}
],
"parameters": {
@@ -6,7 +6,8 @@
{
"name": "exists!: bool",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT tmdb_id FROM movies WHERE id = ?",
"describe": {
"columns": [
{
"name": "tmdb_id",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "1612f76ea880bbd06a396b3043c21bbc42c5d412e31d2303b45813efa52201b9"
}
@@ -0,0 +1,194 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, poster_path, vote_average, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE tmdb_id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "root_id"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "wanted"
}
}
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "overrides"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "state"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "blocked"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "last_searched_at"
}
}
},
{
"name": "poster_path",
"ordinal": 12,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 13,
"type_info": "Float",
"origin": {
"Table": {
"table": "movies",
"name": "vote_average"
}
}
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 14,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "waiver"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
"hash": "16778fe075b61babcb7f5436113e91bf5f86e9a968d7b61f12daa022cc27f4d1"
}
@@ -0,0 +1,69 @@
{
"db_name": "SQLite",
"query": "SELECT e.id AS \"episode_id!: i64\", mf.path AS \"path!: String\", mf.size AS \"size!: i64\", mf.probed AS \"probed?: serde_json::Value\", json_extract(mf.waiver, '$.rule') AS \"waiver?: String\" FROM media_files mf JOIN episodes e ON mf.owner_kind = 'episode' AND e.id = mf.owner_id JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ? ORDER BY mf.path",
"describe": {
"columns": [
{
"name": "episode_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "path!: String",
"ordinal": 1,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "path"
}
}
},
{
"name": "size!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "media_files",
"name": "size"
}
}
},
{
"name": "probed?: serde_json::Value",
"ordinal": 3,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "probed"
}
}
},
{
"name": "waiver?: String",
"ordinal": 4,
"type_info": "Null",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
null
]
},
"hash": "17c53bd3b8dee72d62a23d41b7bcd6329037fe678ed628ea3ee92d14c7692540"
}
@@ -1,27 +1,51 @@
{
"db_name": "SQLite",
"query": "\n SELECT s.id AS \"series_id!: i64\", s.title AS \"title!: String\", s.year,\n g.target_id AS \"episode_id!: i64\"\n FROM grabs g\n JOIN episodes e ON g.target_kind = 'episode' AND e.id = g.target_id\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n WHERE g.state = 'failed'\n GROUP BY s.id, s.title, s.year, e.id\n HAVING count(DISTINCT g.release_id) >= 2\n ",
"query": "\n SELECT s.id AS \"series_id!: i64\", s.title AS \"title!: String\", s.year,\n g.target_id AS \"episode_id!: i64\"\n FROM grabs g\n JOIN episodes e ON g.target_kind = 'episode' AND e.id = g.target_id\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n WHERE g.state = 'failed'\n AND e.wanted = 1 AND e.state != 'available'\n GROUP BY s.id, s.title, s.year, e.id\n HAVING count(DISTINCT g.release_id) >= 2\n ",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "title!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 2,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "episode_id!: i64",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "target_id"
}
}
}
],
"parameters": {
@@ -34,5 +58,5 @@
false
]
},
"hash": "faa9e5cf0cf869161dd4878f6fb8707e378b7d9c6516d602afb49b1e30792207"
"hash": "1878841679d1664139dfedffae9d97ed1764321d76022ff55684969be0171cb6"
}
@@ -0,0 +1,21 @@
{
"db_name": "SQLite",
"query": "SELECT EXISTS(\n SELECT 1 FROM media_files f JOIN episodes e ON e.id = f.owner_id\n WHERE f.owner_kind = 'episode' AND e.season_id = ?\n ) AS \"exists!: bool\"",
"describe": {
"columns": [
{
"name": "exists!: bool",
"ordinal": 0,
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "1b594ec9db13ac2eacffe98d8cb60547c4fbac9959c79a59e2192c5fb448b4bb"
}
@@ -0,0 +1,182 @@
{
"db_name": "SQLite",
"query": "\n SELECT s.overrides AS \"overrides!: String\",\n r.id AS \"root_id!: i64\",\n r.kind AS \"root_kind!: String\",\n r.audience AS \"root_audience!: String\",\n r.path AS \"root_path!: String\",\n p.id AS \"policy_id!: i64\",\n p.name AS \"policy_name!: String\",\n p.required_audio AS \"required_audio!: String\",\n p.dub_blacklist AS \"dub_blacklist!: String\",\n p.hdr_rules AS \"hdr_rules!: String\",\n p.size_bands AS \"size_bands!: String\",\n p.resolution_pref AS \"resolution_pref!: String\",\n p.source_weights AS \"source_weights!: String\",\n p.score_weights AS \"score_weights!: String\"\n FROM series s\n JOIN roots r ON r.id = s.root_id\n JOIN policies p ON p.id = r.policy_id\n WHERE s.id = ?\n ",
"describe": {
"columns": [
{
"name": "overrides!: String",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "overrides"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "roots",
"name": "id"
}
}
},
{
"name": "root_kind!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "kind"
}
}
},
{
"name": "root_audience!: String",
"ordinal": 3,
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "audience"
}
}
},
{
"name": "root_path!: String",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
},
{
"name": "policy_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "policies",
"name": "id"
}
}
},
{
"name": "policy_name!: String",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
},
{
"name": "required_audio!: String",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "required_audio"
}
}
},
{
"name": "dub_blacklist!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "dub_blacklist"
}
}
},
{
"name": "hdr_rules!: String",
"ordinal": 9,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "hdr_rules"
}
}
},
{
"name": "size_bands!: String",
"ordinal": 10,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "size_bands"
}
}
},
{
"name": "resolution_pref!: String",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "resolution_pref"
}
}
},
{
"name": "source_weights!: String",
"ordinal": 12,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "source_weights"
}
}
},
{
"name": "score_weights!: String",
"ordinal": 13,
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "score_weights"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false
]
},
"hash": "1f67ae5af28115d22ad5e2fde1df8ee0f4aeb615e1d29c9cae03a589c7a6bdd4"
}
@@ -0,0 +1,146 @@
{
"db_name": "SQLite",
"query": "\n SELECT g.id AS \"grab_id!: i64\",\n g.infohash AS \"infohash!: String\",\n se.id AS \"season_id!: i64\",\n se.number AS \"season_number!: i64\",\n s.id AS \"series_id!: i64\",\n s.tmdb_id AS \"series_tmdb_id!: i64\",\n s.title AS \"series_title!: String\",\n s.year AS \"series_year\",\n s.original_language,\n s.runtime_minutes,\n r.name AS \"release_name!: String\"\n FROM grabs g\n JOIN seasons se ON se.id = g.target_id\n JOIN series s ON s.id = se.series_id\n JOIN releases r ON r.id = g.release_id\n WHERE g.state = 'downloaded' AND g.target_kind = 'season'\n ORDER BY g.id\n ",
"describe": {
"columns": [
{
"name": "grab_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "id"
}
}
},
{
"name": "infohash!: String",
"ordinal": 1,
"type_info": "Text",
"origin": {
"Table": {
"table": "grabs",
"name": "infohash"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "series_id!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "series_tmdb_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "series_title!: String",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "series_year",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "runtime_minutes",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "runtime_minutes"
}
}
},
{
"name": "release_name!: String",
"ordinal": 10,
"type_info": "Text",
"origin": {
"Table": {
"table": "releases",
"name": "name"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
false
]
},
"hash": "1fa97a49b40502e95b7618ac8fed38ad03e58f95ec9636a79ef0c06b24635a67"
}
@@ -0,0 +1,33 @@
{
"db_name": "SQLite",
"query": "SELECT e.air_date,\n EXISTS (\n SELECT 1 FROM media_files f\n WHERE f.owner_kind = 'episode' AND f.owner_id = e.id\n ) AS \"has_file!: bool\"\n FROM episodes e\n WHERE e.season_id = ?",
"describe": {
"columns": [
{
"name": "air_date",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "has_file!: bool",
"ordinal": 1,
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false
]
},
"hash": "20c1cbcd9cc317b148357ff64e967e30032a438c4815816323cf62896398d2a2"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE media_files SET path = ?, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "20dd51ed5a7e54bb156d9a5eaf83621c69971e6dc0784f3d2c011c8e90a001d6"
}
@@ -6,72 +6,156 @@
{
"name": "overrides!: String",
"ordinal": 0,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "overrides"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "roots",
"name": "id"
}
}
},
{
"name": "root_kind!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "kind"
}
}
},
{
"name": "root_audience!: String",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "audience"
}
}
},
{
"name": "root_path!: String",
"ordinal": 4,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
},
{
"name": "policy_id!: i64",
"ordinal": 5,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "policies",
"name": "id"
}
}
},
{
"name": "policy_name!: String",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
},
{
"name": "required_audio!: String",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "required_audio"
}
}
},
{
"name": "dub_blacklist!: String",
"ordinal": 8,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "dub_blacklist"
}
}
},
{
"name": "hdr_rules!: String",
"ordinal": 9,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "hdr_rules"
}
}
},
{
"name": "size_bands!: String",
"ordinal": 10,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "size_bands"
}
}
},
{
"name": "resolution_pref!: String",
"ordinal": 11,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "resolution_pref"
}
}
},
{
"name": "source_weights!: String",
"ordinal": 12,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "source_weights"
}
}
},
{
"name": "score_weights!: String",
"ordinal": 13,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "score_weights"
}
}
}
],
"parameters": {
@@ -6,39 +6,75 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "roots",
"name": "id"
}
}
},
{
"name": "kind!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "kind"
}
}
},
{
"name": "audience!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "audience"
}
}
},
{
"name": "path!: String",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
},
{
"name": "policy_id",
"ordinal": 4,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "roots",
"name": "policy_id"
}
}
},
{
"name": "policy_name!: String",
"ordinal": 5,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
true,
false,
false,
false,
false,
@@ -0,0 +1,122 @@
{
"db_name": "SQLite",
"query": "SELECT s.id AS \"id!: i64\", s.tmdb_id AS \"tmdb_id!: i64\", s.title AS \"title!: String\", s.year, s.original_language, s.root_id AS \"root_id!: i64\", s.blocked AS \"blocked!: bool\", s.poster_path, s.vote_average FROM series s WHERE NOT EXISTS (SELECT 1 FROM json_each(?) token WHERE s.title NOT LIKE '%' || token.value || '%' ESCAPE '\\') ORDER BY s.title, s.year, s.id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "root_id"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "blocked"
}
}
},
{
"name": "poster_path",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 8,
"type_info": "Float",
"origin": {
"Table": {
"table": "series",
"name": "vote_average"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
true,
true
]
},
"hash": "268dc95276f57bf3c457c98d172ef5e6f9acf430ae419ca68dc3800b0390b5b7"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE seasons SET vanished = 0, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = ? AND vanished != 0",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "26e3da3ba98a6bb1bc371922a02bc8faa769b6ae37e2174c6712b4d1b5d4dadc"
}
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT last_pack_search_at FROM seasons WHERE id = ?",
"describe": {
"columns": [
{
"name": "last_pack_search_at",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "seasons",
"name": "last_pack_search_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
true
]
},
"hash": "2759a3a5fb0ca9d37560b8d89922c7c5618b25843192ffa28b9c13eacd0b9c26"
}
@@ -0,0 +1,98 @@
{
"db_name": "SQLite",
"query": "\n SELECT s.id AS \"series_id!: i64\", s.tmdb_id AS \"tmdb_id!: i64\",\n s.title AS \"title!: String\", s.year,\n e.id AS \"episode_id!: i64\",\n se.number AS \"season_number!: i64\", e.number AS \"episode_number!: i64\"\n FROM episodes e\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n JOIN roots root ON root.id = s.root_id\n WHERE root.audience = 'kids'\n AND s.blocked = 0\n AND e.wanted = 1 AND e.state = 'missing' AND e.search_attempts > 0\n AND NOT EXISTS (\n SELECT 1 FROM episode_releases er\n JOIN releases r ON r.id = er.release_id\n WHERE er.episode_id = e.id AND r.verdict IN ('eligible', 'waived')\n )\n ORDER BY se.number, e.number\n ",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "episode_id!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "episode_number!: i64",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
true,
false,
false,
false
]
},
"hash": "29d6fdda533e0552f5da24a8e5180e5935b3550ee2c024e09aef9b76fd47a708"
}
@@ -6,14 +6,20 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "id"
}
}
}
],
"parameters": {
"Right": 4
},
"nullable": [
true
null
]
},
"hash": "2d0b92ba9aa4bc257286a67f0d37e2182c4478153c9096c1522c5ab23ad472e9"
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT s.title AS \"title!: String\"\n FROM seasons se\n JOIN series s ON s.id = se.series_id\n WHERE se.id = ?",
"describe": {
"columns": [
{
"name": "title!: String",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "321ce3a18bd627b357ba6a98b958a8efb0c7af09fa6cff4b1f31fb963da58bd5"
}
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT path AS \"path!: String\"\n FROM media_files WHERE owner_kind = 'episode' AND owner_id = ?",
"describe": {
"columns": [
{
"name": "path!: String",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "path"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "32c562fdb70cabb3265e351583b6ac1579490b29da670fe9062117451911576a"
}
@@ -6,56 +6,94 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "number!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "air_date",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 4,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 5,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
},
{
"name": "has_file!: bool",
"ordinal": 6,
"type_info": "Null"
"type_info": "Integer",
"origin": "Expression"
},
{
"name": "in_flight!: bool",
"ordinal": 7,
"type_info": "Null"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false,
true,
false,
false,
true,
null,
null
false,
false
]
},
"hash": "33de7e17f5defa761de0d6e174dca40e2d883b9990bec497355422f5b5e6dfe5"
@@ -6,47 +6,101 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "policies",
"name": "id"
}
}
},
{
"name": "name!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
},
{
"name": "required_audio!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "required_audio"
}
}
},
{
"name": "dub_blacklist!: String",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "dub_blacklist"
}
}
},
{
"name": "hdr_rules!: String",
"ordinal": 4,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "hdr_rules"
}
}
},
{
"name": "size_bands!: String",
"ordinal": 5,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "size_bands"
}
}
},
{
"name": "resolution_pref!: String",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "resolution_pref"
}
}
},
{
"name": "source_weights!: String",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "source_weights"
}
}
},
{
"name": "score_weights!: String",
"ordinal": 8,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "score_weights"
}
}
}
],
"parameters": {
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM media_files WHERE owner_kind = 'episode' AND owner_id IN (\n SELECT e.id FROM episodes e JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "3531a16bd038c149465397a70c24c14ed005683c68f06d322409c5c2b39b84d1"
}
@@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "UPDATE movies\n SET title = ?, year = ?, original_language = ?, digital_release = ?,\n imdb_id = ?,\n metadata_refreshed_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now'),\n search_attempts = 0, last_searched_at = NULL,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ? AND (\n title IS NOT ? OR year IS NOT ? OR original_language IS NOT ?\n OR digital_release IS NOT ? OR imdb_id IS NOT ?\n )",
"describe": {
"columns": [],
"parameters": {
"Right": 11
},
"nullable": []
},
"hash": "369bc5ff5cf6b84b51bfb0b254a4a78db9b8c277a7e276b2ffb04c8064ce7cf8"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE episodes SET search_attempts = 0, last_searched_at = NULL,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE season_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "37622919b83dba5d63d2420fb0d8036f72347fbbbf8836e1ad495bfa66e6ebfc"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM title_owners WHERE title_kind = 'series' AND title_id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "3775aa6dbb8d3ae7de48c3fb5dc81eca64ac5fa5b410cb14d885af2a137693b7"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM episodes WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "3974fc9a150b9d1feb9401f7c8075a774d0570104d0b089fd2e5ed2e85e66f0c"
}
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE e.season_id = ?",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "season_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "title!: String",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "title"
}
}
},
{
"name": "air_date",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "state"
}
}
},
{
"name": "vanished!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "vanished"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true
]
},
"hash": "3a02f30ced2765dcdbf7575d680c1b4ab1db895065f65db4a99bb0a4dc6e71ed"
}
@@ -6,52 +6,102 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 4,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "wanted"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "root_id"
}
}
},
{
"name": "root_path!: String",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
},
{
"name": "created_at!: String",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "created_at"
}
}
},
{
"name": "file_count!: i64",
"ordinal": 8,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
},
{
"name": "size_on_disk!: i64",
"ordinal": 9,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
@@ -1,74 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "number!: i64",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "air_date",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "state!: String",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "search_attempts!: i64",
"ordinal": 8,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 9,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
false,
false,
true,
false,
false,
false,
true
]
},
"hash": "3b3165092d403797f233f7a926daab43aea1c78c508790a2cca230ce0cc73b26"
}
@@ -0,0 +1,182 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", tvdb_id, title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", auto_track AS \"auto_track!: bool\", overrides AS \"overrides!: serde_json::Value\", upstream_ended AS \"upstream_ended!: bool\", blocked AS \"blocked!: bool\", poster_path, vote_average, metadata_refreshed_at FROM series ORDER BY title, year, id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "tvdb_id",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tvdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 3,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "root_id"
}
}
},
{
"name": "auto_track!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "auto_track"
}
}
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "overrides"
}
}
},
{
"name": "upstream_ended!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "upstream_ended"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "blocked"
}
}
},
{
"name": "poster_path",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 12,
"type_info": "Float",
"origin": {
"Table": {
"table": "series",
"name": "vote_average"
}
}
},
{
"name": "metadata_refreshed_at",
"ordinal": 13,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "metadata_refreshed_at"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
true,
false,
true,
true,
false,
false,
false,
false,
false,
true,
true,
true
]
},
"hash": "3b518839d694b872f83005ca059d45d048a8c44efd78b75e08e74299fed072ea"
}
@@ -6,19 +6,31 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "id"
}
}
},
{
"name": "tracked!: bool",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "tracked"
}
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
true,
false,
false
]
},
@@ -0,0 +1,38 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", path AS \"path!: String\"\n FROM media_files WHERE owner_kind = 'movie' AND owner_id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "media_files",
"name": "id"
}
}
},
{
"name": "path!: String",
"ordinal": 1,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "path"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "3be9c350ef24a69490540379225d95d2949fe2a0f1f59d55d6272cca1bd431aa"
}
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE e.id = ?",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "season_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "title!: String",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "title"
}
}
},
{
"name": "air_date",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "state"
}
}
},
{
"name": "vanished!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "vanished"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true
]
},
"hash": "3c4fdf30427dc972e695940a7a98cbc7c1da617502c818e5dbe0f35c87b175d5"
}
@@ -1,12 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO series (tmdb_id, tvdb_id, title, year, original_language, root_id, auto_track, upstream_ended, blocked, overrides) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"query": "INSERT INTO series (tmdb_id, tvdb_id, title, year, original_language, root_id, auto_track, upstream_ended, blocked, overrides, poster_path, backdrop_path, vote_average, runtime_minutes) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 10
"Right": 14
},
"nullable": []
},
"hash": "88f8bbd8844d26dd81973b5cfd4cb5df34d72f53cd68578a47773eff0a10e054"
"hash": "3cc5524f3ac253e86de8618970a5413135a87ccbd8ec3f73e21ef9c73e8ba80c"
}
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", series_id AS \"series_id!: i64\", number AS \"number!: i64\" FROM seasons",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "series_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "number!: i64",
"ordinal": 2,
"type_info": "Integer"
}
],
"parameters": {
"Right": 0
},
"nullable": [
true,
false,
false
]
},
"hash": "3e3a42524f3e481eef0b896c20aac3cf11d578ee864e36412a6f70477fff8325"
}
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ?",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "season_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "title!: String",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "title"
}
}
},
{
"name": "air_date",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "state"
}
}
},
{
"name": "vanished!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "vanished"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true
]
},
"hash": "3ee558a18edee423eab6fe572f2a6f5bad8db69e0827e620264700f4affb3652"
}
@@ -0,0 +1,33 @@
{
"db_name": "SQLite",
"query": "\n SELECT e.air_date,\n EXISTS (\n SELECT 1 FROM media_files f\n WHERE f.owner_kind = 'episode' AND f.owner_id = e.id\n ) AS \"on_disk!: bool\"\n FROM episodes e\n WHERE e.season_id = ?\n ORDER BY e.number\n ",
"describe": {
"columns": [
{
"name": "air_date",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "on_disk!: bool",
"ordinal": 1,
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false
]
},
"hash": "3fc7d7e39520dc60fa81da21a4cae0c4a718e95f9718629f0aba9f3d00d179e1"
}
@@ -0,0 +1,21 @@
{
"db_name": "SQLite",
"query": "SELECT EXISTS(\n SELECT 1 FROM media_files\n WHERE owner_kind = 'episode' AND owner_id = ?\n ) AS \"exists!: bool\"",
"describe": {
"columns": [
{
"name": "exists!: bool",
"ordinal": 0,
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "40f68614d733827b00499cb65a4c9b0219c18d2321720c060e1d22bb398d7d3d"
}
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT s.title AS \"title!: String\"\n FROM episodes e\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n WHERE e.id = ?",
"describe": {
"columns": [
{
"name": "title!: String",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "4322e03b45c5a7ec6be51a33107586dc4f7682ab4edbd483d36fedbc985a27f4"
}
@@ -1,92 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 12,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "44886371d0d5966ce83ca4b10f6e4d424b5eb3598a8c9940e59ab23b4fae95f5"
}
@@ -6,7 +6,8 @@
{
"name": "count!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
@@ -1,80 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT s.id AS \"id!: i64\", s.tmdb_id AS \"tmdb_id!: i64\", s.tvdb_id, s.title AS \"title!: String\", s.year, s.original_language, s.root_id AS \"root_id!: i64\", s.auto_track AS \"auto_track!: bool\", s.overrides AS \"overrides!: serde_json::Value\", s.upstream_ended AS \"upstream_ended!: bool\", s.blocked AS \"blocked!: bool\" FROM series s JOIN title_owners t ON t.title_kind = 'series' AND t.title_id = s.id WHERE t.owner_id = ? ORDER BY s.title, s.year, s.id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "tvdb_id",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 4,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "auto_track!: bool",
"ordinal": 7,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "upstream_ended!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "blocked!: bool",
"ordinal": 10,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
true,
false,
true,
true,
false,
false,
false,
false,
false
]
},
"hash": "45d5b3f5e133289014b2f6e10fc14070b4b4ec2f18d97f7546f3b866004c404b"
}
@@ -0,0 +1,182 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", tvdb_id,\n title AS \"title!: String\", year, original_language,\n root_id AS \"root_id!: i64\", auto_track AS \"auto_track!: bool\",\n upstream_ended AS \"upstream_ended!: bool\", metadata_refreshed_at,\n poster_path, backdrop_path, vote_average, runtime_minutes\n FROM series WHERE id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "tvdb_id",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tvdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 3,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "root_id"
}
}
},
{
"name": "auto_track!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "auto_track"
}
}
},
{
"name": "upstream_ended!: bool",
"ordinal": 8,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "upstream_ended"
}
}
},
{
"name": "metadata_refreshed_at",
"ordinal": 9,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "metadata_refreshed_at"
}
}
},
{
"name": "poster_path",
"ordinal": 10,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "poster_path"
}
}
},
{
"name": "backdrop_path",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "backdrop_path"
}
}
},
{
"name": "vote_average",
"ordinal": 12,
"type_info": "Float",
"origin": {
"Table": {
"table": "series",
"name": "vote_average"
}
}
},
{
"name": "runtime_minutes",
"ordinal": 13,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "runtime_minutes"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
true,
false,
true,
true,
false,
false,
false,
true,
true,
true,
true,
true
]
},
"hash": "4af1ce70996a3dc496b0ff507b8c70a43cde5f8b79ea02483047626fc11bc377"
}
@@ -6,22 +6,46 @@
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "title!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 2,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "target_id"
}
}
}
],
"parameters": {
@@ -6,12 +6,24 @@
{
"name": "title_id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "title_owners",
"name": "title_id"
}
}
},
{
"name": "owner_id!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "title_owners",
"name": "owner_id"
}
}
}
],
"parameters": {
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO season_releases (season_id, release_id) VALUES (?, ?)\n ON CONFLICT DO NOTHING",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "5184ffb7e40d1660eb5c78971c278a2b2705c65da7c037e1c5af062bc53e0345"
}
@@ -0,0 +1,81 @@
{
"db_name": "SQLite",
"query": "\n SELECT se.id AS \"season_id!: i64\",\n se.number AS \"season_number!: i64\",\n s.title AS \"series_title!: String\",\n s.tvdb_id AS series_tvdb_id,\n s.original_language,\n (\n EXISTS (\n SELECT 1 FROM episodes e\n WHERE e.season_id = se.id\n AND e.wanted = 1\n AND NOT EXISTS (\n SELECT 1 FROM media_files f\n WHERE f.owner_kind = 'episode' AND f.owner_id = e.id\n )\n AND NOT EXISTS (\n SELECT 1 FROM grabs g\n WHERE g.target_kind = 'episode' AND g.target_id = e.id\n AND g.state IN ('sent', 'downloaded', 'imported')\n )\n )\n AND NOT EXISTS (\n SELECT 1 FROM grabs g\n WHERE g.target_kind = 'season' AND g.target_id = se.id\n AND g.state IN ('sent', 'downloaded', 'imported')\n )\n ) AS \"is_gap!: bool\"\n FROM seasons se\n JOIN series s ON s.id = se.series_id\n WHERE se.id = ?\n AND s.blocked = 0\n ",
"describe": {
"columns": [
{
"name": "season_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "series_title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "series_tvdb_id",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tvdb_id"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "is_gap!: bool",
"ordinal": 5,
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false
]
},
"hash": "519d77ceec9ce13aa65abed28ea32db6568360e8c3fc7e31e968508d88c1bc67"
}
@@ -0,0 +1,194 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, poster_path, vote_average, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "root_id"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "wanted"
}
}
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "overrides"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "state"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "blocked"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "last_searched_at"
}
}
},
{
"name": "poster_path",
"ordinal": 12,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 13,
"type_info": "Float",
"origin": {
"Table": {
"table": "movies",
"name": "vote_average"
}
}
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 14,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "waiver"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
"hash": "53a2b5bcc6a753b8ef0a5f4110a69cc8ece28966cfa003f4bfe1190c55831a23"
}
@@ -6,7 +6,13 @@
{
"name": "path!: String",
"ordinal": 0,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "path"
}
}
}
],
"parameters": {
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ? ORDER BY se.number DESC, e.number DESC",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "season_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "title!: String",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "title"
}
}
},
{
"name": "air_date",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "state"
}
}
},
{
"name": "vanished!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "vanished"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true
]
},
"hash": "580e3bf81062d253fd08c9a4e1a879a0e57d6357ab9b278503cdf8fb5252886a"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE episodes\n SET wanted = ?,\n state = CASE WHEN state = 'available' THEN 'missing' ELSE state END,\n updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now')\n WHERE id = ?",
"describe": {
"columns": [],
"parameters": {
"Right": 2
},
"nullable": []
},
"hash": "58fe68be59f015fd8214306483c0d45fcc4b2ac595d3b04efb224b3e426cc1cf"
}
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT r.path AS \"path!: String\"\n FROM roots r\n JOIN series s ON s.root_id = r.id\n JOIN seasons se ON se.series_id = s.id\n JOIN episodes e ON e.season_id = se.id\n WHERE e.id = ?",
"describe": {
"columns": [
{
"name": "path!: String",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "5b059a2f93a3fb46b6c55e0b665aa55931045af290894e396b3b410123bfd539"
}
@@ -1,92 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT m.id AS \"id!: i64\", m.tmdb_id AS \"tmdb_id!: i64\", m.title AS \"title!: String\", m.year, m.original_language, m.root_id AS \"root_id!: i64\", m.wanted AS \"wanted!: bool\", m.overrides AS \"overrides!: serde_json::Value\", m.state AS \"state!: String\", m.blocked AS \"blocked!: bool\", m.search_attempts AS \"search_attempts!: i64\", m.last_searched_at, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = m.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies m JOIN title_owners t ON t.title_kind = 'movie' AND t.title_id = m.id WHERE t.owner_id = ? ORDER BY m.title, m.year, m.id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 12,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "5fc9aa28b8329895c03c7be43024069d8a065ddd37ea77bb3058aa8ec1cab52e"
}
@@ -1,92 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies ORDER BY title, year, id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 12,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "61e9081eaedc7a69ada44b057c59553511e64634b75386d523f82c2d03d78f1a"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "UPDATE episodes SET vanished = 1, updated_at = strftime('%Y-%m-%dT%H:%M:%fZ', 'now') WHERE id = ? AND vanished = 0",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "625b669e6a408eec81bbb235fb2eb3922336dfebee6f3fec7987fd538e472c34"
}
@@ -0,0 +1,194 @@
{
"db_name": "SQLite",
"query": "SELECT m.id AS \"id!: i64\", m.tmdb_id AS \"tmdb_id!: i64\", m.title AS \"title!: String\", m.year, m.original_language, m.root_id AS \"root_id!: i64\", m.wanted AS \"wanted!: bool\", m.overrides AS \"overrides!: serde_json::Value\", m.state AS \"state!: String\", m.blocked AS \"blocked!: bool\", m.search_attempts AS \"search_attempts!: i64\", m.last_searched_at, m.poster_path, m.vote_average, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = m.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies m JOIN title_owners t ON t.title_kind = 'movie' AND t.title_id = m.id WHERE t.owner_id = ? ORDER BY m.title, m.year, m.id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "root_id"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "wanted"
}
}
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "overrides"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "state"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "blocked"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "last_searched_at"
}
}
},
{
"name": "poster_path",
"ordinal": 12,
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 13,
"type_info": "Float",
"origin": {
"Table": {
"table": "movies",
"name": "vote_average"
}
}
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 14,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "waiver"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true,
true,
true
]
},
"hash": "6394f95e9e437ed3c46bb325c2d946ce75f94e00bf0d3aa6ac54811080725cc2"
}
@@ -6,24 +6,42 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "owners",
"name": "id"
}
}
},
{
"name": "name!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "owners",
"name": "name"
}
}
},
{
"name": "ntfy_topic!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "owners",
"name": "ntfy_topic"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false,
false
]
@@ -1,92 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE tmdb_id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 12,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "6a25900e3815470be997f96bfee10f2079242e8d755da6387dbb8a0f40fe6ea1"
}
@@ -6,42 +6,90 @@
{
"name": "name!: String",
"ordinal": 0,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
},
{
"name": "required_audio!: String",
"ordinal": 1,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "required_audio"
}
}
},
{
"name": "dub_blacklist!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "dub_blacklist"
}
}
},
{
"name": "hdr_rules!: String",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "hdr_rules"
}
}
},
{
"name": "size_bands!: String",
"ordinal": 4,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "size_bands"
}
}
},
{
"name": "resolution_pref!: String",
"ordinal": 5,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "resolution_pref"
}
}
},
{
"name": "source_weights!: String",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "source_weights"
}
}
},
{
"name": "score_weights!: String",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "score_weights"
}
}
}
],
"parameters": {
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "season_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "title!: String",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "title"
}
}
},
{
"name": "air_date",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "state"
}
}
},
{
"name": "vanished!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "vanished"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true
]
},
"hash": "6bda2cef202e94b64f7bbcf88bbed823cca790c1439d94fba1c7dcea024d9467"
}
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT path AS \"path!: String\" FROM roots WHERE id = ?",
"describe": {
"columns": [
{
"name": "path!: String",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false
]
},
"hash": "6ef45d7e6fc113b578fab91148f9ab5455e7a2d06fc86291e2c6c9696fd08953"
}
@@ -0,0 +1,122 @@
{
"db_name": "SQLite",
"query": "SELECT s.id AS \"id!: i64\", s.tmdb_id AS \"tmdb_id!: i64\", s.title AS \"title!: String\", s.year, s.original_language, s.root_id AS \"root_id!: i64\", s.blocked AS \"blocked!: bool\", s.poster_path, s.vote_average FROM series s WHERE s.tmdb_id = ? OR NOT EXISTS (SELECT 1 FROM json_each(?) token WHERE s.title NOT LIKE '%' || token.value || '%' ESCAPE '\\') ORDER BY s.title, s.year, s.id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "root_id"
}
}
},
{
"name": "blocked!: bool",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "blocked"
}
}
},
{
"name": "poster_path",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "poster_path"
}
}
},
{
"name": "vote_average",
"ordinal": 8,
"type_info": "Float",
"origin": {
"Table": {
"table": "series",
"name": "vote_average"
}
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
true,
true
]
},
"hash": "6f41ffaa0679bbbe51ea5d54fbdbf757e0f85d1d86ee6322253f223fae49265f"
}
@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "DELETE FROM media_files WHERE owner_kind = 'episode' AND owner_id IN (\n SELECT e.id FROM episodes e WHERE e.season_id = ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "6feaa1abb79ce2a0298bef052d3b731e8ccec88228f7a81b2e8ff5cee76f3fa4"
}
@@ -1,80 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", tvdb_id, title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", auto_track AS \"auto_track!: bool\", overrides AS \"overrides!: serde_json::Value\", upstream_ended AS \"upstream_ended!: bool\", blocked AS \"blocked!: bool\" FROM series WHERE id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "tvdb_id",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 4,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "auto_track!: bool",
"ordinal": 7,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "upstream_ended!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "blocked!: bool",
"ordinal": 10,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
true,
false,
true,
true,
false,
false,
false,
false,
false
]
},
"hash": "71534a7c100984bfe082a1348474263fa67c980e532fc037cc77b82c1109ecaa"
}
@@ -6,72 +6,156 @@
{
"name": "overrides!: String",
"ordinal": 0,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "overrides"
}
}
},
{
"name": "root_id!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "roots",
"name": "id"
}
}
},
{
"name": "root_kind!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "kind"
}
}
},
{
"name": "root_audience!: String",
"ordinal": 3,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "audience"
}
}
},
{
"name": "root_path!: String",
"ordinal": 4,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "roots",
"name": "path"
}
}
},
{
"name": "policy_id!: i64",
"ordinal": 5,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "policies",
"name": "id"
}
}
},
{
"name": "policy_name!: String",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "name"
}
}
},
{
"name": "required_audio!: String",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "required_audio"
}
}
},
{
"name": "dub_blacklist!: String",
"ordinal": 8,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "dub_blacklist"
}
}
},
{
"name": "hdr_rules!: String",
"ordinal": 9,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "hdr_rules"
}
}
},
{
"name": "size_bands!: String",
"ordinal": 10,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "size_bands"
}
}
},
{
"name": "resolution_pref!: String",
"ordinal": 11,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "resolution_pref"
}
}
},
{
"name": "source_weights!: String",
"ordinal": 12,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "source_weights"
}
}
},
{
"name": "score_weights!: String",
"ordinal": 13,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "policies",
"name": "score_weights"
}
}
}
],
"parameters": {
@@ -6,7 +6,8 @@
{
"name": "count!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
@@ -0,0 +1,86 @@
{
"db_name": "SQLite",
"query": "\n SELECT s.id AS \"series_id!: i64\", s.tmdb_id AS \"tmdb_id!: i64\",\n s.title AS \"title!: String\", s.year,\n g.target_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\"\n FROM grabs g\n JOIN seasons se ON g.target_kind = 'season' AND se.id = g.target_id\n JOIN series s ON s.id = se.series_id\n WHERE g.state = 'failed'\n GROUP BY s.id, s.tmdb_id, s.title, s.year, se.id, se.number\n ",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "target_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
true,
false,
false
]
},
"hash": "7930e2d10b25627dcbf81f60a5ac077c27b647a6f0b411e13105398a2963cd51"
}
@@ -6,17 +6,35 @@
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "number!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "tracked!: bool",
"ordinal": 2,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "tracked"
}
}
}
],
"parameters": {
@@ -1,74 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT g.id AS \"grab_id!: i64\",\n g.infohash AS \"infohash!: String\",\n se.id AS \"season_id!: i64\",\n se.number AS \"season_number!: i64\",\n s.id AS \"series_id!: i64\",\n s.tmdb_id AS \"series_tmdb_id!: i64\",\n s.title AS \"series_title!: String\",\n s.year AS \"series_year\",\n s.original_language,\n r.name AS \"release_name!: String\"\n FROM grabs g\n JOIN seasons se ON se.id = g.target_id\n JOIN series s ON s.id = se.series_id\n JOIN releases r ON r.id = g.release_id\n WHERE g.state = 'downloaded' AND g.target_kind = 'season'\n ORDER BY g.id\n ",
"describe": {
"columns": [
{
"name": "grab_id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "infohash!: String",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "series_id!: i64",
"ordinal": 4,
"type_info": "Integer"
},
{
"name": "series_tmdb_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "series_title!: String",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "series_year",
"ordinal": 7,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "release_name!: String",
"ordinal": 9,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
true,
false,
false,
false,
false,
false,
false,
true,
true,
false
]
},
"hash": "7963cce11a588f8b8697e596da24802e4a5556c388b84fe7a6102444a887c2cc"
}
@@ -1,92 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", wanted AS \"wanted!: bool\", overrides AS \"overrides!: serde_json::Value\", state AS \"state!: String\", blocked AS \"blocked!: bool\", search_attempts AS \"search_attempts!: i64\", last_searched_at, (SELECT f.waiver FROM media_files f WHERE f.owner_kind = 'movie' AND f.owner_id = movies.id AND f.waiver IS NOT NULL ORDER BY f.id LIMIT 1) AS \"waiver?: serde_json::Value\" FROM movies WHERE NOT EXISTS (SELECT 1 FROM json_each(?) token WHERE title NOT LIKE '%' || token.value || '%' ESCAPE '\\') ORDER BY title, year, id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "blocked!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text"
},
{
"name": "waiver?: serde_json::Value",
"ordinal": 12,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
true,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "7b6b0d6bbfcd752bd3a9d97f8d64529bd7aab96ad817fdb9ac9829a525a9f1d7"
}
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", se.number AS \"season_number!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.vanished AS \"vanished!: bool\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE e.season_id = ?",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "series_id"
}
}
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "season_id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "title!: String",
"ordinal": 5,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "title"
}
}
},
{
"name": "air_date",
"ordinal": 6,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "state!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "state"
}
}
},
{
"name": "vanished!: bool",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "vanished"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "last_searched_at"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
true,
false,
false,
false,
false,
true
]
},
"hash": "7c638b148b697645d250fe43cf7fcc049e3754e5b1837ff54289e8908523d40c"
}
@@ -1,80 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", tmdb_id AS \"tmdb_id!: i64\", tvdb_id, title AS \"title!: String\", year, original_language, root_id AS \"root_id!: i64\", auto_track AS \"auto_track!: bool\", overrides AS \"overrides!: serde_json::Value\", upstream_ended AS \"upstream_ended!: bool\", blocked AS \"blocked!: bool\" FROM series ORDER BY title, year, id",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "tvdb_id",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "year",
"ordinal": 4,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "root_id!: i64",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "auto_track!: bool",
"ordinal": 7,
"type_info": "Integer"
},
{
"name": "overrides!: serde_json::Value",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "upstream_ended!: bool",
"ordinal": 9,
"type_info": "Integer"
},
{
"name": "blocked!: bool",
"ordinal": 10,
"type_info": "Integer"
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
true,
false,
true,
true,
false,
false,
false,
false,
false
]
},
"hash": "7c76ab54e1c32a1e98cfc04ffb709382d09fc1eea9f1ddf3b613446a4c1bdb31"
}
@@ -6,52 +6,107 @@
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "id"
}
}
},
{
"name": "tmdb_id!: i64",
"ordinal": 1,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "tmdb_id"
}
}
},
{
"name": "title!: String",
"ordinal": 2,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "title"
}
}
},
{
"name": "year",
"ordinal": 3,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 4,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
},
{
"name": "search_attempts!: i64",
"ordinal": 5,
"type_info": "Integer"
"type_info": "Integer",
"origin": {
"Table": {
"table": "movies",
"name": "search_attempts"
}
}
},
{
"name": "last_searched_at",
"ordinal": 6,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "last_searched_at"
}
}
},
{
"name": "digital_release",
"ordinal": 7,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "digital_release"
}
}
},
{
"name": "metadata_refreshed_at",
"ordinal": 8,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "metadata_refreshed_at"
}
}
},
{
"name": "is_gap!: i64",
"ordinal": 9,
"type_info": "Integer"
"type_info": "Integer",
"origin": "Expression"
}
],
"parameters": {
@@ -1,80 +0,0 @@
{
"db_name": "SQLite",
"query": "\n SELECT g.id AS \"grab_id!: i64\",\n g.infohash AS \"infohash!: String\",\n e.id AS \"episode_id!: i64\",\n se.id AS \"season_id!: i64\",\n se.number AS \"season_number!: i64\",\n s.id AS \"series_id!: i64\",\n s.tmdb_id AS \"series_tmdb_id!: i64\",\n s.title AS \"series_title!: String\",\n s.year AS \"series_year\",\n s.original_language,\n r.name AS \"release_name!: String\"\n FROM grabs g\n JOIN episodes e ON e.id = g.target_id\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n JOIN releases r ON r.id = g.release_id\n WHERE g.state = 'downloaded' AND g.target_kind = 'episode'\n ORDER BY g.id\n ",
"describe": {
"columns": [
{
"name": "grab_id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "infohash!: String",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "episode_id!: i64",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "season_id!: i64",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "season_number!: i64",
"ordinal": 4,
"type_info": "Integer"
},
{
"name": "series_id!: i64",
"ordinal": 5,
"type_info": "Integer"
},
{
"name": "series_tmdb_id!: i64",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "series_title!: String",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "series_year",
"ordinal": 8,
"type_info": "Integer"
},
{
"name": "original_language",
"ordinal": 9,
"type_info": "Text"
},
{
"name": "release_name!: String",
"ordinal": 10,
"type_info": "Text"
}
],
"parameters": {
"Right": 0
},
"nullable": [
true,
false,
false,
false,
false,
false,
false,
false,
true,
true,
false
]
},
"hash": "7f94d0bad8dd346c5e930c2606c8643e732850b0a1ec331e216c3aedf6987ad4"
}
@@ -6,7 +6,13 @@
{
"name": "original_language",
"ordinal": 0,
"type_info": "Text"
"type_info": "Text",
"origin": {
"Table": {
"table": "movies",
"name": "original_language"
}
}
}
],
"parameters": {
@@ -1,74 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT se.series_id AS \"series_id!: i64\", e.id AS \"id!: i64\", e.season_id AS \"season_id!: i64\", e.number AS \"number!: i64\", e.title AS \"title!: String\", e.air_date, e.wanted AS \"wanted!: bool\", e.state AS \"state!: String\", e.search_attempts AS \"search_attempts!: i64\", e.last_searched_at\n FROM episodes e JOIN seasons se ON se.id = e.season_id WHERE se.series_id = ?",
"describe": {
"columns": [
{
"name": "series_id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "season_id!: i64",
"ordinal": 2,
"type_info": "Integer"
},
{
"name": "number!: i64",
"ordinal": 3,
"type_info": "Integer"
},
{
"name": "title!: String",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "air_date",
"ordinal": 5,
"type_info": "Text"
},
{
"name": "wanted!: bool",
"ordinal": 6,
"type_info": "Integer"
},
{
"name": "state!: String",
"ordinal": 7,
"type_info": "Text"
},
{
"name": "search_attempts!: i64",
"ordinal": 8,
"type_info": "Integer"
},
{
"name": "last_searched_at",
"ordinal": 9,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
true,
false,
false,
false,
true,
false,
false,
false,
true
]
},
"hash": "7fc4e02be63e223a60b1bf7d78f68aad4106abc0e17f7da6b98efd818ecdc372"
}
@@ -0,0 +1,74 @@
{
"db_name": "SQLite",
"query": "\n SELECT r.id AS \"id!: i64\",\n r.size AS \"size!: i64\",\n r.parsed AS \"parsed!: serde_json::Value\",\n r.verdict,\n r.rejected_rule\n FROM releases r\n WHERE r.id IN (\n SELECT er.release_id\n FROM episode_releases er\n JOIN episodes e ON e.id = er.episode_id\n JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?\n UNION\n SELECT sr.release_id\n FROM season_releases sr\n JOIN seasons se ON se.id = sr.season_id\n WHERE se.series_id = ?\n )\n ",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "releases",
"name": "id"
}
}
},
{
"name": "size!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "releases",
"name": "size"
}
}
},
{
"name": "parsed!: serde_json::Value",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "releases",
"name": "parsed"
}
}
},
{
"name": "verdict",
"ordinal": 3,
"type_info": "Text",
"origin": {
"Table": {
"table": "releases",
"name": "verdict"
}
}
},
{
"name": "rejected_rule",
"ordinal": 4,
"type_info": "Text",
"origin": {
"Table": {
"table": "releases",
"name": "rejected_rule"
}
}
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
true,
true
]
},
"hash": "7fe60916664f3552cd111e45586c58997079821e2521a196174f4182e41531ad"
}
@@ -0,0 +1,136 @@
{
"db_name": "SQLite",
"query": "\n SELECT e.id AS \"id!: i64\",\n e.number AS \"number!: i64\",\n e.air_date,\n e.wanted AS \"wanted!: bool\",\n EXISTS (\n SELECT 1 FROM media_files f\n WHERE f.owner_kind = 'episode' AND f.owner_id = e.id\n ) AS \"has_file!: bool\",\n EXISTS (\n SELECT 1 FROM grabs g\n WHERE g.target_kind = 'episode' AND g.target_id = e.id\n AND g.state IN ('sent', 'downloaded', 'imported')\n ) AS \"in_flight!: bool\",\n se.id AS \"season_id!: i64\",\n se.number AS \"season_number!: i64\",\n s.title AS \"series_title!: String\",\n s.tvdb_id AS series_tvdb_id,\n s.original_language\n FROM episodes e\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n WHERE e.id = ?\n AND s.blocked = 0\n ",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "number!: i64",
"ordinal": 1,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "number"
}
}
},
{
"name": "air_date",
"ordinal": 2,
"type_info": "Text",
"origin": {
"Table": {
"table": "episodes",
"name": "air_date"
}
}
},
{
"name": "wanted!: bool",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "wanted"
}
}
},
{
"name": "has_file!: bool",
"ordinal": 4,
"type_info": "Integer",
"origin": "Expression"
},
{
"name": "in_flight!: bool",
"ordinal": 5,
"type_info": "Integer",
"origin": "Expression"
},
{
"name": "season_id!: i64",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 7,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "series_title!: String",
"ordinal": 8,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "series_tvdb_id",
"ordinal": 9,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tvdb_id"
}
}
},
{
"name": "original_language",
"ordinal": 10,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
true
]
},
"hash": "80210068b65f85f4e6840a98defa7271c33b1da4ec9f6389b8d7212be80c97ea"
}
@@ -1,32 +0,0 @@
{
"db_name": "SQLite",
"query": "SELECT id AS \"id!: i64\", series_id AS \"series_id!: i64\", number AS \"number!: i64\" FROM seasons WHERE series_id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer"
},
{
"name": "series_id!: i64",
"ordinal": 1,
"type_info": "Integer"
},
{
"name": "number!: i64",
"ordinal": 2,
"type_info": "Integer"
}
],
"parameters": {
"Right": 1
},
"nullable": [
true,
false,
false
]
},
"hash": "808c20cad25bdb0d81ac502379dcf72c77bb581bc0fdff7b2728cfa13712eb10"
}
@@ -0,0 +1,158 @@
{
"db_name": "SQLite",
"query": "\n SELECT g.id AS \"grab_id!: i64\",\n g.infohash AS \"infohash!: String\",\n e.id AS \"episode_id!: i64\",\n se.id AS \"season_id!: i64\",\n se.number AS \"season_number!: i64\",\n s.id AS \"series_id!: i64\",\n s.tmdb_id AS \"series_tmdb_id!: i64\",\n s.title AS \"series_title!: String\",\n s.year AS \"series_year\",\n s.original_language,\n s.runtime_minutes,\n r.name AS \"release_name!: String\"\n FROM grabs g\n JOIN episodes e ON e.id = g.target_id\n JOIN seasons se ON se.id = e.season_id\n JOIN series s ON s.id = se.series_id\n JOIN releases r ON r.id = g.release_id\n WHERE g.state = 'downloaded' AND g.target_kind = 'episode'\n ORDER BY g.id\n ",
"describe": {
"columns": [
{
"name": "grab_id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "grabs",
"name": "id"
}
}
},
{
"name": "infohash!: String",
"ordinal": 1,
"type_info": "Text",
"origin": {
"Table": {
"table": "grabs",
"name": "infohash"
}
}
},
{
"name": "episode_id!: i64",
"ordinal": 2,
"type_info": "Integer",
"origin": {
"Table": {
"table": "episodes",
"name": "id"
}
}
},
{
"name": "season_id!: i64",
"ordinal": 3,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "id"
}
}
},
{
"name": "season_number!: i64",
"ordinal": 4,
"type_info": "Integer",
"origin": {
"Table": {
"table": "seasons",
"name": "number"
}
}
},
{
"name": "series_id!: i64",
"ordinal": 5,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "id"
}
}
},
{
"name": "series_tmdb_id!: i64",
"ordinal": 6,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "tmdb_id"
}
}
},
{
"name": "series_title!: String",
"ordinal": 7,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "title"
}
}
},
{
"name": "series_year",
"ordinal": 8,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "year"
}
}
},
{
"name": "original_language",
"ordinal": 9,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
},
{
"name": "runtime_minutes",
"ordinal": 10,
"type_info": "Integer",
"origin": {
"Table": {
"table": "series",
"name": "runtime_minutes"
}
}
},
{
"name": "release_name!: String",
"ordinal": 11,
"type_info": "Text",
"origin": {
"Table": {
"table": "releases",
"name": "name"
}
}
}
],
"parameters": {
"Right": 0
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
false
]
},
"hash": "81361374c5c84d4c12ac33fc103ab96ce79164dc551f388180c554034dec007b"
}
@@ -0,0 +1,26 @@
{
"db_name": "SQLite",
"query": "SELECT original_language FROM series WHERE id = ?",
"describe": {
"columns": [
{
"name": "original_language",
"ordinal": 0,
"type_info": "Text",
"origin": {
"Table": {
"table": "series",
"name": "original_language"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
true
]
},
"hash": "869e17a01bcf8710bb533dbe428af062e73659ee89ab4387e0a28b7d546f5be4"
}
@@ -0,0 +1,38 @@
{
"db_name": "SQLite",
"query": "SELECT mf.id AS \"id!: i64\", mf.path AS \"path!: String\"\n FROM media_files mf\n JOIN episodes e ON mf.owner_kind = 'episode' AND e.id = mf.owner_id\n JOIN seasons se ON se.id = e.season_id\n WHERE se.series_id = ?",
"describe": {
"columns": [
{
"name": "id!: i64",
"ordinal": 0,
"type_info": "Integer",
"origin": {
"Table": {
"table": "media_files",
"name": "id"
}
}
},
{
"name": "path!: String",
"ordinal": 1,
"type_info": "Text",
"origin": {
"Table": {
"table": "media_files",
"name": "path"
}
}
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false
]
},
"hash": "89fb1aa140a11bcd9bb082b2dcba50df414a77bc191755d515e5d5905a651adc"
}

Some files were not shown because too many files have changed in this diff Show More