This PR replaces the APScheduler lib with the Taskiq task queuing lib.
# why
APScheduler doesn't support FastAPI's DI in tasks, this makes them quite
cumbersome to read and write since DB, Repositories and Services all
need to be instanciated manually.
Moreover, Taskiq makes it easier to start background tasks from FastAPI
requests. This enables MM to move to a more event-based architecture.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* App now uses an orchestrated async startup/shutdown and runs
background scheduling via a database-backed task queue; startup enqueues
pre-load/import/update tasks.
* **Bug Fixes**
* Improved torrent client handling with clearer conflict messages and
guidance for manual resolution.
* Enhanced logging around season, episode and metadata update
operations; minor regex/behaviour formatting preserved.
* **Chores**
* Updated dependencies to support the new task queue and connection
pooling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Bumps
[@eslint/compat](https://github.com/eslint/rewrite/tree/HEAD/packages/compat)
from 1.4.1 to 2.0.2.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/releases"><code>@eslint/compat</code>'s
releases</a>.</em></p>
<blockquote>
<h2>compat: v2.0.2</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/compat-v2.0.1...compat-v2.0.2">2.0.2</a>
(2026-01-29)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>add eslint 10 as peer dependency (<a
href="https://redirect.github.com/eslint/rewrite/issues/361">#361</a>)
(<a
href="ecb37dcafc">ecb37dc</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/core</code> bumped from ^1.0.1 to ^1.1.0</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>migrate-config: v2.0.2</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/migrate-config-v2.0.1...migrate-config-v2.0.2">2.0.2</a>
(2026-01-29)</h2>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/compat</code> bumped from ^2.0.1 to ^2.0.2</li>
</ul>
</li>
<li>devDependencies
<ul>
<li><code>@eslint/core</code> bumped from ^1.0.1 to ^1.1.0</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>compat: v2.0.1</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/compat-v2.0.0...compat-v2.0.1">2.0.1</a>
(2026-01-08)</h2>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/core</code> bumped from ^1.0.0 to ^1.0.1</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>migrate-config: v2.0.1</h2>
<h2><a
href="https://github.com/eslint/rewrite/compare/migrate-config-v2.0.0...migrate-config-v2.0.1">2.0.1</a>
(2026-01-08)</h2>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/compat</code> bumped from ^2.0.0 to ^2.0.1</li>
</ul>
</li>
<li>devDependencies
<ul>
<li><code>@eslint/core</code> bumped from ^1.0.0 to ^1.0.1</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>compat: v2.0.0</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/eslint/rewrite/blob/main/packages/compat/CHANGELOG.md"><code>@eslint/compat</code>'s
changelog</a>.</em></p>
<blockquote>
<h2><a
href="https://github.com/eslint/rewrite/compare/compat-v2.0.1...compat-v2.0.2">2.0.2</a>
(2026-01-29)</h2>
<h3>Bug Fixes</h3>
<ul>
<li>add eslint 10 as peer dependency (<a
href="https://redirect.github.com/eslint/rewrite/issues/361">#361</a>)
(<a
href="ecb37dcafc">ecb37dc</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/core</code> bumped from ^1.0.1 to ^1.1.0</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2><a
href="https://github.com/eslint/rewrite/compare/compat-v2.0.0...compat-v2.0.1">2.0.1</a>
(2026-01-08)</h2>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/core</code> bumped from ^1.0.0 to ^1.0.1</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2><a
href="https://github.com/eslint/rewrite/compare/compat-v1.4.1...compat-v2.0.0">2.0.0</a>
(2025-11-14)</h2>
<h3>⚠ BREAKING CHANGES</h3>
<ul>
<li>Require Node.js ^20.19.0 || ^22.13.0 || >=24 (<a
href="https://redirect.github.com/eslint/rewrite/issues/297">#297</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>patch missing context and SourceCode methods for v10 (<a
href="https://redirect.github.com/eslint/rewrite/issues/311">#311</a>)
(<a
href="a40d8c60af">a40d8c6</a>)</li>
<li>Require Node.js ^20.19.0 || ^22.13.0 || >=24 (<a
href="https://redirect.github.com/eslint/rewrite/issues/297">#297</a>)
(<a
href="acc623c807">acc623c</a>)</li>
</ul>
<h3>Dependencies</h3>
<ul>
<li>The following workspace dependencies were updated
<ul>
<li>dependencies
<ul>
<li><code>@eslint/core</code> bumped from ^0.17.0 to ^1.0.0</li>
</ul>
</li>
</ul>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="7960653fe6"><code>7960653</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/compat/issues/356">#356</a>)</li>
<li><a
href="ecb37dcafc"><code>ecb37dc</code></a>
fix: add eslint 10 as peer dependency (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/compat/issues/361">#361</a>)</li>
<li><a
href="074cac2268"><code>074cac2</code></a>
docs: Update README sponsors</li>
<li><a
href="a3b0fd5102"><code>a3b0fd5</code></a>
docs: Update README sponsors</li>
<li><a
href="7abc05147e"><code>7abc051</code></a>
chore: release main (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/compat/issues/336">#336</a>)</li>
<li><a
href="f0b5b68e6d"><code>f0b5b68</code></a>
docs: Update README sponsors</li>
<li><a
href="b65204d085"><code>b65204d</code></a>
docs: Update README sponsors</li>
<li><a
href="5f8bc5b872"><code>5f8bc5b</code></a>
ci: run <code>arethetypeswrong</code> on packages with types (<a
href="https://github.com/eslint/rewrite/tree/HEAD/packages/compat/issues/338">#338</a>)</li>
<li><a
href="d9eb64a30a"><code>d9eb64a</code></a>
docs: Update README sponsors</li>
<li><a
href="7444f36783"><code>7444f36</code></a>
docs: Update README sponsors</li>
<li>Additional commits viewable in <a
href="https://github.com/eslint/rewrite/commits/compat-v2.0.2/packages/compat">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [sqlalchemy](https://github.com/sqlalchemy/sqlalchemy) from 2.0.45
to 2.0.47.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sqlalchemy/sqlalchemy/releases">sqlalchemy's
releases</a>.</em></p>
<blockquote>
<h1>2.0.47</h1>
<p>Released: February 24, 2026</p>
<h2>orm</h2>
<ul>
<li>
<p><strong>[orm] [bug]</strong> Fixed issue when using ORM mappings with
Python 3.14's <a href="https://peps.python.org/pep-0649">PEP 649</a>
feature
that no longer requires "future annotations", where the ORM's
introspection
of the <code>__init__</code> method of mapped classes would fail if
non-present
identifiers in annotations were present. The vendored
<code>getfullargspec()</code>
method has been amended to use <code>Format.FORWARDREF</code> under
Python 3.14 to
prevent resolution of names that aren't present.</p>
<p>References: <a
href="https://www.sqlalchemy.org/trac/ticket/13104">#13104</a></p>
</li>
</ul>
<h2>engine</h2>
<ul>
<li>
<p><strong>[engine] [usecase]</strong> The connection object returned by
<code>_engine.Engine.raw_connection()</code>
now supports the context manager protocol, automatically returning the
connection to the pool when exiting the context.</p>
<p>References: <a
href="https://www.sqlalchemy.org/trac/ticket/13116">#13116</a></p>
</li>
</ul>
<h2>postgresql</h2>
<ul>
<li>
<p><strong>[postgresql] [bug]</strong> Fixed an issue in the PostgreSQL
dialect where foreign key constraint
reflection would incorrectly swap or fail to capture
<code>onupdate</code> and
<code>ondelete</code> values when these clauses appeared in a different
order than
expected in the constraint definition. This issue primarily affected
PostgreSQL-compatible databases such as CockroachDB, which may return
<code>ON DELETE</code> before <code>ON UPDATE</code> in the constraint
definition string. The
reflection logic now correctly parses both clauses regardless of their
ordering.</p>
<p>References: <a
href="https://www.sqlalchemy.org/trac/ticket/13105">#13105</a></p>
</li>
<li>
<p><strong>[postgresql] [bug]</strong> Fixed issue in the
<code>engine_insertmanyvalues</code> feature where using
PostgreSQL's <code>ON CONFLICT</code> clause with
<code>_dml.Insert.returning.sort_by_parameter_order</code> enabled would
generate invalid SQL when the insert used an implicit sentinel
(server-side
autoincrement primary key). The generated SQL would incorrectly declare
a
sentinel counter column in the <code>imp_sen</code> table alias without
providing
corresponding values in the <code>VALUES</code> clause, leading to a
<code>ProgrammingError</code> indicating column count mismatch. The fix
allows batch
execution mode when <code>embed_values_counter</code> is active, as the
embedded
counter provides the ordering capability needed even with upsert
behaviors,
rather than unnecessarily downgrading to row-at-a-time execution.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/sqlalchemy/sqlalchemy/commits">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Fixs for #460
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Improvements**
* Refined keyword matching in indexer queries with case-insensitive,
word-boundary-aware search for more accurate results.
* **Bug Fixes**
* Corrected torrent URL redirect resolution logic.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
The base title scoring rule **avoid_cam** can be extended with more
keyword related to low quality videos similar to CAM.
| Type | Acronyms | Meaning |
|-----------|-------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| CAM | CAM<br>CAMRIP<br>HDCAM | A recording made with a handheld camera
in a movie theater. |
| Screener |
BDSCR<br>DDC<br>DVDSCR<br>DVDSCREENER<br>SCR<br>SCREENER<br>WEBSCREENER
| Screeners are early DVD or BD releases of the theatrical version of a
film, typically sent to movie reviewers, academy members and executives
for review purposes. |
| Telecine | HDTC<br>TC<br>TELECINE | A digital scan of the film print.
|
| Telesync | HDTS<br>TELESYNC<br>TS | Similar to *CAM*, but the camera
is typically placed closer to the projector or on a tripod in the
projection booth. Audio is captured directly from the sound system. |
| TV | TVRIP |
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Chores**
* Improved detection of additional camera-related content format
variants through updated filtering rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
## What
Two-line fix to the quality detection regex in
`media_manager/indexer/schemas.py`.
**UHD pattern**: `\b(4k)\b` → `\b(4k|2160p|uhd)\b`
**FullHD pattern**: `\b(1080p)\b` → `\b(1080p|fullhd|full\s*hd)\b`
## Why
The UHD regex only matched the literal keyword `4k`. Torrent titles
containing `2160p` or `UHD` (but not `4k`) were classified as
`Quality.unknown` (value 5) instead of `Quality.uhd` (value 1). Since
sorting uses quality as the primary key, these 4K releases ended up at
the bottom of search results.
### Example
| Title | Before | After |
|---|---|---|
| `Movie.2013.4K.HDR.2160p.x265` | ✅ `Quality.uhd` | ✅ `Quality.uhd` |
| `Movie.2013.UHD.BluRay.2160p.HDR10.x265` | ❌ `Quality.unknown` | ✅
`Quality.uhd` |
| `Movie.2013.2160p.WEBRip.DDP5.1.x264` | ❌ `Quality.unknown` | ✅
`Quality.uhd` |
All patterns already use `re.IGNORECASE`, so case variants are handled.
Fixes#449
---------
Co-authored-by: GokuPlay609 <GokuPlay609@users.noreply.github.com>
Co-authored-by: Amp <amp@ampcode.com>
Co-authored-by: maxid <97409287+maxdorninger@users.noreply.github.com>
**Description**
As explained on #322, MediaManager currently only matches torrents that
represent full seasons or season packs.
As a result, valid episode-based releases — commonly returned by
indexers such as EZTV — are filtered out during scoring and never
considered for download.
Initial changes to the season parsing logic allow these torrents to be
discovered.
However, additional changes are required beyond season parsing to
properly support single-episode imports.
This PR is intended as a work-in-progress / RFC to discuss the required
changes and align on the correct approach before completing the
implementation.
**Things planned to do**
[X] Update Web UI to better display episode-level details
[ ] Update TV show import logic to handle single episode files, instead
of assuming full season files (to avoid integrity errors when episodes
are missing)
[ ] Create episode file tables to store episode-level data, similar to
season files
[ ] Implement fetching and downloading logic for single-episode torrents
**Notes / current limitations**
At the moment, the database and import logic assume one file per season
per quality, which works for season packs but not for episode-based
releases.
These changes are intentionally not completed yet and are part of the
discussion this PR aims to start.
**Request for feedback**
This represents a significant change in how TV content is handled in
MediaManager.
Before proceeding further, feedback from @maxdorninger on the overall
direction and next steps would be greatly appreciated.
Once aligned, the remaining tasks can be implemented incrementally.
---------
Co-authored-by: Maximilian Dorninger <97409287+maxdorninger@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Bumps the uv group with 2 updates in the /metadata_relay directory:
[python-multipart](https://github.com/Kludex/python-multipart) and
[urllib3](https://github.com/urllib3/urllib3).
Updates `python-multipart` from 0.0.21 to 0.0.22
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/python-multipart/releases">python-multipart's
releases</a>.</em></p>
<blockquote>
<h2>Version 0.0.22</h2>
<h2>What's Changed</h2>
<ul>
<li>Drop directory path from filename in <code>File</code> <a
href="9433f4bbc9">9433f4b</a>.</li>
</ul>
<hr />
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Kludex/python-multipart/compare/0.0.21...0.0.22">https://github.com/Kludex/python-multipart/compare/0.0.21...0.0.22</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/python-multipart/blob/master/CHANGELOG.md">python-multipart's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.22 (2026-01-25)</h2>
<ul>
<li>Drop directory path from filename in <code>File</code> <a
href="9433f4bbc9">9433f4b</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bea7bbb290"><code>bea7bbb</code></a>
Version 0.0.22 (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/222">#222</a>)</li>
<li><a
href="0fb59a9df0"><code>0fb59a9</code></a>
chore: add return type on test (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/221">#221</a>)</li>
<li><a
href="9433f4bbc9"><code>9433f4b</code></a>
Merge commit from fork</li>
<li><a
href="d5c91ecb0a"><code>d5c91ec</code></a>
Bump the github-actions group with 2 updates (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/219">#219</a>)</li>
<li><a
href="5a90631b48"><code>5a90631</code></a>
bump uv (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/218">#218</a>)</li>
<li>See full diff in <a
href="https://github.com/Kludex/python-multipart/compare/0.0.21...0.0.22">compare
view</a></li>
</ul>
</details>
<br />
Updates `urllib3` from 2.6.2 to 2.6.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.6.3</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project after a sharp decline
in financial support. If your company or organization uses Python and
would benefit from HTTP/2 support in Requests, pip, cloud SDKs, and
thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Changes</h2>
<ul>
<li>Fixed a security issue where decompression-bomb safeguards of the
streaming API were bypassed when HTTP redirects were followed.
(CVE-2026-21441 reported by <a
href="https://github.com/D47A"><code>@D47A</code></a>, 8.9 High,
GHSA-38jv-5279-wg99)</li>
<li>Started treating <code>Retry-After</code> times greater than 6 hours
as 6 hours by default. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3743">urllib3/urllib3#3743</a>)</li>
<li>Fixed <code>urllib3.connection.VerifiedHTTPSConnection</code> on
Emscripten. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3752">urllib3/urllib3#3752</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.6.3 (2026-01-07)</h1>
<ul>
<li>Fixed a high-severity security issue where decompression-bomb
safeguards of
the streaming API were bypassed when HTTP redirects were followed.
(<code>GHSA-38jv-5279-wg99
<https://github.com/urllib3/urllib3/security/advisories/GHSA-38jv-5279-wg99></code>__)</li>
<li>Started treating <code>Retry-After</code> times greater than 6 hours
as 6 hours by
default. (<code>[#3743](https://github.com/urllib3/urllib3/issues/3743)
<https://github.com/urllib3/urllib3/issues/3743></code>__)</li>
<li>Fixed <code>urllib3.connection.VerifiedHTTPSConnection</code> on
Emscripten.
(<code>[#3752](https://github.com/urllib3/urllib3/issues/3752)
<https://github.com/urllib3/urllib3/issues/3752></code>__)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="0248277dd7"><code>0248277</code></a>
Release 2.6.3</li>
<li><a
href="8864ac407b"><code>8864ac4</code></a>
Merge commit from fork</li>
<li><a
href="70cecb27ca"><code>70cecb2</code></a>
Fix Scorecard issues related to vulnerable dev dependencies (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3755">#3755</a>)</li>
<li><a
href="41f249abe1"><code>41f249a</code></a>
Move "v2.0 Migration Guide" to the end of the table of
contents (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3747">#3747</a>)</li>
<li><a
href="fd4dffd2fc"><code>fd4dffd</code></a>
Patch <code>VerifiedHTTPSConnection</code> for Emscripten (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3752">#3752</a>)</li>
<li><a
href="13f0bfd55e"><code>13f0bfd</code></a>
Handle massive values in Retry-After when calculating time to sleep for
(<a
href="https://redirect.github.com/urllib3/urllib3/issues/3743">#3743</a>)</li>
<li><a
href="8c480bf87b"><code>8c480bf</code></a>
Bump actions/upload-artifact from 5.0.0 to 6.0.0 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3748">#3748</a>)</li>
<li><a
href="4b40616e95"><code>4b40616</code></a>
Bump actions/cache from 4.3.0 to 5.0.1 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3750">#3750</a>)</li>
<li><a
href="82b8479663"><code>82b8479</code></a>
Bump actions/download-artifact from 6.0.0 to 7.0.0 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3749">#3749</a>)</li>
<li><a
href="34284cb017"><code>34284cb</code></a>
Mention experimental features in the security policy (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3746">#3746</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.6.2...2.6.3">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/maxdorninger/MediaManager/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the uv group with 3 updates in the / directory:
[cryptography](https://github.com/pyca/cryptography),
[python-multipart](https://github.com/Kludex/python-multipart) and
[urllib3](https://github.com/urllib3/urllib3).
Updates `cryptography` from 46.0.3 to 46.0.5
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pyca/cryptography/blob/main/CHANGELOG.rst">cryptography's
changelog</a>.</em></p>
<blockquote>
<p>46.0.5 - 2026-02-10</p>
<pre><code>
* An attacker could create a malicious public key that reveals portions
of your
private key when using certain uncommon elliptic curves (binary curves).
This version now includes additional security checks to prevent this
attack.
This issue only affects binary elliptic curves, which are rarely used in
real-world applications. Credit to **XlabAI Team of Tencent Xuanwu Lab
and
Atuin Automated Vulnerability Discovery Engine** for reporting the
issue.
**CVE-2026-26007**
* Support for ``SECT*`` binary elliptic curves is deprecated and will be
removed in the next release.
<p>.. v46-0-4:</p>
<p>46.0.4 - 2026-01-27<br />
</code></pre></p>
<ul>
<li><code>Dropped support for win_arm64 wheels</code>_.</li>
<li>Updated Windows, macOS, and Linux wheels to be compiled with OpenSSL
3.5.5.</li>
</ul>
<p>.. _v46-0-3:</p>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="06e120e682"><code>06e120e</code></a>
bump version for 46.0.5 release (<a
href="https://redirect.github.com/pyca/cryptography/issues/14289">#14289</a>)</li>
<li><a
href="0eebb9dbb6"><code>0eebb9d</code></a>
EC check key on cofactor > 1 (<a
href="https://redirect.github.com/pyca/cryptography/issues/14287">#14287</a>)</li>
<li><a
href="bedf6e186b"><code>bedf6e1</code></a>
fix openssl version on 46 branch (<a
href="https://redirect.github.com/pyca/cryptography/issues/14220">#14220</a>)</li>
<li><a
href="e6f44fc8e6"><code>e6f44fc</code></a>
bump for 46.0.4 and drop win arm64 due to CI issues (<a
href="https://redirect.github.com/pyca/cryptography/issues/14217">#14217</a>)</li>
<li>See full diff in <a
href="https://github.com/pyca/cryptography/compare/46.0.3...46.0.5">compare
view</a></li>
</ul>
</details>
<br />
Updates `python-multipart` from 0.0.21 to 0.0.22
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/python-multipart/releases">python-multipart's
releases</a>.</em></p>
<blockquote>
<h2>Version 0.0.22</h2>
<h2>What's Changed</h2>
<ul>
<li>Drop directory path from filename in <code>File</code> <a
href="9433f4bbc9">9433f4b</a>.</li>
</ul>
<hr />
<p><strong>Full Changelog</strong>: <a
href="https://github.com/Kludex/python-multipart/compare/0.0.21...0.0.22">https://github.com/Kludex/python-multipart/compare/0.0.21...0.0.22</a></p>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/Kludex/python-multipart/blob/master/CHANGELOG.md">python-multipart's
changelog</a>.</em></p>
<blockquote>
<h2>0.0.22 (2026-01-25)</h2>
<ul>
<li>Drop directory path from filename in <code>File</code> <a
href="9433f4bbc9">9433f4b</a>.</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="bea7bbb290"><code>bea7bbb</code></a>
Version 0.0.22 (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/222">#222</a>)</li>
<li><a
href="0fb59a9df0"><code>0fb59a9</code></a>
chore: add return type on test (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/221">#221</a>)</li>
<li><a
href="9433f4bbc9"><code>9433f4b</code></a>
Merge commit from fork</li>
<li><a
href="d5c91ecb0a"><code>d5c91ec</code></a>
Bump the github-actions group with 2 updates (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/219">#219</a>)</li>
<li><a
href="5a90631b48"><code>5a90631</code></a>
bump uv (<a
href="https://redirect.github.com/Kludex/python-multipart/issues/218">#218</a>)</li>
<li>See full diff in <a
href="https://github.com/Kludex/python-multipart/compare/0.0.21...0.0.22">compare
view</a></li>
</ul>
</details>
<br />
Updates `urllib3` from 2.6.2 to 2.6.3
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/releases">urllib3's
releases</a>.</em></p>
<blockquote>
<h2>2.6.3</h2>
<h2>🚀 urllib3 is fundraising for HTTP/2 support</h2>
<p><a
href="https://sethmlarson.dev/urllib3-is-fundraising-for-http2-support">urllib3
is raising ~$40,000 USD</a> to release HTTP/2 support and ensure
long-term sustainable maintenance of the project after a sharp decline
in financial support. If your company or organization uses Python and
would benefit from HTTP/2 support in Requests, pip, cloud SDKs, and
thousands of other projects <a
href="https://opencollective.com/urllib3">please consider contributing
financially</a> to ensure HTTP/2 support is developed sustainably and
maintained for the long-haul.</p>
<p>Thank you for your support.</p>
<h2>Changes</h2>
<ul>
<li>Fixed a security issue where decompression-bomb safeguards of the
streaming API were bypassed when HTTP redirects were followed.
(CVE-2026-21441 reported by <a
href="https://github.com/D47A"><code>@D47A</code></a>, 8.9 High,
GHSA-38jv-5279-wg99)</li>
<li>Started treating <code>Retry-After</code> times greater than 6 hours
as 6 hours by default. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3743">urllib3/urllib3#3743</a>)</li>
<li>Fixed <code>urllib3.connection.VerifiedHTTPSConnection</code> on
Emscripten. (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3752">urllib3/urllib3#3752</a>)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/urllib3/urllib3/blob/main/CHANGES.rst">urllib3's
changelog</a>.</em></p>
<blockquote>
<h1>2.6.3 (2026-01-07)</h1>
<ul>
<li>Fixed a high-severity security issue where decompression-bomb
safeguards of
the streaming API were bypassed when HTTP redirects were followed.
(<code>GHSA-38jv-5279-wg99
<https://github.com/urllib3/urllib3/security/advisories/GHSA-38jv-5279-wg99></code>__)</li>
<li>Started treating <code>Retry-After</code> times greater than 6 hours
as 6 hours by
default. (<code>[#3743](https://github.com/urllib3/urllib3/issues/3743)
<https://github.com/urllib3/urllib3/issues/3743></code>__)</li>
<li>Fixed <code>urllib3.connection.VerifiedHTTPSConnection</code> on
Emscripten.
(<code>[#3752](https://github.com/urllib3/urllib3/issues/3752)
<https://github.com/urllib3/urllib3/issues/3752></code>__)</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="0248277dd7"><code>0248277</code></a>
Release 2.6.3</li>
<li><a
href="8864ac407b"><code>8864ac4</code></a>
Merge commit from fork</li>
<li><a
href="70cecb27ca"><code>70cecb2</code></a>
Fix Scorecard issues related to vulnerable dev dependencies (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3755">#3755</a>)</li>
<li><a
href="41f249abe1"><code>41f249a</code></a>
Move "v2.0 Migration Guide" to the end of the table of
contents (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3747">#3747</a>)</li>
<li><a
href="fd4dffd2fc"><code>fd4dffd</code></a>
Patch <code>VerifiedHTTPSConnection</code> for Emscripten (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3752">#3752</a>)</li>
<li><a
href="13f0bfd55e"><code>13f0bfd</code></a>
Handle massive values in Retry-After when calculating time to sleep for
(<a
href="https://redirect.github.com/urllib3/urllib3/issues/3743">#3743</a>)</li>
<li><a
href="8c480bf87b"><code>8c480bf</code></a>
Bump actions/upload-artifact from 5.0.0 to 6.0.0 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3748">#3748</a>)</li>
<li><a
href="4b40616e95"><code>4b40616</code></a>
Bump actions/cache from 4.3.0 to 5.0.1 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3750">#3750</a>)</li>
<li><a
href="82b8479663"><code>82b8479</code></a>
Bump actions/download-artifact from 6.0.0 to 7.0.0 (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3749">#3749</a>)</li>
<li><a
href="34284cb017"><code>34284cb</code></a>
Mention experimental features in the security policy (<a
href="https://redirect.github.com/urllib3/urllib3/issues/3746">#3746</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/urllib3/urllib3/compare/2.6.2...2.6.3">compare
view</a></li>
</ul>
</details>
<br />
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions
You can disable automated security fix PRs for this repo from the
[Security Alerts
page](https://github.com/maxdorninger/MediaManager/network/alerts).
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [alembic](https://github.com/sqlalchemy/alembic) from 1.17.2 to
1.18.4.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/sqlalchemy/alembic/releases">alembic's
releases</a>.</em></p>
<blockquote>
<h1>1.18.4</h1>
<p>Released: February 10, 2026</p>
<h2>bug</h2>
<ul>
<li>
<p><strong>[bug] [operations]</strong> Reverted the behavior of
<code>Operations.add_column()</code> that would
automatically render the "PRIMARY KEY" keyword inline when a
<code>Column</code> with <code>primary_key=True</code> is added. The
automatic
behavior, added in version 1.18.2, is now opt-in via the new
<code>Operations.add_column.inline_primary_key</code> parameter. This
change restores the ability to render a PostgreSQL SERIAL column, which
is
required to be <code>primary_key=True</code>, while not impacting the
ability to
render a separate primary key constraint. This also provides consistency
with the <code>Operations.add_column.inline_references</code> parameter
and
gives users explicit control over SQL generation.</p>
<p>To render PRIMARY KEY inline, use the
<code>Operations.add_column.inline_primary_key</code> parameter set to
<code>True</code>:</p>
<p>op.add_column(
"my_table",
Column("id", Integer, primary_key=True),
inline_primary_key=True
)References: <a
href="https://redirect.github.com/sqlalchemy/alembic/issues/1232">#1232</a></p>
</li>
</ul>
<h1>1.18.3</h1>
<p>Released: January 29, 2026</p>
<h2>bug</h2>
<ul>
<li>
<p><strong>[bug] [autogenerate]</strong> Fixed regression in version
1.18.0 due to <a
href="https://redirect.github.com/sqlalchemy/alembic/issues/1771">#1771</a>
where autogenerate
would raise <code>NoReferencedTableError</code> when a foreign key
constraint
referenced a table that was not part of the initial table load,
including
tables filtered out by the
<code>EnvironmentContext.configure.include_name</code> callable or
tables
in remote schemas that were not included in the initial reflection
run.</p>
<p>The change in <a
href="https://redirect.github.com/sqlalchemy/alembic/issues/1771">#1771</a>
was a performance optimization that eliminated
additional reflection queries for tables that were only referenced by
foreign keys but not explicitly included in the main reflection run.
However, this optimization inadvertently removed the creation of
<code>Table</code> objects for these referenced tables, causing
autogenerate
to fail when processing foreign key constraints that pointed to
them.</p>
<p>The fix creates placeholder <code>Table</code> objects for foreign
key targets</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/sqlalchemy/alembic/commits">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps
[prettier-plugin-svelte](https://github.com/sveltejs/prettier-plugin-svelte)
from 3.4.0 to 3.4.1.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/sveltejs/prettier-plugin-svelte/blob/v3.4.1/CHANGELOG.md">prettier-plugin-svelte's
changelog</a>.</em></p>
<blockquote>
<h2>3.4.1</h2>
<ul>
<li>(fix) externalize all prettier imports</li>
<li>(fix) don't remove parantheses of <code>bind:</code>ings with
<code>as</code> type casts</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/sveltejs/prettier-plugin-svelte/commits/v3.4.1">compare
view</a></li>
</ul>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps
[@sinclair/typebox](https://github.com/sinclairzx81/typebox-legacy) from
0.34.41 to 0.34.48.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/sinclairzx81/typebox-legacy/commits/0.34.48">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by [GitHub Actions](<a
href="https://www.npmjs.com/~GitHub">https://www.npmjs.com/~GitHub</a>
Actions), a new releaser for <code>@sinclair/typebox</code> since your
current version.</p>
</details>
<br />
[](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.
[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)
---
<details>
<summary>Dependabot commands and options</summary>
<br />
You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)
</details>
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This PR makes the user the container runs as configurable. Before, the
container always tried stepping down (from root) to the mediamanager
user. Now it detects if it's already running as a non-root user and
starts the server directly. Fixes#397
Hi, I've added file names sanitization when saving the torrent file, as
previously the import was failing on torrents with special characters in
names. This fixes#367
Following the discussion in #329 and #115, here's a doc section on using
nix flakes to install MediaManager.
Co-authored-by: lschuetze <lschuetze@mpi-sws.org>
This PR facilities the migration from the old Writerside documentation
platform to Gitbook.
## motivation
Gitbook supports serving multiple versions of the documentation, e.g.
v1.12.1, v1.13.0, and master.
this mostly either removes unused parameters, prefixes them with an
underscore or uses the @override decorator to tell the linter, that that
method comes from a superclass and can't be changed
this mostly adds a timeout=60 to all requests
this does mainly wants a timeout to all requests functions, since when
left out they hang infinitly.
I added a timeout of 60s, which is probably way too high, but since
before this there was none, I guess it's an improvement?
This PR changes all mentions of GHCR to Quay, adds docs about the
registries MM is available on, adds docs about the available docker
image tags, and adds the GHCR permission issue to the troubleshooting
page.
MediaManager is modern software to manage your TV and movie library. It is designed to be a replacement for Sonarr,
Radarr, Overseer, and Jellyseer.
It supports TVDB and TMDB for metadata, supports OIDC and OAuth 2.0 for authentication and supports Prowlarr and
Jackett.
MediaManager is built first and foremost for deployment with Docker, making it easy to set up.
MediaManager is the modern, easy-to-use successor to the fragmented "Arr" stack. Manage, discover, and automate your TV and movie collection in a single, simple interface.
It also provides an API to interact with the software programmatically, allowing for automation and integration with
# you probably need to edit the config.toml file in the ./config directory, for more help see the documentation
docker compose up -d
```
### [View the docs for installation instructions and more](https://maxdorninger.github.io/MediaManager/configuration-overview.html#configuration-overview)
### [View the docs for installation instructions and more](https://maxdorninger.github.io/MediaManager/)
d="m 0,0 h 669.787 c 68.994,0 116.873,-68.746 92.95,-133.46 L 542.309,-729.728 c -14.382,-38.904 -51.472,-64.736 -92.95,-64.736 h -669.787 c -68.994,0 -116.873,68.746 -92.949,133.46 L -92.949,-64.736 C -78.567,-25.832 -41.478,0 0,0"
d="m 0,0 h -571.59 c -58.879,0 -99.738,58.667 -79.322,113.893 l 188.111,508.849 c 12.274,33.201 43.925,55.246 79.322,55.246 h 571.59 c 58.879,0 99.739,-58.667 79.322,-113.894 L 79.322,55.245 C 67.049,22.045 35.397,0 0,0"
d="m 0,0 h 724.733 c 74.654,0 126.46,-74.386 100.575,-144.408 L 586.797,-789.591 c -15.562,-42.096 -55.694,-70.047 -100.575,-70.047 h -724.733 c -74.654,0 -126.461,74.386 -100.574,144.409 l 238.511,645.182 C -85.013,-27.952 -44.88,0 0,0"
Scoring rulesets in MediaManager allow you to flexibly control which releases are preferred or avoided when searching
for media. Each ruleset is a collection of scoring rules that can be assigned to one or more libraries. When
MediaManager evaluates releases, it applies the relevant ruleset(s) to adjust the score of each result, influencing
which releases are selected for download.
## How Rulesets Work
- **Rulesets** are defined in the configuration and contain a list of rule names and the libraries they apply to.
- **Scoring rules** can target keywords in release titles or specific indexer flags.
- When searching for a release, MediaManager checks which library the media belongs to and applies the corresponding
ruleset.
## Rules
Rules define how MediaManager scores releases based on their titles or indexer flags. You can create rules that:
- Prefer releases with specific codecs (e.g., H.265 over H.264).
- Avoid releases with certain keywords (e.g., "CAM", "TS", "Nuked").
- Reject releases that do not meet certain criteria (e.g., non-freeleech releases).
- and more.
<note>
The keywords and flags are compared case-insensitively.
</note>
### Title Rules
Title rules allow you to adjust the score of a release based on the presence (or absence) of specific keywords in the release title. This is useful for preferring or avoiding certain encodings, sources, or other characteristics that are typically included in release names.
Each title rule consists of:
-`name`: A unique identifier for the rule.
-`keywords`: A list of keywords to search for in the release title.
-`score_modifier`: The amount to add or subtract from the score if a keyword matches.
-`negate`: If true, the rule applies when none of the keywords are present.
#### Examples for Title Rules
```toml
[[indexers.title_scoring_rules]]
name="prefer_h265"
keywords=["h265","hevc","x265"]
score_modifier=100
negate=false
[[indexers.title_scoring_rules]]
name="avoid_cam"
keywords=["cam","ts"]
score_modifier=-10000
negate=false
```
- The first rule increases the score for releases containing "h265", "hevc", or "x265".
- The second rule heavily penalizes releases containing "cam" or "ts".
If `negate` is set to `true`, the `score_modifier` is applied only if none of the keywords are found in the title.
### Indexer Flag Rules
Indexer flag rules adjust the score based on flags provided by the indexer (such as `freeleech`, `nuked`, etc). These flags are often used to indicate special properties or warnings about a release.
Each indexer flag rule consists of:
-`name`: A unique identifier for the rule.
-`flags`: A list of indexer flags to match.
-`score_modifier`: The amount to add or subtract from the score if a flag matches.
-`negate`: If true, the rule applies when none of the flags are present.
#### Examples for Indexer Flag Rules
```toml
[[indexers.indexer_flag_scoring_rules]]
name="reject_non_freeleech"
flags=["freeleech","freeleech75"]
score_modifier=-10000
negate=true
[[indexers.indexer_flag_scoring_rules]]
name="reject_nuked"
flags=["nuked"]
score_modifier=-10000
negate=false
```
- The first rule penalizes releases that do **not** have the "freeleech" or "freeleech75" flag.
- The second rule penalizes releases that are marked as "nuked".
If `negate` is set to `true`, the `score_modifier` is applied only if none of the flags are present on the release.
These settings configure the core backend application through the `config.toml` file. All backend configuration is now
centralized in this TOML file instead of environment variables.
## General Settings (`[misc]`)
-`frontend_url`
The URL the frontend will be accessed from. This is a required field and must not include a trailing slash. The default
path is `http://localhost:8000`.
E.g. if you are accessing MediaManager at `http://example.com/media` where `/media` is the base path, set this to: `http://example.com/media`.
If you are accessing MediaManager at the root of a domain, e.g. `https://mediamanager.example.com`, set this to `https://mediamanager.example.com`.
Make sure to change this to the URL you will use to access the application in your browser.
<tip>
Note that this doesn't affect where the server binds, nor does it affect the base URL prefix. See the page on <a href="url-prefix.md"><code>BASE_PATH</code></a> for information on how to configure a prefix.
</tip>
-`cors_urls`
A list of origins you are going to access the API from. Note the lack of trailing slashes.
-`development`
Set to `true` to enable development mode. Default is `false`.
## Example Configuration
Here's a complete example of the general settings section in your `config.toml`:
```toml
[misc]
# REQUIRED: Change this to match your actual frontend domain.
frontend_url="http://mediamanager.dev"
cors_urls=["http://localhost:8000"]
# Optional: Development mode (set to true for debugging)
development=false
```
<note>
The <code>frontend_url</code> is the most important settings to configure correctly. Make sure it matches your actual deployment URLs.
- **Vite proxy**: Automatically forwards all `/api/*` requests from frontend to backend
This means when your browser makes a request to `http://localhost:5173/api/v1/tv/shows`, Vite automatically proxies it
to `http://mediamanager:8000/api/v1/tv/shows`. The `PUBLIC_API_URL` environment variable is set to use this proxy, so
you don't need to configure anything manually.
### Setting up the full development environment with Docker (Recommended)
This is the easiest and recommended way to get started. Everything runs in Docker with hot-reloading enabled.
1. Copy the example config & .env:
```bash
mkdir -p res/config # Only needed on first run
cp config.dev.toml res/config/config.toml
cp web/.env.example web/.env
```
2. Start all services:
```bash
# Recommended: Use make commands for easy development
make up
# Alternative: Use docker compose directly (if make is not available)
docker compose -f docker-compose.dev.yaml up
```
<tip> Run <code>make help</code> to see all available development commands including <code>make down</code>, <code>make logs</code>, <code>make app</code> (
shell into backend), and more.</tip>
3. Access the application:
- Frontend (with HMR): <http://localhost:5173>
- Backend API: <http://localhost:8000>
- Database: localhost:5432
The default user email is `admin@example.com` and password is `admin`, these are printed out in the logs accessible with `make logs`.
That's it! Now you can edit code and see changes instantly:
- Edit Python files → Backend auto-reloads
- Edit Svelte/TypeScript files → Frontend HMR updates in browser
- Edit config.toml → Changes apply immediately
### Setting up the backend development environment (Local)
Metadata provider settings are configured in the `[metadata]` section of your `config.toml` file. These settings control how MediaManager retrieves information about movies and TV shows.
## TMDB Settings (`[metadata.tmdb]`)
TMDB (The Movie Database) is the primary metadata provider for MediaManager. It provides detailed information about movies and TV shows.
<tip>
Other software like Jellyfin use TMDB as well, so there won't be any metadata discrepancies.
</tip>
### `tmdb_relay_url`
If you want to use your own TMDB relay service, set this to the URL of your own MetadataRelay. Otherwise, use the default relay.
If a TV show/movie's original language is in this list, metadata will be displayed and fetched in that language. Torrent searches done in Standard Mode uses the same fetched metadata, so if you use any language-specific tracker, you may enter the language here to get the desired search results.
Otherwise, `default_language` will be used.
**Format: ISO 639-1 codes (2 letters). Full list: https://en.wikipedia.org/wiki/List_of_ISO_639_language_codes**
- **Default:** `[]`
- **Example:** `["no", "de", "es"]`
### `default_language`
<warning>
`default_language` sets the TMDB `language` paramater when searching and adding TV shows and movies. If TMDB does not find a matching translation, metadata in the <strong>original language</strong> will be fetched with no option for a fallback language. It is therefore highly advised to only use "broad" languages. For most use cases, the default setting is safest.
</warning>
**Format: ISO 639-1 codes (2 letters).**
- **Default:** `en`
## TVDB Settings (`[metadata.tvdb]`)
<warning>
The TVDB might provide false metadata and doesn't support some features of MediaManager like showing overviews. Therefore, TMDB is the preferred metadata provider.
</warning>
### `tvdb_relay_url`
If you want to use your own TVDB relay service, set this to the URL of your own MetadataRelay. Otherwise, use the default relay.
To use MediaManager <strong>you don't need to set up your own MetadataRelay</strong>, as the default relay hosted by the developer should be sufficient for most purposes.
</note>
The MetadataRelay is a service that provides metadata for MediaManager. It acts as a proxy for TMDB and TVDB, allowing you to use your own API keys if needed, but the default relay means you don't need to create accounts for API keys yourself.
You might want to use your own relay if you want to avoid rate limits, protect your privacy, or for other reasons. If you know Sonarr's Skyhook, this is similar to that.
### Where to get API keys
- Get a TMDB API key from [The Movie Database](https://www.themoviedb.org/settings/api)
- Get a TVDB API key from [The TVDB](https://thetvdb.com/auth/register)
<tip>
If you want to use your own MetadataRelay, you can set the <code>tmdb_relay_url</code> and/or <code>tvdb_relay_url</code> to your own relay service.
</tip>
## Example Configuration
Here's a complete example of the metadata section in your `config.toml`:
Always check the container and browser logs for more specific error messages
</tip>
## Authentication Issues
<procedure title="I can't log in with OAuth/OIDC?" id="procedure-i-cannot-log-in-with-oauth">
<step>Verify your OAuth provider's configuration. <a href="authentication-setup.md" anchor="openid-connect-settings-auth-openid-connect">See the OAuth documentation</a></step>
<step>Check if the callback URI you set in your OIDC providers settings is correct. <a href="authentication-setup.md" anchor="redirect-uri">See the callback URI documentation</a> </step>
<step>Check the frontend url in your config file. It should match the URL you use to access MediaManager.</step>
<step>Make sure you are logging in, not signing up.</step>
<step>Try logging in with the following credentials:
<list>
<li>Email: admin@mediamanager.local or admin@example.com</li>
<li>Password: admin</li>
</list>
</step>
</procedure>
## Hard linking Issues
- Make sure you are using only one volumes for TV, Movies and Downloads.
<a href="https://raw.githubusercontent.com/maxdorninger/MediaManager/refs/heads/master/docker-compose.yaml"> See the configuration in the example <code>docker-compose.yaml</code> file.</a>
The reason is that hard linking only works within the same filesystem. If your downloads are on a different volume than
your media library, hard linking will not work.
## Torrent Search Issues
<procedure title="I get no search results for torrents?" id="procedure-i-get-no-search-results">
<step>Try switching to the advanced tab when searching for torrents.</step>
<step><a href="Indexer-Settings.md">If you use "slow" indexers, try increasing the timeout threshold.</a></step>
<step>If you still don't get any search results, check the logs, they will provide more information on what is going wrong.</step>
</procedure>
## Import and download Issues
- If you configured a category with a special save path,
<a href="qBittorrent-Category.md">carefully read this page about MM with qBittorrent save paths.</a>
<note>If it still doesn't work, <a href="https://github.com/maxdorninger/MediaManager/issues">please open an Issue.</a> It is possible that a bug is causing the issue.</note>
MediaManager can be configured to follow symlinks when serving frontend files. This is useful if you have a setup where your frontend files are stored in a different location, and you want to symlink them into the MediaManager frontend directory.
*`FRONTEND_FOLLOW_SYMLINKS`\
Set this environment variable to `true` to follow symlinks when serving frontend files. Default is `false`.
Metadata provider settings are configured in the `[metadata]` section of your `config.toml` file. These settings control how MediaManager retrieves information about movies and TV shows.
### TMDB Settings (`[metadata.tmdb]`)
TMDB (The Movie Database) is the primary metadata provider for MediaManager. It provides detailed information about movies and TV shows.
!!! info
Other software like Jellyfin use TMDB as well, so there won't be any metadata discrepancies.
*`tmdb_relay_url`\
URL of the TMDB relay (MetadataRelay). Default is `https://metadata-relay.dorninger.co/tmdb`. Example: `https://your-own-relay.example.com/tmdb`.
*`primary_languages`\
If the original language of a show/movie is in this list, metadata is fetched in that language. Otherwise, `default_language` is used. Default is `[]`. Example: `["no", "de", "es"]`. Format: ISO 639-1 (2 letters). Full list: https://en.wikipedia.org/wiki/List\_of\_ISO\_639\_language\_codes
*`default_language`\
TMDB language parameter used when searching and adding. Default is `en`. Format: ISO 639-1 (2 letters).
!!! warning
`default_language` sets the TMDB `language` parameter when searching and adding TV shows and movies. If TMDB does not find a matching translation, metadata in the original language will be fetched with no option for a fallback language. It is therefore highly advised to only use "broad" languages. For most use cases, the default setting is safest.
### TVDB Settings (`[metadata.tvdb]`)
!!! warning
The TVDB might provide false metadata and doesn't support some features of MediaManager like showing overviews. Therefore, TMDB is the preferred metadata provider.
*`tvdb_relay_url`\
URL of the TVDB relay (MetadataRelay). Default is `https://metadata-relay.dorninger.co/tvdb`. Example: `https://your-own-relay.example.com/tvdb`.
### MetadataRelay
!!! info
To use MediaManager you don't need to set up your own MetadataRelay, as the default relay hosted by the developer should be sufficient for most purposes.
The MetadataRelay is a service that provides metadata for MediaManager. It acts as a proxy for TMDB and TVDB, allowing you to use your own API keys if needed, but the default relay means you don't need to create accounts for API keys yourself.
You might want to use your own relay if you want to avoid rate limits, protect your privacy, or for other reasons. If you know Sonarr's Skyhook, this is similar to that.
#### Where to get API keys
* Get a TMDB API key from [The Movie Database](https://www.themoviedb.org/settings/api)
* Get a TVDB API key from [The TVDB](https://thetvdb.com/auth/register)
!!! info
If you want to use your own MetadataRelay, you can set the `tmdb_relay_url` and/or `tvdb_relay_url` to your own relay service.
### Example Configuration
Here's a complete example of the metadata section in your `config.toml`:
qBittorrent supports saving Torrents to subdirectories based on the category of the Torrent. The default category name that MediaManager uses is `MediaManager`.
Use the following variables to customize behavior:
*`torrents.qbittorrent.category_name`\
Category name MediaManager uses when adding torrents to qBittorrent. Default is `MediaManager`.
*`torrents.qbittorrent.category_save_path`\
Save path for the category in qBittorrent. By default, no subdirectory is used. Example: `/data/torrents/MediaManager`.
!!! info
qBittorrent saves torrents to the path specified by `torrents.qbittorrent.category_save_path`, so it must be a valid path that qBittorrent can write to.
!!! warning
For MediaManager to successfully import torrents, you must add the subdirectory to the `misc.torrent_directory` variable.
@@ -6,7 +6,7 @@ In order to run it on a prefixed path, like `maxdorninger.github.io/media`, the
In short, clone the repository, then run:
```
```none title="Build Docker image"
docker build \
--build-arg BASE_PATH=/media \
--build-arg VERSION=my-custom-version \
@@ -16,7 +16,10 @@ docker build \
You also need to set the `BASE_PATH` environment variable at runtime in `docker-compose.yaml`:
```yaml
* `BASE_PATH`\
Base path prefix MediaManager is served under. Example: `/media`. This must match the `BASE_PATH` build arg.
```yaml title="docker-compose.yaml (excerpt)"
services:
mediamanager:
image: MediaManager:my-custom-version
@@ -27,8 +30,7 @@ services:
...
```
<note>
Make sure to include the base path in the frontend_url field in the config file. For more information see the page on <a href="configuration-backend.md"><code>frontend_url</code></a>.
</note>
!!! info
Make sure to include the base path in the `frontend_url` field in the config file. See [Backend](../configuration/backend.md).
Finally, ensure that whatever reverse proxy you're using leaves the incoming path unchanged; that is, you should not strip the `/media` from `/media/web/`.
MediaManager uses a TOML configuration file (`config.toml`) for all backend settings. This centralized configuration approach makes it easier to manage, backup, and share your MediaManager setup.
Frontend settings are configured through environment variables in your `docker-compose.yaml` file.
## Configuration File Location
!!! warning
Note that MediaManager may need to be restarted for changes in the config file to take effect.
Your `config.toml` file should be in the directory that's mounted to `/app/config/config.toml` inside the container:
```yaml
volumes:
- ./config:/app/config
```
You can change the configuration directory with the following environment variable:
*`CONFIG_DIR`\
Directory that contains `config.toml`. Default is `/app/config`. Example: `/etc/mediamanager/`.
## Configuration Sections
The configuration is organized into the following sections:
*`[indexers]` - Indexer settings (Prowlarr and Jackett )
*`[metadata]` - TMDB and TVDB settings
## Configuring Secrets
For sensitive information like API keys, passwords, and secrets, you should use environment variables. You can actually set every configuration value through environment variables. For example, to set the `token_secret` value for authentication, with a .toml file you would use:
```toml
[auth]
token_secret="your_super_secret_key_here"
```
But you can also set it through an environment variable:
So for every config "level", you basically have to take the name of the value and prepend it with the section names in uppercase with 2 underscores as delimiters and `MEDIAMANAGER_` as the prefix.
!!! warning
Note that not every env variable starts with `MEDIAMANAGER_`; this prefix only applies to env variables which replace/overwrite values in the config file. Variables like the `CONFIG_DIR` env variable must not be prefixed.
authentication is the default, but you can also enable OpenID Connect (OAuth
2.0) for integration with external identity providers
---
# Authentication
All authentication settings are configured in the `[auth]` section of your `config.toml` file.
## General Authentication Settings (`[auth]`)
*`token_secret`\
Strong secret key for signing JWTs (create with `openssl rand -hex 32`). This is required.
*`session_lifetime`\
Lifetime of user sessions in seconds. Default is `86400` (1 day).
*`admin_emails`\
A list of email addresses for administrator accounts. This is required.
*`email_password_resets`\
Enables password resets via email. Default is `false`.
!!! info
To use email password resets, you must also configure SMTP settings in the `[notifications.smtp_config]` section.
!!! info
When setting up MediaManager for the first time, you should add your email to `admin_emails` in the `[auth]` config section. MediaManager will then use this email instead of the default admin email. Your account will automatically be created as an admin account, allowing you to manage other users, media and settings.
OpenID Connect allows you to integrate with external identity providers like Google, Microsoft Azure AD, Keycloak, or any other OIDC-compliant provider.
*`enabled`\
Set to `true` to enable OpenID Connect authentication. Default is `false`.
*`client_id`\
Client ID provided by your OpenID Connect provider.
*`client_secret`\
Client secret provided by your OpenID Connect provider.
*`configuration_endpoint`\
OpenID Connect configuration endpoint URL. Do not include a trailing slash. Usually ends with `/.well-known/openid-configuration`.
*`name`\
Display name for the OpenID Connect provider shown on the login page.
### Configuration for your OpenID Connect Provider
#### Redirect URI
The OpenID server will likely require a redirect URI. This URL will usually look something like this:
```none
{MEDIAMANAGER_URL}/api/v1/auth/oauth/callback
```
!!! warning
It is very important that you set the correct callback URI, otherwise it won't work!
#### Authentik Example
Here is an example configuration for the OpenID Connect provider for Authentik.
These settings configure the core backend application through the config.toml
file. All backend configuration is now centralized in this TOML file instead
of environment variables.
---
# Backend
## General Settings (`[misc]`)
*`frontend_url`\
The URL the frontend will be accessed from. This is required. Do not include a trailing slash. Default is `http://localhost:8000`.
Example: if you are accessing MediaManager at `http://example.com/media`, set this to `http://example.com/media`.
If you are accessing MediaManager at the root of a domain, e.g. `https://mediamanager.example.com`, set this to `https://mediamanager.example.com`.
`frontend_url` does not affect where the server binds. It also does not configure a base path prefix. For prefixes, see [URL Prefix](../advanced-features/url-prefix.md).
*`cors_urls`\
A list of origins you are going to access the API from. Do not include trailing slashes.
*`development`\
Set to `true` to enable development mode. Default is `false`.
## Example Configuration
Here's a complete example of the general settings section in your `config.toml`:
```toml title="config.toml"
[misc]
# REQUIRED: Change this to match your actual frontend domain.
frontend_url = "http://mediamanager.dev"
cors_urls = ["http://localhost:8000"]
# Optional: Development mode (set to true for debugging)
development = false
```
!!! info
The `frontend_url` is the most important setting to configure correctly. Make sure it matches your actual deployment URLs.
@@ -4,22 +4,20 @@ MediaManager supports custom libraries, allowing you to add multiple folders for
## Configuration
Custom libraries are configured in the `mis` section in the `config.toml` file. You can add as many libraries as you need.
Custom libraries are configured in the `misc` section in the `config.toml` file. You can add as many libraries as you need.
<note>
You are not limited to `/data/tv` or `/data/movies`, you can choose the entire path freely!
</note>
!!! info
You are not limited to `/data/tv` or `/data/movies`, you can choose the entire path freely!
### Movie Libraries
To add custom movie libraries, you need to add a `[[misc.movie_libraries]]` section for each library. Each library requires a `name` and a `path`.
To add custom movie libraries, add a `[[misc.movie_libraries]]` section for each library. Each library requires a `name` and a `path`.
Here is an example of how to configure two movie libraries:
Example — configuring two movie libraries:
```toml
[misc]
# ... other misc settings
[[misc.movie_libraries]]
@@ -35,12 +33,13 @@ In this example, MediaManager will scan both `/data/movies/action` and `/data/mo
### TV Show Libraries
Similarly, to add custom TV show libraries, you need to add a `[[misc.tv_libraries]]` section for each library. Each library requires a `name` and a `path`.
Similarly, to add custom TV show libraries, add a `[[misc.tv_libraries]]` section for each library. Each library requires a `name` and a `path`.
Here is an example of how to configure two TV show libraries:
Example — configuring two TV show libraries:
```toml
[misc]
# ... other misc settings
[[misc.tv_libraries]]
@@ -50,5 +49,4 @@ path = "/data/tv/live-action"
[[misc.tv_libraries]]
name = "Animation"
path = "/data/tv/animation"
```
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.