417 Commits

Author SHA1 Message Date
Maximilian Dorninger
f5253990e0 switch from APScheduler to Taskiq (#461)
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 -->
2026-02-26 21:23:24 +01:00
Juan David Bermudez Celedon
cbd70bd6f3 Fix scoring rules keyword matching (#473)
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 -->
2026-02-26 16:37:29 +01:00
Maximilian Dorninger
7824891557 Fix qbittorrent category error (#456)
This PR fixes an error caused by MM trying to set the category save path
to None if the string is empty.
2026-02-22 19:51:10 +01:00
Maximilian Dorninger
a643c9426d remove everything related to requests (#455)
This PR removes the requests feature. The functionality will be replaced
either by Seerr or by reimplementing it in a better way.
2026-02-22 19:46:47 +01:00
GokuPlay609
c2645000e5 fix: improve quality detection regex to match 2160p, UHD, FullHD and other keywords (#450)
## 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>
2026-02-22 16:25:36 +01:00
natarelli22
d8a0ec66c3 Support for handling Single Episode Torrents (#331)
**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>
2026-02-22 15:21:19 +01:00
Mark Riabov
0cfd1fa724 Fix suffix formatting for with_suffix call (#408)
Fixes issue ValueError: Invalid suffix 'jpg'

Completely prevents downloading posters from metadata provider
2026-02-10 20:29:05 +01:00
Maximilian Dorninger
2665106847 Merge pull request #401 from maxdorninger/fix-env-variables
Fix download clients config being read from env variables
2026-02-08 16:37:15 +01:00
maxid
d029177fc0 hot fix: fix search tag name for episode in jackett 2026-02-04 23:52:07 +01:00
maxid
abac894a95 fix download clients config being read from env variables without the mediamanager prefix 2026-02-04 22:49:24 +01:00
maxid
12854ff661 format files 2026-02-04 21:34:37 +01:00
maxid
3d52a87302 add id search capabilities to jackett 2026-02-04 21:34:31 +01:00
Maximilian Dorninger
c45c9e5873 add correlation id to logging (#398)
This PR adds Correlation IDs to logs and request responses.

```
2026-02-04 12:40:32,793 - [afd825081d874d6e835b5c59a6ddb371] DEBUG - media_manager.movies - get_importable_movies(): Found 5 importable movies.
2026-02-04 12:40:32,794 - [afd825081d874d6e835b5c59a6ddb371] INFO - uvicorn.access - send(): 172.19.0.1:64094 - "GET /api/v1/movies/importable HTTP/1.1" 200
2026-02-04 12:40:47,322 - [41d30b7003fd45288c6a4bb1cfba5e7a] INFO - uvicorn.access - send(): 127.0.0.1:52964 - "GET /api/v1/health HTTP/1.1" 200
2026-02-04 12:41:17,408 - [157027ea5dde472a9e620f53739ccd53] INFO - uvicorn.access - send(): 127.0.0.1:39850 - "GET /api/v1/health HTTP/1.1" 200
```
2026-02-04 13:55:05 +01:00
Sergey Khruschak
24fcba6bee Torrent file name sanitizing (#390)
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
2026-02-03 17:09:36 +01:00
Juan David Bermudez Celedon
a1f3f92c10 Enhance size validation for indexer results 2026-02-01 22:14:04 -05:00
Juan David Bermudez Celedon
caaa08fbf4 Fix typo in Jackett log for search_movie 2026-02-01 22:01:42 -05:00
Juan David Bermudez Celedon
5db60141bb Fix bug by typo in jackett log message (#387)
fix typo in the `search_season` function log, which causes an error when searching for torrents.
2026-02-01 18:09:18 +01:00
Marcel Hellwig
96b84d45db Adding some more new lints (#393)
Enable `UP` and `TRY` lint
2026-02-01 18:04:15 +01:00
Marcel Hellwig
311e625eee two hotfixes (#392)
this prevents the app from running correctly
2026-02-01 17:42:15 +01:00
Maximilian Dorninger
a39e0d204a Ruff enable type annotations rule (#362)
This PR enables the ruff rule for return type annotations (ANN), and
adds the ty package for type checking.
2026-01-06 17:07:19 +01:00
Renan Greca
dd0b439bbe Fix logging bug in jackett indexer (#360)
fix MM trying to access non-existent attribute
2026-01-06 14:49:06 +01:00
maxid
d5c41430a6 add back hello word message 2026-01-05 23:05:46 +01:00
Marcel Hellwig
75406cbc64 ruff: add RET lint
lints about assign and immediatly returning a variable
2026-01-05 19:30:42 +01:00
Marcel Hellwig
805a6981a6 ruff: enable PTH lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
acd883df21 ruff: enable PIE lint
this just removes needless pass or ...
2026-01-05 19:30:42 +01:00
Marcel Hellwig
f2141ca8b8 ruff: enable PERF lint
this complains a lot about using manual append where a list
comprehension would be more suitable
2026-01-05 19:30:42 +01:00
Marcel Hellwig
7182344036 create list from range directly instead of using append 2026-01-05 19:30:42 +01:00
Marcel Hellwig
a34b0f11a6 use single s since we're ignoring cases anyway 2026-01-05 19:30:42 +01:00
Marcel Hellwig
40812c6040 omit return_type in computed field
it's calculated from the functions return type, so there's no need to
specifify it
2026-01-05 19:30:42 +01:00
Marcel Hellwig
29476e2008 ruff: enable INT and N lint
this renames some files to use snake_case and add Error suffix to custom
exceptions
2026-01-05 19:30:42 +01:00
Marcel Hellwig
29a0d8fe5d ruff: add INP lint
this checks for missing __init__.py files, there was one :)
2026-01-05 19:30:42 +01:00
Marcel Hellwig
55b2dd63d8 ruff: add ARG linter
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
2026-01-05 19:30:42 +01:00
Marcel Hellwig
6e46b482cb ruff: enable A lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
5368cad77a ruff: add S linter
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?
2026-01-05 19:30:42 +01:00
Marcel Hellwig
1857cf501c ruff: enable RUF lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
a7bb5e1e04 Make proper use of function overloading
In preparation of the RUFF lint, I rewrote the function to use
typing.overload.
This is the proper way to accept either two arguments or one argument
2026-01-05 19:30:42 +01:00
Marcel Hellwig
ff013ac76e ruff: enable I lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
eac58d2843 ruff: enable FAST lint
this mostly is replacing the response_model attribute with a return type
of that function since that's the more idiomatic way to do
2026-01-05 19:30:42 +01:00
Marcel Hellwig
97cb3b5c1e ruff: enable EM lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
7ef4e52c81 ruff: enable C4 lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
2c36adfd75 ruff: Enable B lint 2026-01-05 19:30:42 +01:00
Marcel Hellwig
9ff2dc4b92 rewrite downlaod_post_image function
this now uses the proper functions instead of handling with strings
2026-01-05 19:30:00 +01:00
Marcel Hellwig
593e1828cc remove pillow-avif package
it is possible since 11.3 to use avif in the main pillow package,
therefore the avif package is no longer needed

https://github.com/python-pillow/Pillow/pull/5201#issuecomment-3023668716
2026-01-05 19:29:52 +01:00
Maximilian Dorninger
fc691f95bb fix bugs in MovieService
fix some small bugs in MovieService that were caused by the refactor
2026-01-04 23:37:33 +01:00
Maximilian Dorninger
21495653d2 Include show year in season search query 2026-01-04 14:20:38 +01:00
maxid
f144ce1bdf format files after merge 2026-01-02 16:25:41 +01:00
maxid
2d2afaba50 Merge branch 'master' into fork/strangeglyph/master
# Conflicts:
#	media_manager/main.py
2026-01-02 16:24:18 +01:00
maxid
a253ffd946 only accept TRUE 2026-01-02 16:21:58 +01:00
maxid
4841d1ed11 fix tvdb search not working 2026-01-02 14:38:58 +01:00
strangeglyph
64f01cc919 Allow frontend files to be followed through symlinks 2026-01-02 12:33:15 +01:00