Compare commits

..

360 Commits

Author SHA1 Message Date
Qstick 3ca6f83a4d fixup! New: (Cardigann) Paging Support 2023-02-26 17:06:47 -06:00
Qstick fb5b325271 fixup! New: (Cardigann) Add AllowEmptyInputs
Co-Authored-By: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-26 16:48:53 -06:00
Qstick ec8025c3dc New: (Cardigann) Add AllowEmptyInputs
Co-Authored-By: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-26 16:41:02 -06:00
Qstick b42bf2cf20 New: (Cardigann) Paging Support 2023-02-25 20:18:21 -06:00
Qstick 712d95e6ce Cleanup request paging code 2023-02-25 20:17:46 -06:00
Bogdan 24f6c937da Fixed: (Cardigann) Prevent fetching the first page multiple times 2023-02-26 01:56:56 +02:00
Bogdan e94aa7c499 Fixed: (DateTimeUtil) Move check for Rfc1123ZPattern
Co-authored-by: Sergey M <msergein@users.noreply.github.com>
2023-02-25 23:55:42 +02:00
Bogdan 201bc1944b Fixed: (DateTimeUtil) Check first for Standard Format in ParseDateTimeGoLang 2023-02-25 23:16:57 +02:00
Bogdan 09e40e0060 Fixed: (Rarbg) Set rate limit to 31s for RSS sync 2023-02-25 19:56:06 +02:00
Qstick 348d90a37e Fixed: (Cardigann) Invariant date string parsing for "reltime", "timeago", "fuzzytime"
Fixes #835
2023-02-25 11:52:24 -06:00
Qstick 726dc34424 Improve GetLongFromString and ParseFields
2700X faster
2023-02-25 11:52:24 -06:00
Qstick 2e9f6cd94b More Improvement to unix timestamp performance 2023-02-25 11:52:24 -06:00
Bogdan 495f61f412 Improve unix timestamp performance 2023-02-25 11:52:24 -06:00
Qstick 0f11f414b6 Benchmark Framework 2023-02-25 11:52:24 -06:00
Bogdan d397cdf5fb Fixed: (Cardigann) Implement validate as field filter 2023-02-25 17:45:34 +02:00
Bogdan 888b514dd8 Fixed: (Cardigann) Switch to DateTime standard 2023-02-24 15:26:44 +02:00
Bogdan caab337379 Fixed: (Cardigann) Parse text templates only if necessary 2023-02-23 08:02:37 +02:00
Bogdan 26bea14137 Fixed: (GreatPosterWall) Use cookies for 2FA
Co-authored-by: ilike2burnthing <59480337+ilike2burnthing@users.noreply.github.com>
2023-02-23 07:01:36 +02:00
Qstick 5f26287234 Bump version to 1.3.1 2023-02-22 21:40:18 -06:00
Bogdan 6ec761c217 Fixed: (Cardigann) Change UseBeforeResponse to Usebeforeresponse 2023-02-23 02:13:41 +02:00
Bogdan b85679de56 Fixed: Filter releases with null description 2023-02-23 01:29:56 +02:00
Bogdan 71775b97a3 Fixed: (Rarbg) Check for rate limits before parsing token errors 2023-02-22 09:30:22 +02:00
bakerboy448 5bb3dbfbf5 Fixed: (Rarbg) Change app_id per site request 2023-02-21 23:39:30 +02:00
Bogdan b608a7a904 Fixed: (FunFile) Change download url 2023-02-21 23:32:50 +02:00
Bogdan 4ad992f76a Fixed: (UI) Replace api. only if it's a subdomain 2023-02-21 22:59:08 +02:00
Bogdan 95497480a2 Fixed: (GreatPosterWall) Remove cookies only if redirected to login.php 2023-02-21 02:42:26 +02:00
Qstick cc57866ab0 New: Filter releases by search criteria
Co-Authored-By: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-20 18:41:39 -06:00
Qstick dbc4989a95 Fixed: (IndexerSearch) Update isRss logic for new properties 2023-02-20 18:41:39 -06:00
Bogdan af4961e3e6 Fixed: (Rarbg) update cats 2023-02-21 02:38:29 +02:00
Bogdan 0ec54906c6 Fixed: (Caridgann) Custom headers in login and download blocks 2023-02-21 02:37:49 +02:00
Qstick 35f85fc986 More update tests 2023-02-19 23:40:53 -06:00
Qstick 0aedafb278 Fix update tests 2023-02-19 23:09:35 -06:00
Qstick 54dce448a8 Added react-hooks lint rules
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-02-19 23:09:35 -06:00
Servarr 3c915002c6 Automated API Docs update 2023-02-19 19:41:55 -06:00
Qstick e32f8f4330 Remove unused tinytwitter library 2023-02-19 19:26:03 -06:00
Qstick 5abb5ada49 New: Ping Endpoint 2023-02-19 19:23:26 -06:00
Qstick 6579385110 Cleanup multi-platform code 2023-02-19 19:23:05 -06:00
Mark McDowall 1c6e5543df New: Return static response to requests while app is starting 2023-02-19 19:06:13 -06:00
Qstick 85737aacbe Bump version to 1.3.0 2023-02-19 18:14:12 -06:00
Servarr 30c3aedeb1 Automated API Docs update 2023-02-19 17:23:52 -06:00
Qstick 1640980e2b New: OnGrab Notifications 2023-02-19 17:16:05 -06:00
Bogdan 99bc56efb6 Fixed: (Indexers) Rate limit for download and auth 2023-02-19 18:54:17 +02:00
bakerboy448 04276eb587 Fixed: (Rarbg) Updated app_id per site request (#1447) 2023-02-19 18:23:18 +02:00
Bogdan 34c560fd3a Fixed: (CardigannBase) Remedy for casting strings to booleans 2023-02-19 17:07:25 +02:00
Bogdan caa8bb05a7 Fixed: (Newznab API) Response with StatusCode 429 when limits are reached 2023-02-19 10:43:26 +02:00
Qstick 773e8ff1f4 Bump version to 1.2.2 2023-02-19 00:15:54 -06:00
Qstick 0984976378 Bump DryIoc, YamlDotNet, AngleSharp 2023-02-18 21:12:08 -06:00
Qstick fcb3c96455 Call async methods when in an async method 2023-02-18 15:03:35 -06:00
Qstick acf7a425b5 Add global analyzer config 2023-02-18 15:03:35 -06:00
Qstick da898fe958 Remove Non-Failing Rules 2023-02-18 15:03:35 -06:00
Qstick 5bb3ea0806 Remove unnecessary assignments to default type value
The .NET runtime initializes all fields of reference types to their default values before running the constructor. In most cases, explicitly initializing a field to its default value in a constructor is redundant, adding maintenance costs and potentially degrading performance
2023-02-18 15:03:35 -06:00
Qstick b41cb80e33 Use const where appropriate
The value of a const field is computed at compile time and stored in the metadata, which improves run-time performance when it is compared to a static readonly field.
2023-02-18 15:03:35 -06:00
Qstick a39341be4b Enable all analyzers to default back to our rules 2023-02-18 15:03:35 -06:00
Weblate 27b3d8618a Translated using Weblate (Ukrainian)
Currently translated at 73.3% (349 of 476 strings)

Translated using Weblate (Slovak)

Currently translated at 22.6% (108 of 476 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 23.5% (112 of 476 strings)

Translated using Weblate (Catalan)

Currently translated at 74.5% (355 of 476 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN))

Currently translated at 99.5% (474 of 476 strings)

Translated using Weblate (Arabic)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (476 of 476 strings)

Translated using Weblate (Vietnamese)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Turkish)

Currently translated at 71.4% (340 of 476 strings)

Translated using Weblate (Thai)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Swedish)

Currently translated at 86.3% (411 of 476 strings)

Translated using Weblate (Russian)

Currently translated at 76.4% (364 of 476 strings)

Translated using Weblate (Romanian)

Currently translated at 72.0% (343 of 476 strings)

Translated using Weblate (Portuguese)

Currently translated at 79.2% (377 of 476 strings)

Translated using Weblate (Polish)

Currently translated at 74.1% (353 of 476 strings)

Translated using Weblate (Dutch)

Currently translated at 88.4% (421 of 476 strings)

Translated using Weblate (Korean)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Japanese)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Italian)

Currently translated at 99.3% (473 of 476 strings)

Translated using Weblate (Icelandic)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.5% (474 of 476 strings)

Translated using Weblate (Hindi)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Hebrew)

Currently translated at 81.3% (387 of 476 strings)

Translated using Weblate (French)

Currently translated at 98.5% (469 of 476 strings)

Translated using Weblate (Finnish)

Currently translated at 99.1% (472 of 476 strings)

Translated using Weblate (Spanish)

Currently translated at 77.9% (371 of 476 strings)

Translated using Weblate (Greek)

Currently translated at 99.5% (474 of 476 strings)

Translated using Weblate (German)

Currently translated at 98.1% (467 of 476 strings)

Translated using Weblate (Danish)

Currently translated at 74.5% (355 of 476 strings)

Translated using Weblate (Czech)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Spanish)

Currently translated at 77.9% (371 of 476 strings)

Translated using Weblate (Arabic)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Bulgarian)

Currently translated at 67.0% (319 of 476 strings)

Translated using Weblate (Spanish)

Currently translated at 77.9% (371 of 476 strings)

Translated using Weblate (Croatian)

Currently translated at 18.2% (87 of 476 strings)

Translated using Weblate (Croatian)

Currently translated at 18.2% (87 of 476 strings)

Translated using Weblate (Ukrainian)

Currently translated at 73.3% (349 of 476 strings)

Translated using Weblate (Slovak)

Currently translated at 22.6% (108 of 476 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 23.5% (112 of 476 strings)

Translated using Weblate (Catalan)

Currently translated at 74.5% (355 of 476 strings)

Translated using Weblate (Catalan)

Currently translated at 74.5% (355 of 476 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN))

Currently translated at 99.5% (474 of 476 strings)

Translated using Weblate (Arabic)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (476 of 476 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (476 of 476 strings)

Translated using Weblate (Vietnamese)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Turkish)

Currently translated at 71.4% (340 of 476 strings)

Translated using Weblate (Thai)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Swedish)

Currently translated at 86.3% (411 of 476 strings)

Translated using Weblate (Russian)

Currently translated at 76.4% (364 of 476 strings)

Translated using Weblate (Romanian)

Currently translated at 72.0% (343 of 476 strings)

Translated using Weblate (Portuguese)

Currently translated at 79.2% (377 of 476 strings)

Translated using Weblate (Polish)

Currently translated at 74.1% (353 of 476 strings)

Translated using Weblate (Dutch)

Currently translated at 88.4% (421 of 476 strings)

Translated using Weblate (Korean)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Japanese)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Italian)

Currently translated at 99.3% (473 of 476 strings)

Translated using Weblate (Icelandic)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Hungarian)

Currently translated at 99.5% (474 of 476 strings)

Translated using Weblate (Hindi)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Hebrew)

Currently translated at 81.3% (387 of 476 strings)

Translated using Weblate (French)

Currently translated at 98.5% (469 of 476 strings)

Translated using Weblate (Finnish)

Currently translated at 99.1% (472 of 476 strings)

Translated using Weblate (Spanish)

Currently translated at 77.7% (370 of 476 strings)

Translated using Weblate (Greek)

Currently translated at 99.5% (474 of 476 strings)

Translated using Weblate (German)

Currently translated at 98.1% (467 of 476 strings)

Translated using Weblate (Danish)

Currently translated at 74.5% (355 of 476 strings)

Translated using Weblate (Czech)

Currently translated at 71.6% (341 of 476 strings)

Translated using Weblate (Bulgarian)

Currently translated at 67.0% (319 of 476 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Qstick <qstick@gmail.com>
Co-authored-by: TheHrle <Hpranjkovic@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: dtalens <databio@gmail.com>
Co-authored-by: fiego14 <alvaross_96@hotmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-02-18 14:39:38 -06:00
Bogdan 550b9b58df Fixed: (TorrentIndexerBase) Validate downloaded torrent data 2023-02-18 22:13:33 +02:00
Bogdan 035ad33b72 Fixed: (Nebulance) Prevent redirect to login page when downloading torrent files 2023-02-18 21:20:17 +02:00
Qstick 85f8e0c451 Update MagnetLinkBuilder public trackers
https://github.com/ngosang/trackerslist/commit/8ba874e69da0532166644922ea207da3084dff66
2023-02-18 11:49:34 -06:00
bakerboy448 ea2061a7d3 fixup!
Co-authored-by: Bogdan <mynameisbogdan@users.noreply.github.com>
2023-02-18 19:24:47 +02:00
Bakerboy448 ea6d01a49b Fixed: (RarBG) Handle HTTP 200 Rate Limiting False Positive
Fixes: #1277
Finishes: #1169
Related: #1380

partially reverts 5cc044aa8f
2023-02-18 19:24:47 +02:00
Bogdan 252cd97e35 Fixed: (SpeedAppBase) Add pagination 2023-02-18 19:08:02 +02:00
Bogdan a8ea05af07 Fixed: (Nebulance) Add SupportsRedirect since their API is stateless 2023-02-18 19:01:37 +02:00
Bogdan 24d6a0cb06 Fixed: (UI) Remedy for external link regression 2023-02-18 19:01:23 +02:00
Bakerboy448 8e1771b5a9 Fixed: Improved Indexer HTTP Validation Failure Messaging 2023-02-17 11:23:59 +02:00
Bogdan d767a82e84 Fixed: (RuTracker) Add "Use Magnet Links" and "Add RUS to title" options 2023-02-17 07:12:57 +02:00
Bogdan 76bfd29f23 New: Add UniOtaku 2023-02-17 07:12:21 +02:00
Bogdan c923982711 New: (AudioBookBay) Migrate to C# 2023-02-17 07:11:28 +02:00
Bogdan f03a64f9ac Fixed: (Shazbat) Fix Guid 2023-02-15 06:09:06 +02:00
Bogdan e713e58e83 Fixed: (ImmortalSeed) Set RateLimit to 5 2023-02-15 06:08:47 +02:00
Bogdan 4fb5d3432b Fixed: (FileList) Switch to Basic Auth 2023-02-13 02:28:02 +02:00
Qstick a31b107a90 Fix some UI translated strings 2023-02-12 18:22:43 -06:00
Qstick f91ffb8328 New: (Localization) 7 New Languages 2023-02-12 17:57:22 -06:00
Weblate a3ba070296 Added translation using Weblate (Tamil)
Added translation using Weblate (Indonesian)

Added translation using Weblate (Estonian)

Added translation using Weblate (Serbian)

Added translation using Weblate (Croatian)

Added translation using Weblate (Bosnian)

Added translation using Weblate (Spanish (Mexico))

Co-authored-by: Weblate <noreply@weblate.org>
2023-02-12 17:38:07 -06:00
Qstick bccb0bd5c8 Bump version to 1.2.1 2023-02-11 13:25:32 -06:00
Weblate 4517f271c4 Translated using Weblate (Greek)
Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Ukrainian)

Currently translated at 73.4% (346 of 471 strings)

Translated using Weblate (Russian)

Currently translated at 76.6% (361 of 471 strings)

Translated using Weblate (Dutch)

Currently translated at 88.7% (418 of 471 strings)

Translated using Weblate (Hebrew)

Currently translated at 81.5% (384 of 471 strings)

Translated using Weblate (French)

Currently translated at 98.9% (466 of 471 strings)

Translated using Weblate (Greek)

Currently translated at 75.5% (356 of 471 strings)

Translated using Weblate (Danish)

Currently translated at 74.7% (352 of 471 strings)

Translated using Weblate (French)

Currently translated at 97.0% (457 of 471 strings)

Translated using Weblate (French)

Currently translated at 97.0% (457 of 471 strings)

Translated using Weblate (French)

Currently translated at 97.0% (457 of 471 strings)

Translated using Weblate (French)

Currently translated at 96.1% (453 of 471 strings)

Translated using Weblate (French)

Currently translated at 96.1% (453 of 471 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (471 of 471 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: KevoM <lilmarsu@gmail.com>
Co-authored-by: Vasilis Ieropoulos <kirav96@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: louismaxx <lmdupouy@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translation: Servarr/Prowlarr
2023-02-11 11:28:14 -06:00
Qstick 2ae2a0b184 Delete azuresync.yml 2023-02-11 10:35:07 -06:00
Bogdan b5e43e7a1a Fixed: (Cardigann) Show redirect url when the response has errors 2023-02-11 08:28:38 +02:00
Bogdan 3a52048dc2 Fixed: (UI) Check for non-array indexerUrls 2023-02-11 08:27:16 +02:00
Bogdan 8b898733ab Fixed: (RuTracker/Toloka) Clean title 2023-02-10 06:46:02 +02:00
Bogdan f99a2e1164 Fixed: Standardize dashes/single quotes in search term, ignore artist if "VA" 2023-02-10 06:44:39 +02:00
Bogdan 306209fcc2 Fixed: Simplify DateTime alteration 2023-02-09 13:13:16 +02:00
Bogdan 5d09c2b5fa Fixed: (Shazbat) Simplify conditions for CheckIfLoginNeeded 2023-02-09 12:48:39 +02:00
Bogdan 41a9d2d732 New: Add Shazbat 2023-02-09 07:05:29 +02:00
Bogdan 49b120ba55 Revert "Fixed: (Redacted/Orpheus/Libble/SecretCinema) Add SupportsRawSearch"
This reverts commit c46b7c5e4b.
2023-02-08 06:28:05 +02:00
Qstick a88fc34a78 Fixed: Settings fail to save for some auth setups 2023-02-06 23:12:20 -06:00
Bogdan c46b7c5e4b Fixed: (Redacted/Orpheus/Libble/SecretCinema) Add SupportsRawSearch 2023-02-07 07:00:27 +02:00
Bogdan 94c45541ae Fixed: (Anidub/Animedia) Use rate limit in sub-requests 2023-02-07 06:59:48 +02:00
Bogdan f8082047a5 Fixed: (HttpIndexerBase) Catch HttpRequestException/TaskCanceledException 2023-02-05 20:00:10 +02:00
Qstick 011fd57f7d Fixed: Handle null IEnumerable field values in SchemaBuilder 2023-02-05 10:37:35 -06:00
Bogdan 6c35c3fc6f Fixed: (ImmortalSeed/XSpeeds) Sitewide Freeleech 2023-02-05 01:34:36 +02:00
Qstick 5da02c49eb Bump version to 1.2.0 2023-02-04 15:07:01 -06:00
Bogdan 1a339b9ab2 Fixed: (ImmortalSeed) Add sorting to skip the sticky results 2023-02-04 07:39:17 +02:00
Bogdan 94edd7538e Fixed: (GreatPosterWall) Remove JsonProperty 2023-02-04 07:08:58 +02:00
Bogdan 9b2274805e Fixed: (GreatPosterWall) Remove special characters from titles 2023-02-04 07:08:58 +02:00
Bogdan dbf86efb0a Fixed: (ExecuteAuth) Request timeout of 15s by default, if not set otherwise 2023-02-04 05:52:33 +02:00
Weblate 529fbfd9bd Translated using Weblate (Hebrew)
Currently translated at 80.8% (381 of 471 strings)

Translated using Weblate (Greek)

Currently translated at 73.8% (348 of 471 strings)

Translated using Weblate (Danish)

Currently translated at 74.0% (349 of 471 strings)

Co-authored-by: Nir Israel Hen <nirisraelh@gmail.com>
Co-authored-by: Vasilis Ieropoulos <kirav96@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: hhjuhl <hans@kopula.dk>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translation: Servarr/Prowlarr
2023-02-03 21:49:54 -06:00
Bogdan 0ed5bfe0d0 Fixed: (AroLol) Make login possible without 2FA 2023-02-04 05:46:58 +02:00
Bogdan 6a43eb0031 Fixed: (HDBits) Change TVDB search for daily shows, append slash to IndexerUrl 2023-02-04 05:45:38 +02:00
Bogdan a12001a5ef Fixed: (XSpeeds) Category filtering if single, add sorting to skip sticky 2023-02-04 05:42:11 +02:00
Qstick b57014762d Fixed: (RuTracker) Update categories 2023-02-01 22:36:37 -06:00
Bogdan a51a8bf921 Fixed: (GreatPosterWall) Parse categories based on resolution 2023-02-02 06:18:51 +02:00
Martin Häger e8dc5b3206 Serve plain text files (e.g. logs) as UTF-8. 2023-02-01 22:17:30 -06:00
Bogdan d4f22f3596 Fixed: (assorted) Use GetArgumentFromQueryString and other minor fixes 2023-02-02 06:09:13 +02:00
Bogdan b6018a4cd7 Fixed: (norbits) Refactor parsing 2023-02-02 06:06:20 +02:00
Bogdan ec389987df Fixed: (pornolab) Improvements generator/parsing 2023-02-02 06:04:02 +02:00
Bogdan 6b62504916 Fixed: (PreToMe) Improved parsing, login and settings to extend UserPassTorrentBaseSettings 2023-02-02 06:02:31 +02:00
Bogdan 626d777d3c Fixed: (HttpIndexerBase) Add IndexerAuthException to logs 2023-02-02 06:02:17 +02:00
Bogdan 234707b291 Fixed: (SpeedCD) Fix wildcard when using air date 2023-02-02 06:02:01 +02:00
Bogdan 15734ca0da Fixed: (Libble) Minor improvements 2023-02-02 05:28:01 +02:00
Bogdan 19913e5b01 Fixed: (CloudFlareDetection) Check for DDoS-Guard case-insensitive 2023-02-02 05:20:29 +02:00
Qstick 156f6505be Bump version to 1.1.3 2023-01-30 21:21:33 -06:00
Bogdan e383287972 New: Add FunFile 2023-01-31 03:05:00 +02:00
Bogdan 0c0cbdac2f Fixed: (FileList) Add alternative URL and return only FL results when fl-only is set 2023-01-31 02:06:50 +02:00
Bogdan 0685c2eb04 Fixed: (PirateTheNet) Changed the login path 2023-01-30 04:45:25 +02:00
Bogdan e8c132e908 New: Add PirateTheNet 2023-01-29 04:27:58 +02:00
Bogdan bea9bd39ff Fixed: (LazyLibrarian) Sync priority 2023-01-27 03:07:43 +02:00
Bogdan 077e4727f2 New: Add aro.lol 2023-01-27 03:07:05 +02:00
Bogdan 5f7bc82eb5 Fixed: (Anidex) Update indexer capabilities 2023-01-26 04:42:21 +02:00
Bogdan 0dd5c56175 New: Add XSpeeds 2023-01-26 04:11:24 +02:00
Bogdan 409a218379 Fixed: (ImmortalSeed) Parse pre-release dates correctly 2023-01-26 04:11:24 +02:00
Bogdan 07cc1e03c8 Fixed: (Nebulance) Use single wildcard in search 2023-01-25 19:13:43 -06:00
Qstick 560cda8ba0 Bump dotnet to 6.0.13 2023-01-25 19:07:47 -06:00
Weblate 934f566359 Translated using Weblate (Greek)
Currently translated at 73.2% (345 of 471 strings)

Translated using Weblate (French)

Currently translated at 95.1% (448 of 471 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN))

Currently translated at 100.0% (471 of 471 strings)

Co-authored-by: Vasilis Ieropoulos <kirav96@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: aenron <1414004038@qq.com>
Co-authored-by: josehggr <jose.hogger@hotmail.fr>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2023-01-23 23:43:36 -06:00
Bogdan 89ae5ceaa6 Fixed: Remove NotWhatCD 2023-01-24 05:50:19 +02:00
Bogdan c7d5889e59 Fixed: (Newznab) Use NameValueCollection.Set 2023-01-24 04:07:24 +02:00
Bogdan bea3c051b9 Fixed: (Newznab) Remove extra ampersand 2023-01-24 04:07:24 +02:00
Bogdan c0b1675627 Fixed: (AlphaRatio/GreatPosterWall) Add freeleech only and exclude scene settings 2023-01-23 19:56:30 -06:00
Qstick 906d09e162 Bump version to 1.1.2 2023-01-22 16:07:45 -06:00
Bogdan 8cd9ad01c2 Fixed: (Indexers) Use the defined names for C# indexers 2023-01-22 20:08:30 +02:00
Bogdan ce2f322478 New: Add Anidex 2023-01-22 19:50:41 +02:00
Bogdan 0487309ee8 New: Add Toloka.to 2023-01-22 19:49:51 +02:00
Qstick 9862584611 Fixed: Catch InvalidDataException during initial config to prevent boot loop 2023-01-21 17:19:06 -06:00
Qstick 6a00e0db90 Filter useless PG Errors from coming to Sentry 2023-01-21 17:16:54 -06:00
Qstick c93831dd8b Fixed: (TorrentBytes) Avoid null exception in DoLogin error handling 2023-01-21 16:51:19 -06:00
Bogdan 6546ba773c New: (Notification) Apprise 2023-01-21 20:24:28 +02:00
Qstick 4c3484a898 New: (Notifications) Add Ntfy 2023-01-21 12:14:21 -06:00
Qstick 8561b862f9 New: (Notifications) Add Simplepush 2023-01-21 12:13:50 -06:00
Bogdan e1032fb0f5 New: Add optional app minimum seeders per indexer 2023-01-21 11:26:09 -06:00
Bogdan 4063219430 Fixed: (Orpheus) Title improvements to include ReleaseType and fix categories 2023-01-21 11:25:35 -06:00
Bogdan e008be8581 Fixed: (Redacted) Search requests, title improvements 2023-01-21 11:25:35 -06:00
Bogdan d6b379df64 Fixed: Validation inheritance 2023-01-19 21:04:08 -06:00
Bogdan 27094ccf62 Fixed: (ImmortalSeed) Improve tv search with season+ep and parsing, add MR/MST 2023-01-18 18:46:27 -06:00
Bogdan edf9473e9a Fixed: (TorrentDay) Add freeleech only setting 2023-01-18 18:44:22 -06:00
Qstick a0d11e7e33 Bump version to 1.1.1 2023-01-16 21:06:48 -06:00
Bogdan 7729eb398a Fixed: (Nebulance) CS cleanup 2023-01-16 19:48:04 -06:00
Bogdan 989564dbce Fixed: (IPTorrents) Improve clean title 2023-01-16 19:48:04 -06:00
Bogdan c1f917f1ac Fixed: (SpeedCD) Improve clean title 2023-01-16 19:48:04 -06:00
Bogdan 4b7e47c397 Fixed: (RetroFlix) Update description and improve clean title 2023-01-16 19:48:04 -06:00
Bogdan 1529527af9 Fixed: (Cardigann) Bump to v8 2023-01-15 18:20:31 -06:00
Bogdan a11bd1c3c7 Fixed: (GreatPosterWall) Revert category to default to Movies 2023-01-14 22:20:06 -06:00
Bogdan 915b320a4a Fixed: (Shizaproject) Obsolete: Site unavailable 2023-01-14 18:43:32 -06:00
Bogdan 155f72cc45 Fixed: (AvistaZ/CinemaZ) Remove Music category mapping 2023-01-14 18:43:15 -06:00
Bogdan 3f73fec5c3 Fixed: (Rarbg) Add slash to IndexerUrl, increase RateLimit to 5s 2023-01-14 18:06:44 -06:00
Bogdan 8515623ceb Fixed: (SpeedApp) Fix cleanse token from response when it's the only field 2023-01-14 11:53:47 -06:00
Bogdan 963cddb582 Fixed: (SpeedCD) Add wildcard to season in tvsearch, add freeleech toggle, improve query selectors 2023-01-14 10:52:55 -06:00
Bogdan ede323b8ed Fixed: (IPTorrents/SceneTime) Remove advanced from freeleech only setting 2023-01-13 22:32:37 -06:00
Bogdan 07d7fc98b0 Fixed: (Orpheus) Add remaster title and year to release title 2023-01-12 21:41:45 -06:00
Bogdan 1b78fd38db Fixed: (FileList) RequestGenerator refactoring, append slash to IndexerUrl 2023-01-12 21:41:13 -06:00
Bogdan 5a9d4d6280 Fixed: (UI) Transpile ES6 libs to fix issues on some browsers 2023-01-11 21:23:10 -06:00
Qstick 70685de5d2 Fixed: Correctly handle relative redirects with dot segments 2023-01-11 21:20:30 -06:00
Bogdan 9860183433 Fixed: (AvistaZ/Anthelion) Cleanse pid, api_key and token 2023-01-11 21:04:50 -06:00
Qstick 50331c61ae Fixed: Use selected BaseUrl for external link
Fixes #1310
2023-01-10 22:19:15 -06:00
Bogdan bd3408f170 Fixed: (HD-Torrents) Add more alt domains, add Internal flag and fix Blu-Ray categories 2023-01-10 22:01:44 -06:00
Bogdan c043bf8da9 Fixed: (HD-Space) Use torrent name as release title 2023-01-10 22:00:40 -06:00
Bakerboy448 ea3fa6f28d Fixed: (BeyondHD) Cleanse RSSKey on Grabs 2023-01-10 21:59:35 -06:00
Bogdan 8917347c0b Fixed: (IPTorrents) Fix pagination when limit is zero 2023-01-10 13:30:21 -06:00
Bogdan 2cebdf4a06 Fixed: (AvistaZ) Use different timezone offset than the rest 2023-01-09 20:21:56 -06:00
Bogdan 985110cfb9 Fixed: (ImmortalSeed) Updated categories, improved searchUrl build and fixed auth 2023-01-08 15:44:51 -06:00
Bogdan de876247a3 Fixed: (MyAnonamouse) Added search type options, search in description/series/filenames as settings 2023-01-08 15:39:25 -06:00
Qstick bad6c301f8 More CF cases from FlareSolverrSharp 2023-01-08 13:59:17 -06:00
Weblate fc3b23394a Translated using Weblate (Ukrainian)
Currently translated at 67.5% (318 of 471 strings)

Translated using Weblate (Russian)

Currently translated at 76.4% (360 of 471 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Dutch)

Currently translated at 88.5% (417 of 471 strings)

Translated using Weblate (Finnish)

Currently translated at 99.5% (469 of 471 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (471 of 471 strings)

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Davide Palma <github@davidepalma.it>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Iagocds <cdsiago@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: andrey4korop <andrey999@i.ua>
Co-authored-by: verhese <sean.verheyen1@telenet.be>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translation: Servarr/Prowlarr
2023-01-07 13:34:30 -06:00
Qstick 92c3656bad New: (HDSpace) Parse Genre and Description 2023-01-07 13:26:49 -06:00
Qstick 1acbee2a57 New: (Notification) Mailgun
Fixes #1297
2023-01-07 13:14:00 -06:00
Qstick c28f9b6bcd Fix Units in Flaresolverr Timeout 2023-01-06 07:21:56 -06:00
Bogdan aa8048968c Fixed: (Cardigann) Apply RateLimit by using RequestDelay from definitions 2023-01-05 22:39:16 -06:00
Qstick 6646734510 Fixed: (Flaresolverr) Ensure Prowlarr Timeout is sufficient for FS setting 2023-01-05 22:29:15 -06:00
Bogdan 71dd8b6d04 Fixed: Use HashSet to prevent duplicated indexer flags 2023-01-05 22:12:24 -06:00
afpak 6d87bd9f8c Fixed: (IPTorrents) use offset to set page field 2023-01-05 21:50:39 -06:00
Weblate 551d969680 Translated using Weblate (Hungarian)
Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Italian)

Currently translated at 100.0% (471 of 471 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Davide Palma <github@davidepalma.it>
Co-authored-by: Iagocds <cdsiago@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2023-01-05 21:49:03 -06:00
Bogdan 57dac6afdd Fixed: (GreatPosterWall) Use UTC for PublishDate, order releases and map categories accordingly 2023-01-05 21:40:46 -06:00
bakerboy448 3dfbfd07dd improve authentication required wording 2023-01-04 22:53:38 -06:00
Qstick 842df6913c New: Improve CF Detection
Co-Authored-By: Diego Heras <ngosang@hotmail.es>
2023-01-04 22:27:03 -06:00
Qstick 599eeb4c61 Bump Version to 1.1.0 2023-01-03 18:50:42 -06:00
Bogdan da371dd921 Fixed: (Avistaz) Use type password for PID 2023-01-03 18:49:17 -06:00
Bogdan fc25ba7ac0 Fixed: (Filelist) Use UTC in tests 2023-01-03 18:05:54 -06:00
Qstick 6e1bef13e2 Fixed: Correctly calculate UI age for some indexers 2023-01-02 23:28:36 -06:00
Qstick 72ee413411 Fixed: (BeyondHD) Assume Universal Time for publish dates 2023-01-02 23:23:56 -06:00
Qstick e87b45b47e Fixed: (Filelist) Assume UTC+2 for API Dates 2023-01-02 23:23:17 -06:00
Qstick cc841fe3d1 Remove Preview from Page Title 2023-01-02 18:06:34 -06:00
Qstick 264ffdcc26 Fixup Provider Tests 2023-01-02 17:41:41 -06:00
Qstick 5cc044aa8f Rarbg Rate Limit Tweaks, Additional back-off level 2023-01-02 17:16:46 -06:00
Bogdan de2fd92b6f Fixed: (Avistaz) Workaround for fetching "retry-after" header not present when using "Accept: application/json" 2023-01-01 15:31:26 -06:00
Qstick eff09c1f72 Treat Master as a valid branch 2022-12-31 19:32:06 -06:00
Qstick 9db888c9a3 Bump Version to 1.0.1 2022-12-31 18:49:38 -06:00
Qstick bf78396164 Rewrite test to avoid 6 hours of failures and needing a change every year 2022-12-31 18:22:07 -06:00
Qstick 0e7eaa9221 Simplify logic in HandleRequest 2022-12-31 17:57:54 -06:00
Colin Gagnaire 5b82decc31 New: Add support for native Freebox Download Client 2022-12-31 17:34:17 -06:00
Mark McDowall 38ab533272 Fixed: Only log /proc/mounts exception once per process 2022-12-31 17:11:05 -06:00
Qstick 4914fcd5df Fixed: (UI) Category is None in history if only search by sub category 2022-12-31 17:03:27 -06:00
Qstick 858415b037 Fixed: (Cardigann) Query string gets first letter removed in request handling 2022-12-31 16:37:15 -06:00
Bogdan 43f4899324 New: (Indexer) Torrent Libble with 2FA and pagination 2022-12-31 16:22:06 -06:00
Bogdan c60a94adfb Fixed: (RetroFlix) Set 5 days as MST, return 100 results and remove "[REQUESTED]" from title 2022-12-31 16:19:47 -06:00
Qstick f386ddb806 Fixed: Sorting on mobile search UI 2022-12-31 16:17:54 -06:00
Qstick 4175c2577e Fixed: Link to release page from mobile search 2022-12-31 15:56:29 -06:00
Qstick 6ce9e5ceb9 Fixed: Release Grab not working on Mobile search 2022-12-30 18:28:55 -06:00
Bogdan c15643be39 Fixed: (Cardigann) Allow use of template variables in fields selector 2022-12-30 17:58:24 -06:00
Bogdan a58380031d Fixed: (Indexer) Added TvSearchParam.ImdbId to SpeedApp 2022-12-28 23:56:08 -06:00
Bogdan 73af5c9a72 Fixed: (Indexer) Changed FL to use internal flag 2022-12-28 23:54:48 -06:00
Bogdan d556545e7f Fixed: Changed torznab parser to use additional attributes 2022-12-28 23:54:01 -06:00
Bogdan affde5d7b7 Fixed: (Orpheus) Changed to use filters for categories, label and year 2022-12-27 22:16:49 -06:00
Bakerboy448 518c85dee2 Fixed: (Rarbg) Improve RateLimit Handling
Fixed: (Rarbg) Increase delay to 4s to reduce Rate Limiting

Fixes #1169
2022-12-26 18:26:43 -06:00
Bakerboy448 ba3a240707 Add TooManyRequestsException with var retryWait 2022-12-26 18:26:43 -06:00
Qstick 587a73f3d6 Fixed: (Newznab) Parsing of Ids from non-standard feeds
Fixes #1261
2022-12-26 18:17:50 -06:00
Weblate ae8f017ca8 Translated using Weblate (Ukrainian)
Currently translated at 63.2% (298 of 471 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN))

Currently translated at 98.5% (464 of 471 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (471 of 471 strings)

Translated using Weblate (Bengali)

Currently translated at 0.8% (4 of 468 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (468 of 468 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (468 of 468 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: andrey4korop <andrey999@i.ua>
Co-authored-by: lhquark <lhquark@gmail.com>
Co-authored-by: saambd <me@salimrahman.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bn/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translation: Servarr/Prowlarr
2022-12-26 17:52:43 -06:00
Bogdan d9098b612e Fixed: (Nebulance) Changed MinimumSeedTime according to their H&R rules 2022-12-26 17:48:29 -06:00
Qstick 29e7cc06a1 Bump MonoTorrent to 2.0.7
Co-Authored-By: Winter <78392041+winterqt@users.noreply.github.com>
2022-12-24 15:16:00 -06:00
Qstick 387fb0bd15 Revert release analytics 2022-12-22 18:52:38 -06:00
Qstick 2d33560d89 Theme tweaks 2022-12-22 15:29:26 -06:00
Qstick 94a797fc1e New: (Nebulace) TVMaze Search Support
Fixes #1252
2022-12-22 14:32:03 -06:00
Qstick 2e851b0588 New: Mobile friendly manual search
Fixes #490
2022-12-22 13:37:09 -06:00
Qstick 7303cdf555 Fixed: Incorrect logic for newznab category parsing 2022-12-22 10:05:52 -06:00
Qstick 6636cbc4ae Fixed: (AnimeTosho) Mapping of Subcat as Parent 2022-12-22 08:47:45 -06:00
Weblate a5a4f62f25 Translated using Weblate (Bengali)
Currently translated at 0.8% (4 of 468 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (468 of 468 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (468 of 468 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: saambd <me@salimrahman.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bn/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translation: Servarr/Prowlarr
2022-12-21 15:53:44 -06:00
bakerboy448 05a7465a07 Fixed: (MTV) Torznab Api Path
#1235
2022-12-21 15:01:51 -06:00
Qstick c35f1212fb New: (Indexer) Torrent Bytes 2022-12-20 21:57:17 -06:00
Qstick ad95d73e9d Fixed: Category parsing for some not-so-great Torznab feeds
MoreThanTv
2022-12-20 20:50:30 -06:00
Qstick 30f53c20ed New: Convert MoreThanTV to API
Fixes #1235
2022-12-20 17:59:50 -06:00
Servarr 0199a37a0c Automated API Docs update 2022-12-20 16:37:56 -06:00
Qstick e9764820c0 Fixed: (SecretCinema) Title not being decoded
Fixes #1238
2022-12-20 16:24:34 -06:00
Qstick d285cbb021 (SecretCinema) Avoid double HtmlDecode
#1238
2022-12-20 15:20:06 -06:00
Qstick 8afaa3386d Fixed: (PrivateHD) Remove Audio category
Fixes #1246
2022-12-20 15:12:07 -06:00
Qstick c94beb6814 Fixed: Translations for Auth Settings 2022-12-20 14:58:58 -06:00
Qstick c7eb08a0f0 New: Auth Required
Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2022-12-20 14:23:09 -06:00
Qstick 2a2e859420 Update UI Dependencies 2022-12-20 14:23:09 -06:00
Qstick 31f0e8212e Update UI Dev Dependencies 2022-12-20 14:23:09 -06:00
Qstick 1cbb9b1724 Bump dotnet to 6.0.12 2022-12-20 14:23:09 -06:00
Qstick 45dbcc6b89 Bump version to 1.0.0 2022-12-20 14:23:09 -06:00
Qstick 3b26613394 Fixed: (Pornolab) Update Categories
Co-Authored-By: ilike2burnthing <59480337+ilike2burnthing@users.noreply.github.com>
2022-12-20 13:38:01 -06:00
Bakerboy448 6bb8c09fcf Log Skipped Application-Indexer Syncs at trace for support 2022-12-20 13:07:32 -06:00
Qstick 810b3612aa Fixed: Mapping of Year, Genre, other from search string 2022-12-20 12:34:56 -06:00
Qstick 57dcd861a9 Fixed: Validation for nested settings not running
Prevents #1243
2022-12-18 23:20:46 -06:00
Qstick dfe132cda2 Fixed: Retain direct Indexer properties not affiliated with Prowlarr
Fixes #1165
2022-12-18 21:46:14 -06:00
Qstick a635820b48 New: Sync Indexers button on index page
Fixes #92
2022-12-18 21:33:30 -06:00
Qstick d959e81efb Modify Nab tests to pass for additional parameters
Fixes #1236
2022-12-18 21:19:03 -06:00
Qstick ac89cd636f New: Separate setting for Pack Seed Time 2022-12-18 20:52:07 -06:00
Qstick 50616f5c9e Fixed: Don't mess with options we don't set on full sync 2022-12-18 20:52:07 -06:00
Qstick 3f9cb2c6ea Fixed: String compare in arr Indexer equality 2022-12-18 20:52:06 -06:00
Qstick b5aa85a548 New: (Nebulance) Convert to API 2022-12-18 18:12:18 -06:00
Qstick 0fa5127c83 Cleanup dev logging in UI 2022-12-18 12:56:03 -06:00
Weblate 4d137886bc Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (468 of 468 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Dutch)

Currently translated at 89.6% (416 of 464 strings)

Translated using Weblate (German)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (464 of 464 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: benniblot <ben2004engler@gmail.com>
Co-authored-by: mhng98 <mark.groenewegen@hotmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2022-12-18 10:41:16 -06:00
Qstick 9dde041c99 New: Search by description on add indexer modal
Fixes #1000
2022-12-18 00:13:44 -06:00
Qstick a8234c9ce0 Fixed: Refresh applicable healthchecks on bulk deletes 2022-12-18 00:02:59 -06:00
Qstick 9227efdb65 New: (FileList) Freeleech Only option
Fixes #1147
2022-12-17 23:34:08 -06:00
Qstick fa923e658f Fixed: (Nyaa) Torrent Age in UI incorrect
Fixes #144
2022-12-17 23:14:56 -06:00
bakerboy448 364a5564ae update-no-results-msg 2022-12-17 21:34:06 -06:00
Qstick 9efd0b391e fixup! 2022-12-17 21:31:37 -06:00
Qstick 320161e051 New: Smarter Newznab category mapping 2022-12-17 21:31:37 -06:00
Servarr 38ba810ae8 Automated API Docs update 2022-12-17 14:18:15 -06:00
Bakerboy448 4e3f460a24 Fixed: (Avistaz Family) Correct Age Parsing
Co-authored-by: Qstick <qstick@gmail.com>
2022-12-17 14:12:23 -06:00
Qstick 0d918a0aa9 New: Define multiple mapped categories for Download Clients
Fixes #170
2022-12-17 14:11:09 -06:00
Qstick a110412665 Fixed: Stats failing of all indexer events are failures
Fixes #1231
2022-12-17 10:27:14 -06:00
Weblate 6c97f1b6ee Translated using Weblate (Italian)
Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (German)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Dutch)

Currently translated at 89.6% (416 of 464 strings)

Translated using Weblate (Dutch)

Currently translated at 89.6% (416 of 464 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Mipiaceanutella <remix-polity-0l@icloud.com>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Robin Flikkema <robin@robinflikkema.nl>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: kamperzoid <nick@kamper.be>
Co-authored-by: reloxx <reloxx@interia.pl>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translation: Servarr/Prowlarr
2022-12-11 12:47:35 -06:00
Qstick 470779ead2 Bump version to 0.4.11 2022-12-11 12:46:58 -06:00
Erik Persson b371f2d913 New: Added setting to not include animebytes synonyms 2022-12-08 17:54:57 -06:00
Qstick 3ff3452e2d Handling for Obsolete API Endpoints 2022-12-08 17:50:18 -06:00
Qstick df13537e29 Fixed: Use route Id for PUT requests if not passed in body 2022-12-08 17:48:33 -06:00
Qstick 5d2fefde8f Fixed: Correct Attribute compare for Id validation 2022-12-08 17:46:49 -06:00
Qstick ffb3f83324 Simplify X-Forwarded-For handling
This happens in asp.net middleware now

Co-Authored-By: ta264 <ta264@users.noreply.github.com>
2022-12-08 17:45:14 -06:00
Qstick 1c125733b2 New: Improve IPAddress.IsLocal method
Co-Authored-By: ta264 <ta264@users.noreply.github.com>
2022-12-08 17:45:04 -06:00
Mark McDowall 2af7fac15e New: IPv6 support for connections/indexers/download clients 2022-12-08 17:44:24 -06:00
Mark McDowall f172d17ecc Fixed: Improve Bind Address validation and help text 2022-12-08 17:42:55 -06:00
Zak Saunders c69843931e New: Auto theme option to match OS theme
Co-authored-by: Qstick <qstick@gmail.com>
2022-12-08 17:40:59 -06:00
bakerboy448 cd3e99ad87 Fixed: Indexer Error handling improvements (#1172)
* Fixed: Indexer Error handling improvements

* fixup! Fixed: Indexer Error handling improvements
2022-12-01 21:30:27 -06:00
Qstick 1cce39b404 Fix Orpheus Tests 2022-11-29 20:15:23 -06:00
Qstick 9b46ab73e4 Fixed: (Orpheus) Parse date from epoch or date time string 2022-11-29 19:42:35 -06:00
Mark McDowall a352c053ab Fixed: Publish ApplicationStartingEvent during startup
(cherry picked from commit 5400bce1295bdc4198d2cfe0b9258bbb7ccf0852)

Fixes #1199
2022-11-26 10:17:05 -06:00
Weblate b33e45d266 Translated using Weblate (Slovak)
Currently translated at 23.0% (107 of 464 strings)

Translated using Weblate (Norwegian Bokmål)

Currently translated at 23.9% (111 of 464 strings)

Translated using Weblate (Catalan)

Currently translated at 75.6% (351 of 464 strings)

Translated using Weblate (Arabic)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Vietnamese)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Turkish)

Currently translated at 72.8% (338 of 464 strings)

Translated using Weblate (Thai)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Swedish)

Currently translated at 88.1% (409 of 464 strings)

Translated using Weblate (Russian)

Currently translated at 77.5% (360 of 464 strings)

Translated using Weblate (Romanian)

Currently translated at 73.2% (340 of 464 strings)

Translated using Weblate (Portuguese)

Currently translated at 80.8% (375 of 464 strings)

Translated using Weblate (Polish)

Currently translated at 75.6% (351 of 464 strings)

Translated using Weblate (Dutch)

Currently translated at 88.7% (412 of 464 strings)

Translated using Weblate (Korean)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Japanese)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Italian)

Currently translated at 98.0% (455 of 464 strings)

Translated using Weblate (Icelandic)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Hindi)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Hebrew)

Currently translated at 74.5% (346 of 464 strings)

Translated using Weblate (French)

Currently translated at 96.7% (449 of 464 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Spanish)

Currently translated at 79.3% (368 of 464 strings)

Translated using Weblate (Greek)

Currently translated at 72.8% (338 of 464 strings)

Translated using Weblate (German)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (German)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Danish)

Currently translated at 72.8% (338 of 464 strings)

Translated using Weblate (Czech)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Czech)

Currently translated at 73.0% (339 of 464 strings)

Translated using Weblate (Bulgarian)

Currently translated at 68.3% (317 of 464 strings)

Translated using Weblate (German)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (German)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (German)

Currently translated at 99.3% (461 of 464 strings)

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Don-Chris <Chr_Sch@t-online.de>
Co-authored-by: Tordai, Ralph <ralph_t@posteo.de>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Zalhera <tobias.bechen@gmail.com>
Co-authored-by: marapavelka <mara.pavelka@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/vi/
Translation: Servarr/Prowlarr
2022-11-22 19:58:33 -06:00
bakerboy448 817d61de91 Fixed: (SpeedApp) Migrate Legacy URL without slash 2022-11-22 19:57:18 -06:00
Rumplin c7e5cc6462 Removed suspicious URL in the default definitions (#1208)
* Removed suspicious URL in the default definitions

Revert "Removed suspicious URL in the default definitions"

This reverts commit e26853f9aa919cd413b0f8b914ac426f220b9475.

* Update Torznab.cs

Removed suspicious URL from the code. Looks like the site that was originally there doesn't exist anymore and it's hosting malware (HD4Free.xyz).

Co-authored-by: admin <stanislav.ivanov@performit.ie>
2022-11-22 19:56:48 -06:00
Qstick 25596fc2e8 Fixed: Orpheus migration fails on Postgres 2022-11-19 13:59:31 -05:00
Qstick 9ff0b90626 Convert Notifiarr Payload to JSON, Standardize with Webhook (#1194)
* Convert Notifiarr Payload to JSON, Standardize with Webhook

* fixup!
2022-11-13 14:18:44 -05:00
ta264 4f4c011436 Swap Orpheus to API key (#946)
* New: Orpheus uses API key instead of user/pass

* fixup! New: Orpheus uses API key instead of user/pass

Co-authored-by: Qstick <qstick@gmail.com>
2022-11-13 11:07:55 -06:00
Qstick bd0115931f Bump version to 0.4.10 2022-11-12 22:02:13 -06:00
Qstick a0d18c546e Bump version to 0.4.9 2022-11-12 20:03:35 -06:00
Qstick d935b0df82 Fix regression in release analytics service after debounce added
Fixes #1193
2022-11-10 17:39:14 -06:00
Qstick 9e37f69224 Fixed: (RetroFlix) Urls built with double slash
Fixes #1188
Closes #1192
2022-11-10 06:54:20 -06:00
Servarr 2805c4f18b Automated API Docs update 2022-11-07 20:22:57 -06:00
Qstick dae21f22b9 Bump version to 0.4.8 2022-11-07 19:30:14 -06:00
Qstick 7ddbe09eca New: Base API info endpoint 2022-11-07 19:26:54 -06:00
bakerboy448 90e3c809c3 New: Notifiarr moved from webhook to API
New: Notifiarr Add Instance Name Support

Fixed: Notifiarr - Better HTTP Error Handling

also quiet sentry

move apikey to header from url
(cherry picked from commit 1db690ad39ec103c0f4dc89ac4545801ef95bec7)

Fixed: Improve Notifiarr Exception Handling and Validation Errors

(cherry picked from commit 6aaa024d71b939030950460ae986ada5bbae5ad7)
2022-11-07 19:23:16 -06:00
Weblate ec8cf5f57a Translated using Weblate (Finnish)
Currently translated at 99.5% (462 of 464 strings)

Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translation: Servarr/Prowlarr
2022-11-07 19:22:26 -06:00
Bakerboy448 f4bbf2f8af Fixed: (Avistaz) Handle 429 Request Limit Reached 2022-11-04 09:55:11 -05:00
bakerboy448 ea98d41472 Update feature_request.yml
[skip ci]
2022-11-04 09:54:04 -05:00
bakerboy448 b8cb0fd291 update bug report template [skip ci] 2022-11-04 09:54:04 -05:00
Bakerboy448 d3dfa620ac Fix confusing session expired test message 2022-11-04 09:53:27 -05:00
Weblate 049668f307 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN))

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Dutch)

Currently translated at 87.0% (404 of 464 strings)

Translated using Weblate (Hungarian)

Currently translated at 100.0% (464 of 464 strings)

Translated using Weblate (Portuguese)

Currently translated at 78.7% (364 of 462 strings)

Translated using Weblate (Chinese (Traditional) (zh_TW))

Currently translated at 2.8% (13 of 462 strings)

Co-authored-by: Csaba <csab0825@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Thirrian <matthiaslantermann@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: korax1970 <duxlatronum@gmail.com>
Co-authored-by: libsu <libsu@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_TW/
Translation: Servarr/Prowlarr
2022-11-04 09:48:54 -05:00
Yukine c400575aac Fixed: (AnimeBytes) add delimiter to episode release 2022-11-04 09:48:14 -05:00
Yukine 6f122fb2e4 New: (AnimeBytes) add filename support for single episodes 2022-11-04 09:47:52 -05:00
Qstick a9c210f8e7 Create CODE_OF_CONDUCT.md 2022-11-03 15:58:57 -05:00
ta264 1068ba8915 Use wildcard pattern now we have better bsd agent 2022-11-03 11:10:41 +00:00
ta264 635335d876 Revert "Temp disable BSD Tests"
This reverts commit 438ea380f5.
2022-11-03 11:10:41 +00:00
Qstick 2ed51cd933 Fixed: Nullref on Cardigann without login test 2022-10-30 18:06:19 -05:00
Qstick b74c46c554 Ignore brotli test on osx 2022-10-30 13:25:34 -05:00
Qstick 7029e0d6ee Enable new Servarr build notifications 2022-10-25 21:59:08 -05:00
Qstick 438ea380f5 Temp disable BSD Tests 2022-10-25 21:54:19 -05:00
Qstick 4eec675d61 Fix Baker Problems 2022-10-25 21:51:48 -05:00
bakerboy448 0a9bd8287f New: Return 429 for Query and Grab Limits 2022-10-25 21:11:13 -05:00
Qstick b583ac3a97 Fixed: (Cardigann) Rework login required logic
Fixes #1166
2022-10-25 20:21:27 -05:00
bakerboy448 4be41ff3fb fixup! 2022-10-18 10:49:12 -05:00
bakerboy448 b911f8cc08 Fix: (RetroFlix) Update URL to .club
Fixes #1159
2022-10-18 10:49:12 -05:00
Weblate 22face385f Translated using Weblate (Portuguese)
Currently translated at 78.7% (364 of 462 strings)

Translated using Weblate (Chinese (Traditional) (zh_TW))

Currently translated at 2.8% (13 of 462 strings)

Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: korax1970 <duxlatronum@gmail.com>
Co-authored-by: libsu <libsu@qq.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_TW/
Translation: Servarr/Prowlarr
2022-10-14 22:22:40 -05:00
Qstick 3e700b63c2 New: Retry Postgres connection 3 times (with 5 second sleep) on Startup 2022-10-10 22:30:00 -05:00
Qstick df0b8fc660 And another..... 2022-10-09 19:04:30 -05:00
Qstick f96dbbfc21 Ensure FS doesn't fail when no proxy 2022-10-09 19:03:53 -05:00
Qstick 4a75f92cb5 Fixed: (FlareSolverr) Send non-auth global proxy when set
Fixes #1142
2022-10-09 18:33:41 -05:00
Qstick dd05a9dbd4 Obsolete Anthelion C# Indexer 2022-10-09 10:34:40 -05:00
Qstick e78b8d5346 New: Add long term Application status Healthcheck 2022-10-09 10:15:50 -05:00
Qstick 74a1d95ab7 Update NZBIndex Categories 2022-10-08 22:52:17 -05:00
Qstick f929a7e62f New: (Indexer) NZBIndex 2022-10-08 22:14:46 -05:00
Qstick e9e4248af4 New: (Indexer) RetroFlix 2022-10-08 19:18:12 -05:00
Yukine 9e3b43ef12 Fixed: (GreatPosterWall) correctly override Gazelle base method 2022-10-08 18:38:46 -05:00
Qstick 738a690aac Fixed: (Rarbg) Incorrect TVDB param logic
Fixes #1129

Co-Authored-By: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2022-10-08 18:20:41 -05:00
Qstick 3b7c59e9bb Fixed: (Rarbg) More reliable token handling and retry
Fixes #1148
2022-10-08 18:11:22 -05:00
Qstick b8ca28d955 Fixed: Explicitly forbid redirects on Gazelle search requests
Fixes #1144
2022-10-08 15:31:51 -05:00
Yukine 8797bb7d1c Remove unused Gazelle legacy code 2022-10-04 06:46:20 -05:00
Yukine be430732f5 Fixed: (GreatPosterWall) move imdb id search to searchstr query param 2022-10-04 06:46:20 -05:00
h96kikh6 e7b1380b85 Fixed: (Indexer) HDSpace - Added new categories
Added new categories: 45 - HDTV 2160 -> Prowlarr: Movies/UHD (2045), 46 - Movies 2160 -> Prowlarr: TV/UHD (5045), 47 - Doc 2160 -> Prowlarr: TV/Documentary (5080), 48 - Animation 2160 -> Prowlarr: TV/Anime (5070), 49 - XXX 2160 -> Prowlarr: XXX/UHD (6045)
2022-10-02 11:08:51 -05:00
Qstick c29735741c Optimize Indexer updates (v2) 2022-09-29 22:47:00 -05:00
Qstick f56a13a375 Bump Mailkit to 3.4.1 2022-09-29 22:14:25 -05:00
Qstick 148d8ee249 Bump Sentry to 3.21.0 2022-09-29 22:14:25 -05:00
Qstick 3547028b96 Bump YamlDotNet to 12.0.1 2022-09-29 22:14:25 -05:00
Qstick e4ffa1873e Fixed: Definition not updating if local file is missing 2022-09-29 22:13:21 -05:00
Qstick 2e85a21576 Fixed: (GazelleGames) Serialization error on empty response
Fixes #1137
2022-09-29 20:14:18 -05:00
Qstick 0a111e7572 Fixed: (Cardigann) Search path redirect
Fixes #1102
2022-09-26 21:13:57 -05:00
Qstick 25217c0ee8 Fixed: TypeError on Keyup in Firefox for IndexerIndex 2022-09-25 20:44:26 -05:00
Qstick 791592927c Purge old PTP Radarr check 2022-09-25 12:13:49 -05:00
Qstick 4137193a60 Fixed: (Avistaz) FL Only should be checkbox 2022-09-25 10:08:12 -05:00
Qstick 99816bfd36 Fix test error due to DryIOC update 2022-09-24 20:24:17 -05:00
Qstick 59e5b5bd52 Set PooledConnectionLifetime to 10 minutes
Setting PooledConnectinLifetime to a defined number will ensure we don't run into DNS refresh issues
2022-09-18 21:45:10 -05:00
Qstick 7fa0a2b33c Bump Swashbuckle to 6.4.0 2022-09-18 21:43:06 -05:00
Qstick 0593ca6b9e Bump DryIoc to 5.2.2 2022-09-18 21:40:32 -05:00
Qstick 06a26b5c87 Fixed: (RarBG) Don't disable indexer on temp rate limit
Fixes #1027
2022-09-18 15:56:31 -05:00
Weblate dcae6dc151 Translated using Weblate (Slovak)
Currently translated at 12.5% (58 of 462 strings)

Translated using Weblate (Portuguese)

Currently translated at 78.3% (362 of 462 strings)

Translated using Weblate (Portuguese)

Currently translated at 78.3% (362 of 462 strings)

Translated using Weblate (Chinese (Traditional) (zh_TW))

Currently translated at 2.8% (13 of 462 strings)

Translated using Weblate (Finnish)

Currently translated at 100.0% (462 of 462 strings)

Added translation using Weblate (Latvian)

Co-authored-by: Dainel Amendoeira <daniel@amendoeira.eu>
Co-authored-by: Gylesie <github-anon.dasheens@aleeas.com>
Co-authored-by: HiNesslio <chi.lio@shms-mail.ch>
Co-authored-by: Oskari Lavinto <olavinto@protonmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/zh_TW/
Translation: Servarr/Prowlarr
2022-09-18 15:54:43 -05:00
Qstick 04e3ed0ffe Fixed: (Gazelle) Download fails if out of FL tokens
Fixes #1088
2022-09-18 15:39:09 -05:00
Qstick 1ed5ed9179 Bump version to 0.4.7 2022-09-18 14:55:58 -05:00
Qstick d292d086ee Prevent query failures on Cardigann Indexers 2022-09-12 22:49:28 -05:00
Qstick f68915c5dd New: Don't query indexers if they don't support query categories 2022-09-12 22:28:07 -05:00
Qstick 01e970e1a7 New: (Avistaz) Genre Search Support
Fixes #1097
2022-09-12 21:27:32 -05:00
Qstick 68df439498 New: (Avistaz) Freeleech Only Setting
#1108
2022-09-12 21:16:05 -05:00
Qstick 33de7ca7ab Fixed: (MoreThanTv) Parsing issue when download url is null
Fixes #1047
2022-09-10 12:50:32 -05:00
Qstick ae2d9b795b Don't reset request Url when calculating RedirectUrl 2022-09-10 12:24:41 -05:00
Qstick eadea745f8 Warn on redirect to alt domain when checking if login required 2022-09-10 12:24:41 -05:00
Qstick f958c4aefa Bump version to 0.4.6 2022-09-08 20:57:06 -05:00
Weblate 4cf9fb0e79 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (462 of 462 strings)

Translated using Weblate (Portuguese (Brazil))

Currently translated at 99.7% (461 of 462 strings)

Translated using Weblate (French)

Currently translated at 95.6% (442 of 462 strings)

Translated using Weblate (French)

Currently translated at 95.2% (440 of 462 strings)

Translated using Weblate (German)

Currently translated at 99.1% (458 of 462 strings)

Translated using Weblate (French)

Currently translated at 95.2% (440 of 462 strings)

Translated using Weblate (French)

Currently translated at 94.8% (438 of 462 strings)

Translated using Weblate (Spanish)

Currently translated at 77.7% (359 of 462 strings)

Co-authored-by: Fradri <adrien.riotte@live.fr>
Co-authored-by: Gian Klug <gian.klug@ict-scouts.ch>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Mijail Todorovich <mijailtodorovich+git@gmail.com>
Co-authored-by: Thomas Schwery <thomas@schwery.me>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: berrre <zdch6W75@gmail.com>
Co-authored-by: cikyw <cikyw@vomoto.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/pt_BR/
Translation: Servarr/Prowlarr
2022-09-08 20:29:59 -05:00
psylenced bfa68347e6 Fix: Trace logging postgres cleanse for large json files. 2022-09-08 20:28:05 -05:00
Qstick f97b35403d Fixed: Indexer proxies not applying to requests
Fixes #1107
2022-09-05 19:55:46 -05:00
Weblate bf2e057247 Translated using Weblate (Russian)
Currently translated at 76.1% (352 of 462 strings)

Translated using Weblate (Romanian)

Currently translated at 71.8% (332 of 462 strings)

Co-authored-by: AlexR-sf <omg.portal.supp@gmail.com>
Co-authored-by: emanuelsipos <emanuelsipos1@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/prowlarr/ru/
Translation: Servarr/Prowlarr
2022-08-18 23:12:04 -05:00
Qstick 5a278f4e9d Fixed: Set default null value for Genre, Publisher, Douban parameters 2022-08-18 22:30:04 -05:00
Yukine 232a6efd0d New: (Indexer) GreatPosterWall (#1085)
* New: (Indexer) GreatPosterWall

* fix(GreatPosterWall): time is Chinese and not UTC

* feat(GreatPosterWall): add canUseToken check to GetDownloadUrl

* feat(GreatPosterWall): add fileName property as title
2022-08-18 20:04:29 -05:00
Chris 7e01c93b2c Fixed: Regex in log cleanser taking 10+ minutes on messages longer than 100k.
(cherry picked from commit d01bae92bfd68b04c54ab19bafe8af16c68ce711)
2022-08-18 20:03:31 -05:00
Qstick d58f6551e6 Fixed: Set Units for Seed Time settings 2022-08-18 19:56:13 -05:00
542 changed files with 24417 additions and 11372 deletions
+7 -7
View File
@@ -117,7 +117,6 @@ dotnet_diagnostic.CA1003.severity = suggestion
dotnet_diagnostic.CA1008.severity = suggestion
dotnet_diagnostic.CA1010.severity = suggestion
dotnet_diagnostic.CA1012.severity = suggestion
dotnet_diagnostic.CA1014.severity = suggestion
dotnet_diagnostic.CA1016.severity = suggestion
dotnet_diagnostic.CA1017.severity = suggestion
dotnet_diagnostic.CA1018.severity = suggestion
@@ -163,6 +162,7 @@ dotnet_diagnostic.CA1309.severity = suggestion
dotnet_diagnostic.CA1310.severity = suggestion
dotnet_diagnostic.CA1401.severity = suggestion
dotnet_diagnostic.CA1416.severity = suggestion
dotnet_diagnostic.CA1419.severity = suggestion
dotnet_diagnostic.CA1507.severity = suggestion
dotnet_diagnostic.CA1508.severity = suggestion
dotnet_diagnostic.CA1707.severity = suggestion
@@ -178,9 +178,6 @@ dotnet_diagnostic.CA1720.severity = suggestion
dotnet_diagnostic.CA1721.severity = suggestion
dotnet_diagnostic.CA1724.severity = suggestion
dotnet_diagnostic.CA1725.severity = suggestion
dotnet_diagnostic.CA1801.severity = suggestion
dotnet_diagnostic.CA1802.severity = suggestion
dotnet_diagnostic.CA1805.severity = suggestion
dotnet_diagnostic.CA1806.severity = suggestion
dotnet_diagnostic.CA1810.severity = suggestion
dotnet_diagnostic.CA1812.severity = suggestion
@@ -192,13 +189,14 @@ dotnet_diagnostic.CA1819.severity = suggestion
dotnet_diagnostic.CA1822.severity = suggestion
dotnet_diagnostic.CA1823.severity = suggestion
dotnet_diagnostic.CA1824.severity = suggestion
dotnet_diagnostic.CA1835.severity = suggestion
dotnet_diagnostic.CA1845.severity = suggestion
dotnet_diagnostic.CA1848.severity = suggestion
dotnet_diagnostic.CA1849.severity = suggestion
dotnet_diagnostic.CA2000.severity = suggestion
dotnet_diagnostic.CA2002.severity = suggestion
dotnet_diagnostic.CA2007.severity = suggestion
dotnet_diagnostic.CA2008.severity = suggestion
dotnet_diagnostic.CA2009.severity = suggestion
dotnet_diagnostic.CA2010.severity = suggestion
dotnet_diagnostic.CA2011.severity = suggestion
dotnet_diagnostic.CA2012.severity = suggestion
dotnet_diagnostic.CA2013.severity = suggestion
dotnet_diagnostic.CA2100.severity = suggestion
@@ -229,6 +227,7 @@ dotnet_diagnostic.CA2243.severity = suggestion
dotnet_diagnostic.CA2244.severity = suggestion
dotnet_diagnostic.CA2245.severity = suggestion
dotnet_diagnostic.CA2246.severity = suggestion
dotnet_diagnostic.CA2254.severity = suggestion
dotnet_diagnostic.CA3061.severity = suggestion
dotnet_diagnostic.CA3075.severity = suggestion
dotnet_diagnostic.CA3076.severity = suggestion
@@ -255,6 +254,7 @@ dotnet_diagnostic.CA5385.severity = suggestion
dotnet_diagnostic.CA5392.severity = suggestion
dotnet_diagnostic.CA5394.severity = suggestion
dotnet_diagnostic.CA5397.severity = suggestion
dotnet_diagnostic.CA5401.severity = suggestion
dotnet_diagnostic.SYSLIB0014.severity = none
+2 -2
View File
@@ -5,9 +5,9 @@ body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the bug you encountered.
description: Please search to see if an open or closed issue already exists for the bug you encountered. If a bug exists and is closed note that it may only be fixed in an unstable branch.
options:
- label: I have searched the existing issues
- label: I have searched the existing open and closed issues
required: true
- type: textarea
attributes:
+2 -2
View File
@@ -5,9 +5,9 @@ body:
- type: checkboxes
attributes:
label: Is there an existing issue for this?
description: Please search to see if an issue already exists for the feature you are requesting.
description: Please search to see if an open or closed issue already exists for the feature you are requesting. If a request exists and is closed note that it may only be fixed in an unstable branch.
options:
- label: I have searched the existing issues
- label: I have searched the existing open and closed issues
required: true
- type: textarea
attributes:
-41
View File
@@ -1,41 +0,0 @@
name: Sync issue to Azure DevOps work item
on:
issues:
types:
[opened, edited, deleted, closed, reopened, labeled, unlabeled, assigned]
concurrency: azuresync-${{ github.event.issue.number }}
jobs:
alert:
runs-on: ubuntu-latest
steps:
- uses: danhellem/github-actions-issue-to-work-item@master
if: "${{ contains(github.event.issue.labels.*.name, 'Type: Bug') == true }}"
env:
ado_token: "${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}"
github_token: "${{ github.token }}"
ado_organization: "Servarr"
ado_project: "Servarr"
ado_area_path: "Servarr\\Prowlarr"
ado_wit: "Bug"
ado_new_state: "New"
ado_active_state: "Active"
ado_close_state: "Closed"
ado_bypassrules: true
log_level: 100
- uses: danhellem/github-actions-issue-to-work-item@master
if: "${{ contains(github.event.issue.labels.*.name, 'Type: Bug') == false }}"
env:
ado_token: "${{ secrets.ADO_PERSONAL_ACCESS_TOKEN }}"
github_token: "${{ github.token }}"
ado_organization: "Servarr"
ado_project: "Servarr"
ado_area_path: "Servarr\\Prowlarr"
ado_wit: "User Story"
ado_new_state: "New"
ado_active_state: "Active"
ado_close_state: "Closed"
ado_bypassrules: true
log_level: 100
+132
View File
@@ -0,0 +1,132 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
<development@prowlarr.com>.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
+4 -3
View File
@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '0.4.5'
majorVersion: '1.3.1'
minorVersion: $[counter('minorVersion', 1)]
prowlarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(prowlarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.301'
dotnetVersion: '6.0.405'
innoVersion: '6.2.0'
nodeVersion: '16.x'
windowsImage: 'windows-2022'
@@ -748,7 +748,7 @@ stages:
inputs:
buildType: 'current'
artifactName: Packages
itemPattern: '/$(pattern)'
itemPattern: '**/$(pattern)'
targetPath: $(Build.ArtifactStagingDirectory)
- bash: |
mkdir -p ${BUILD_ARTIFACTSTAGINGDIRECTORY}/bin
@@ -1108,4 +1108,5 @@ stages:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
DISCORDCHANNELID: $(discordChannelId)
DISCORDWEBHOOKKEY: $(discordWebhookKey)
DISCORDTHREADID: $(discordThreadId)
-55
View File
@@ -1,55 +0,0 @@
# New Beta Release
Prowlarr v0.2.0.1448 has been released on `develop`
A reminder about the `develop` branch
- **develop - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first. This version will receive updates either weeklyish or bi-weeklyish depending on development.**
# Announcements
- Automated API Documentation Updates recently implemented
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v5](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v5 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
# Additional Commentary
- Lidarr v1 coming to `develop` as beta soon^(tm)
- Readarr official beta on `develop` coming soon^(tm) currently dealing with metadata issues
- [Radarr](https://www.reddit.com/r/radarr/comments/sgrsb3/new_stable_release_master_v4045909/) v4.0.4 released to `master` (stable)
- [Radarr Postgres Database Support coming soon (PR#6873)](https://github.com/radarr/radarr/pull/6873)
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
# Releases
## Native
- [GitHub Releases](https://github.com/Prowlarr/Prowlarr/releases)
- [Wiki Installation Instructions](https://wiki.servarr.com/prowlarr/installation)
## Docker
- [hotio/Prowlarr:testing](https://hotio.dev/containers/prowlarr)
- [lscr.io/linuxserver/Prowlarr:develop](https://docs.linuxserver.io/images/docker-prowlarr)
------------
# Release Notes
## v0.2.0.1448 (changes since v0.2.0.1426)
- Sync Indexers on app start, go to http if not sync'd yet
- Misc definition handling improvements
- Fixed: Updated ruTorrent stopped state helptext
- Fixed: Added missing translate for Database
- Fixed: Download limit check was using the query limit instead of the grab limit.
- Other bug fixes and improvements, see github history
-212
View File
@@ -1,212 +0,0 @@
# New Beta Release
Prowlarr v0.2.0.1678 has been released on `develop`
- **Users who do not wish to be on the alpha `nightly` testing branch should take advantage of this parity and switch to `develop`
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.**
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.**
# Announcements
- Automated API Documentation Updates recently implemented
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v6](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v6 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
# Additional Commentary
- Lidarr v1 coming to `develop` as beta soon^(tm)
- [Lidarr](https://lidarr.audio/donate), [Prowlarr](https://prowlarr.com/donate), [Radarr](https://radarr.video/donate), [Readarr](https://readarr.com/donate) now accept direct bitcoin donations
- [Readarr official beta on `develop` announced](https://www.reddit.com/r/Readarr/comments/sxvj8y/new_beta_release_develop_v0101248/)
- Radarr Postgres Database Support in `nightly`
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
# Releases
## Native
- [GitHub Releases](https://github.com/Prowlarr/Prowlarr/releases)
- [Wiki Installation Instructions](https://wiki.servarr.com/prowlarr/installation)
## Docker
- [hotio/Prowlarr:testing](https://hotio.dev/containers/prowlarr)
- [lscr.io/linuxserver/Prowlarr:develop](https://docs.linuxserver.io/images/docker-prowlarr)
## NAS Packages
- Synology - Please ask the SynoCommunity to update the base package; however, you can update in-app normally
- QNAP - Please ask the QNAP to update the base package; however, you should be able to update in-app normally
------------
# Release Notes
## v0.2.0.1678 (changes since v0.2.0.1448)
- Bump moment from 2.29.1 to 2.29.2
- #834 #256 fix for unable to load the Indexes page
- Fix .editorconfig to disallow `this`
- New: MyAnonamouse freeleech support
- Fixed: (BHD) TMDb Parsing Exception
- Fixed: MoreThanTV indexer from browse page layout changes (#922)
- We don't have two Radarrs
- Fix indent from 37c393a659
- Fixed: (HDBits) Treat 403 as Query Limit
- Fixed: (PTP) Treat 403 as Query Limit
- New: (BTN) Rate Limit to 1 Query per 5 Seconds
- Fixed: (BTN) Handle Query Limit Error
- New: (Lidarr/Radarr/Readarr/Sonarr) Improved Errors
- Fixed: Loading old commands from database
- Fixed: Cleanup Temp files after backup creation
- Add Support
- Translated using Weblate (Finnish)
- Fixed: Indexer Infobox Error (#920)
- New: Indexer Description in Add Indexer Modal
- Fixed: Missing Translates
- New: Add Search Capabilities to Indexer API & InfoBox
- Fixed: Update from version in logs
- Automated API Docs update
- Translated using Weblate (Chinese (Simplified) (zh_CN))
- Translated using Weblate (Portuguese (Brazil))
- Fixed: Validation when testing indexers, connections and download clients
- Fixed: Prevent delete of last profile
- New: Load more (page) results on Search UI
- Update webpack packages
- Frontend Package Updates
- Backend Package Updates
- Bump dotnet to 6.0.3
- Translated using Weblate (Spanish)
- Fixed: (Gazelle) Replace Periods for Space in Search Term
- Fixed: (HDSpace) Replace Periods for Space in Search Term
- Fixed: (Anthelion) Replace Periods for Space in Search Term
- Fixed: (Redacted) Map Categories Comedy & E-Learning Videos to 'Other'
- Fixed: No longer require first run as admin on windows (#885)
- Translated using Weblate (Chinese (Simplified) (zh_CN))
- indexer(xthor): moved to YAML definition v5
- Fixed: '/indexers' URL Base breaking UI navigation
- Translated using Weblate (French)
- Fix app settings delete modal not closing and reloading app profiles
- Translated using Weblate (French)
- Bump Swashbuckle to 6.3.0
- Translated using Weblate (Portuguese (Brazil))
- fixup! New: (DanishBytes) Move to YML
- New: (DanishBytes) Move to YML
- Update translation files
- New: (RuTracker.org) add .bet mirror (#876)
- Fixed:(pornolab) language formatting
- New: Housekeeper for ApplicationStatus
- Fixed: Cleanse Tracker api_token from logs
- New: (HDTorrents) Add hd-torrents.org as Url option
- New: (Cardigann) Allow JSON filters
- Fixed: Convert List<HistoryEventTypes> to Int before passing to DB
- Fixed: WhereBuilder for Postgres
- Translated using Weblate (Finnish)
- Fixed: Make authentication cookie name unique to Prowlarr
- Update Categories
- Fixed: Enable response compression over https
- Fixed: (RuTracker) Update Cats
- Fixed: Clarify App Sync Settings (#847)
- Set version header to X-Application-Version (missing hyphen)
- Go to http if def exists on def server
- Fixed: (BHD) Handle API Auth Errors
- Fixed: (Immortalseed) Keywordless Search
- Fixed: (Cardigann) TraktId was mapping to TvRageId
- New: (Cardigann) - Cardigann v4 Support for Genre, Year, and TraktID
- New: (Cardigann) - Cardigann v4 Support for categorydesc
- New: (Cardigann) - Cardigann v4 Add Support for MapTrackerCatDescToNewznab
- New: (Cardigann) - Cardigann v4 Improved Search Logging
- Fixed: Corrected Query Limit and Grab Limit HelpText
- New: (Avistaz) Better error reporting for unauthorized tests
- Fixed: (Cardigann) Requests Failing for Definitions without LegacyLinks
- Bump SharpZipLib from 1.3.1 to 1.3.3 in /src/NzbDrone.Common
- Fixed: (Cardigann) Smarter redirect domain compare
- Fixed: (Cardigann) Treat "Refresh" header as redirect
- Fixed: (Cardigann) Replace legacy links with default link when making requests
- Other bug fixes and improvements, see GitHub history
-117
View File
@@ -1,117 +0,0 @@
# New Beta Release
Prowlarr v0.3.0.1730 has been released on `develop`
- **Users who do not wish to be on the alpha `nightly` testing branch should take advantage of this parity and switch to `develop`**
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.
# Announcements
- Automated API Documentation Updates recently implemented
- [*Coming Soon* - Better \*Arr App Sync](https://github.com/Prowlarr/Prowlarr/pull/983)
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v6](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v6 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
# Additional Commentary
- Lidarr v1 coming to `develop` as beta soon^(tm)
- [Lidarr](https://lidarr.audio/donate), [Prowlarr](https://prowlarr.com/donate), [Radarr](https://radarr.video/donate), [Readarr](https://readarr.com/donate) now accept direct bitcoin donations
- [Readarr official beta on `develop` announced](https://www.reddit.com/r/Readarr/comments/sxvj8y/new_beta_release_develop_v0101248/)
- Radarr Postgres Database Support in `nightly`
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
# Releases
## Native
- [GitHub Releases](https://github.com/Prowlarr/Prowlarr/releases)
- [Wiki Installation Instructions](https://wiki.servarr.com/prowlarr/installation)
## Docker
- [hotio/Prowlarr:testing](https://hotio.dev/containers/prowlarr)
- [lscr.io/linuxserver/Prowlarr:develop](https://docs.linuxserver.io/images/docker-prowlarr)
## NAS Packages
- Synology - Please ask the SynoCommunity to update the base package; however, you can update in-app normally
- QNAP - Please ask the QNAP to update the base package; however, you should be able to update in-app normally
------------
# Release Notes
## v0.3.0.1730 (changes since v0.3.0.1724)
- Fixed: Prevent endless loop when calling IndexerUrls for Torznab
- Deleted translation using Weblate (Chinese (Min Nan))
- Fix some translations
- Other bug fixes and improvements, see GitHub history
## v0.3.0.1724 (changes since v0.2.0.1678)
- Fixed: Prevent endless loop when calling IndexerUrls for Newznab ( #982 )
- Fixed: Default List for Cardigann LegacyLinks
- New: Auto map known legacy BaseUrls for non-Cardigann
- Fixed: (BTN) Move to HTTPS ( #979 )
- Typo for myanonamouse.
- Fixed: (MoreThanTV) Better Response Cleansing ( #928 )
- New: SceneHD Indexer
- Fixed: (MaM) Handle Auth Errors & Session Expiry
- Fixed: Remove Indexer if categories were changed to not include in sync ( #912 )
- Fixed: Sync Indexers on App Edit
- Cleanup Config Values ( #894 )
- Fixed: (Cardigann) Handle json field selector that returns arrays ( #950 )
- New: Schedule refresh and process monitored download tasks at high priority
- Centralise image choice, update to latest images
- Don't return early after re-running checks after startup grace period ( #7147 )
- Fixed: Delay health check notifications on startup
- New: Add date picker for custom filter dates
- Bump Monotorrent to 2.0.5
- Remove old DotNetVersion method and dep
- New: Add backup size information ( #957 )
- Fixed: (BeyondHD) Use TryCoerceInt for tmdbId ( #960 )
- Fixed: (TorrentDay) TV Search returning Series not S/E Results ( #816 )
- Fixed: (CinemaZ and ExoticaZ) Better Log Cleansing
- Fixed: (exoticaz) Category Parsing
- Fixed: (Indexer) HDTorrents search imdbid + season/episode
- Bump version to 0.3.0
- Other bug fixes and improvements, see GitHub history
-203
View File
@@ -1,203 +0,0 @@
# New Beta Release
Prowlarr v0.4.2.1879 has been released on `develop`
- **Users who do not wish to be on the alpha `nightly` testing branch should take advantage of this parity and switch to `develop`**
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.
# Announcements
- [Prowlarr Cardigann Definitions Schema Versions and Validations created](https://github.com/Prowlarr/indexers#schemas)
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v7](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v6 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
# Additional Commentary
- [Lidarr v1 coming to `master` as recently released](https://www.reddit.com/r/Lidarr/comments/v5fdhi/new_stable_release_master_v1022592/)
- [Lidarr](https://lidarr.audio/donate), [Prowlarr](https://prowlarr.com/donate), [Radarr](https://radarr.video/donate), [Readarr](https://readarr.com/donate) now accept direct bitcoin donations
- [Readarr official beta on `develop` announced](https://www.reddit.com/r/Readarr/comments/sxvj8y/new_beta_release_develop_v0101248/)
- Radarr Postgres Database Support in `nightly` and `develop`
- Prowlarr Postgres Database Support in `nightly` and `develop`
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
- \*Arrs Wiki Contributions welcomed and strongly encouraged, simply auth with GitHub on the wiki and update the page
# Releases
## Native
- [GitHub Releases](https://github.com/Prowlarr/Prowlarr/releases)
- [Wiki Installation Instructions](https://wiki.servarr.com/prowlarr/installation)
## Docker
- [hotio/Prowlarr:testing](https://hotio.dev/containers/prowlarr)
- [lscr.io/linuxserver/Prowlarr:develop](https://docs.linuxserver.io/images/docker-prowlarr)
## NAS Packages
- Synology - Please ask the SynoCommunity to update the base package; however, you can update in-app normally
- QNAP - Please ask the QNAP to update the base package; however, you should be able to update in-app normally
------------
# Release Notes
## v0.4.2.1879 (changes since v0.3.0.1730)
- Don't require user agent for IPTorrents
- Fixed: (Applications) ApiPath can be null from -arr in some cases
- ProtectionService Test Fixture
- Fixed: Lidarr null ref when building indexer for sync
- Fixed: Lidarr null ref when building indexer for sync
- Double MultipartBodyLengthLimit for Backup Restore to 256MB
- Fixed: (IPTorrents) Allow UA override for CF
- Fixed: Log Cleanse Indexer Response Logic and Test Cases
- Fixed: Set update executable permissions correctly
- Fixed: Don't call for server notifications on event driven check
- Update file and folder handling methods from Radarr (#1051)
- Running Integration Tests against Postgres Database (#838)
- Updated NLog Version (#7365)
- Add additional link logging to DownloadService
- Fixed: Correctly remove TorrentParadiseMl
- V6 Cardigann Changes (#1045)
- Sliding expiration for auth cookie and a little clean up
- Bump version to 0.4.2
- Update Sentry to 3.18.0
- Update Swashbuckle to 6.3.1
- Bump dotnet to 6.0.6
- Update AngleSharp to 0.17.0
- Remove ShowRSS C# Implementation
- Swallow HTTP issues on analytics call
- Fix NullRef in analytics service
- Bump version to 0.4.1
- Fix Donation Links
- Fix Tooltips in Dark Theme
- Fixed: (AnimeBytes) Cleanse Passkey from response
- Fixed: (Cardigann) Use variables in keywordsfilters block
- New: (BeyondHD) Better status messages for failures
- Fixed: VIP Healthcheck not triggered for expired indexers
- Use DryIoc for Automoqer, drop Unity dependency
- New: Send description element in nab response
- (Filelist) Update help text for pass key (#1039)
- Fixed: (Exoticaz) Category parsing kills search/feed
- New: (PassThePopcorn) Freeleech only option
- Fixed: (Cardigann) Searching with nab Parent should also use Child categories
- Fixed: Better Cleansing of Tracker Announce Keys
- Automated API Docs update
- Update FE dev dependencies
- Ensure .Mono and .Windows projects have all dependencies in build output
- Fixed: (Gazelle) Parse grouptime as long or date
- Fixed: (ExoticaZ) Category Parsing
- Fixed: Input options background color on mobile
- Fixed: Update AltHub API URL (#1010)
- Automated API Docs update
- New: Dark Theme
- New: Move to CSS Variables for Colorings
- New: Native Theme Engine
- diversify chartcolors for doughnut & stackedbar
- Translated using Weblate (Chinese (Simplified) (zh_CN))
- Catch Postgres log connection errors
- Clean lingering Postgres Connections on Close
- New: Instance name in System/Status API endpoint
- New: Instance name for Page Title
- New: Instance Name used for Syslog
- New: Set Instance Name
- Fixed: Use separate guid for download protection
- Fixed: (RuTracker) Support Raw search from apps
- Fixed: Localization for two part language dialects
- Fixed: (AnimeBytes) Handle series synonyms with commas (#984)
- New: Add Lidarr and Readarr DiscographySeedTime Sync
- New: Add Sonarr SeasonSeedTime Sync
- Fixed: Indexer Tags Helptext
- Automated API Docs update
- New: Seed Settings Sync
- New: Only sync indexers with matching app tags
- Indexer Cleanup
- Bump version to 0.4.0
- Bump version to 0.3.1
- Translated using Weblate (Chinese (Simplified) (zh_CN))
- Fixed: Correct User-Agent api logging
- Other bug fixes and improvements, see GitHub history
-110
View File
@@ -1,110 +0,0 @@
# New Beta Release
Prowlarr v0.4.3.1921 has been released on `develop`
- **Users who do not wish to be on the alpha `nightly` testing branch should take advantage of this parity and switch to `develop`**
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.
# Announcements
- [Prowlarr Cardigann Definitions Schema Versions and Validations created](https://github.com/Prowlarr/indexers#schemas)
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v8](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v8 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
# Additional Commentary
- [Radarr Develop recently released](https://www.reddit.com/r/radarr/comments/w3kik4/new_release_develop_v4206438/)
- [Lidarr](https://lidarr.audio/donate), [Prowlarr](https://prowlarr.com/donate), [Radarr](https://radarr.video/donate), [Readarr](https://readarr.com/donate) now accept direct bitcoin donations
- Radarr Postgres Database Support in `nightly` and `develop`
- Prowlarr Postgres Database Support in `nightly` and `develop`
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
- \*Arrs Wiki Contributions welcomed and strongly encouraged, simply auth with GitHub on the wiki and update the page
# Releases
## Native
- [GitHub Releases](https://github.com/Prowlarr/Prowlarr/releases)
- [Wiki Installation Instructions](https://wiki.servarr.com/prowlarr/installation)
## Docker
- [hotio/Prowlarr:testing](https://hotio.dev/containers/prowlarr)
- [lscr.io/linuxserver/Prowlarr:develop](https://docs.linuxserver.io/images/docker-prowlarr)
## NAS Packages
- Synology - Please ask the SynoCommunity to update the base package; however, you can update in-app normally
- QNAP - Please ask the QNAP to update the base package; however, you should be able to update in-app normally
------------
# Release Notes
## v0.4.3.1921 (changes since v0.4.2.1879)
- Fixed: (GazelleGames) Use API instead of scraping
- Translated using Weblate (Hungarian)
- Automated API Docs update
- New: Search by DoubanId
- Fixed: UI Typos (#1072)
- Translated using Weblate (Chinese (Traditional) (zh_TW))
- Update README.md
- Automated API Docs update
- Debounce analytics service
- Fixed: Set Download and Upload Factors from Generic Torznab
- Translated using Weblate (Portuguese (Brazil))
- Translation Improvements
- Cleanup Language and Localization code
- Added translation using Weblate (Lithuanian)
- Fixed: BeyondHD using improperly cased Content-Type header
- Fix NullRef in Cloudflare detection service
- New: (AvistaZ) Parse Languages and Subs, pass in response
- Rework Cloudflare Protection Detection
- New: (FlareSolverr) DDOS Guard Support
- Bump Mailkit to 3.3.0 (#1054)
- New: Add linux-x86 builds
- Remove unused XmlRPC dependency
- Fixed: (Cardigann) Use Indexer Encoding for Form Parameters
- Fixed: (Cardigann) Use Session Cookie when making SimpleCaptchaCall
- Fixed: Delete CustomFilters not handled properly
- Modern HTTP Client (#685)
- Bump version to 0.4.3
- Other bug fixes and improvements, see GitHub history
-83
View File
@@ -1,83 +0,0 @@
# New Beta Release
Prowlarr v0.4.4.1947 has been released on `develop`
- **Users who do not wish to be on the alpha `nightly` testing branch should take advantage of this parity and switch to `develop`**
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.
# Announcements
- [Prowlarr Cardigann Definitions Schema Versions and Validations created](https://github.com/Prowlarr/indexers#schemas)
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v8](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v8 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
# Additional Commentary
- [Radarr Develop recently released](https://www.reddit.com/r/radarr/comments/w3kik4/new_release_develop_v4206438/)
- [Lidarr](https://lidarr.audio/donate), [Prowlarr](https://prowlarr.com/donate), [Radarr](https://radarr.video/donate), [Readarr](https://readarr.com/donate) now accept direct bitcoin donations
- Radarr Postgres Database Support in `nightly` and `develop`
- Prowlarr Postgres Database Support in `nightly` and `develop`
- Readarr Postgres Database Support in `nightly`
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
- \*Arrs Wiki Contributions welcomed and strongly encouraged, simply auth with GitHub on the wiki and update the page
# Releases
## Native
- [GitHub Releases](https://github.com/Prowlarr/Prowlarr/releases)
- [Wiki Installation Instructions](https://wiki.servarr.com/prowlarr/installation)
## Docker
- [hotio/Prowlarr:testing](https://hotio.dev/containers/prowlarr)
- [lscr.io/linuxserver/Prowlarr:develop](https://docs.linuxserver.io/images/docker-prowlarr)
## NAS Packages
- Synology - Please ask the SynoCommunity to update the base package; however, you can update in-app normally
- QNAP - Please ask the QNAP to update the base package; however, you should be able to update in-app normally
------------
# Release Notes
## v0.4.4.1947 (changes since [v0.4.3.1921](https://www.reddit.com/r/prowlarr/comments/wbanhd/new_develop_release_v0431921/))
- Translated using Weblate (Chinese (Simplified) (zh_CN))
- Fixed: Correctly persist FlareSolverr Cookies to ensure it doesn't run on every request
- Fixed: Correctly use FlareSolverr User Agent
- Remove duplicate package NLog.Extensions in Prowlarr.Common
- Fixed: (Cardigann) fix imatch for rows
- Support for digest auth with HttpRequests
- Fixed: (Cardigann) Genre is optional
- Fixed: (Cardigann) Genre Parsing
- Automated API Docs update
- Fixed: (Cardigann) Genre Parsing for Releases
- Fixed: (Cardigann) messy row strdump
- New: (Cardigann) Additional query support
- Bump version to 0.4.4
- Other bug fixes and improvements, see GitHub history
-6
View File
@@ -1,6 +0,0 @@
- [Prowlarr Cardigann Definitions Schema Versions and Validations created](https://github.com/Prowlarr/indexers#schemas)
- [*Coming Soon* - Newznab & All Indexer Definitions to YML - Cardigann v8](https://github.com/Prowlarr/Prowlarr/pull/823)
- Note that users of Newznab (Usenet) Indexers may see that the UI shows Indexers as added that are not.
- This will be fixed with Cardigann v8 and is due to all the Newznab Indexers sharing the same definition.
- https://i.imgur.com/tijCHlk.png
-6
View File
@@ -1,6 +0,0 @@
- **Users who do not wish to be on the alpha `nightly` testing branch should take advantage of this parity and switch to `develop`**
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.
-6
View File
@@ -1,6 +0,0 @@
- **Users who do not wish to be on the alpha `nightly` or beta `develop` testing branches should take advantage of this parity and switch to `master`
A reminder about the `develop` and `nightly` branches
- **develop** - Current Develop/Beta - (Beta): This is the testing edge. Released after tested in nightly to ensure no immediate issues. New features and bug fixes released here first after nightly. It can be considered semi-stable, but is still beta.**
- **nightly** - Current Nightly/Unstable - (Alpha/Unstable) : This is the bleeding edge. It is released as soon as code is committed and passes all automated tests. This build may have not been used by us or other users yet. There is no guarantee that it will even run in some cases. This branch is only recommended for advanced users. Issues and self investigation are expected in this branch. Use this branch only if you know what you are doing and are willing to get your hands dirty to recover a failed update. This version is updated immediately.**
-7
View File
@@ -1,7 +0,0 @@
- [Radarr Develop recently released](https://www.reddit.com/r/radarr/comments/w3kik4/new_release_develop_v4206438/)
- [Lidarr](https://lidarr.audio/donate), [Prowlarr](https://prowlarr.com/donate), [Radarr](https://radarr.video/donate), [Readarr](https://readarr.com/donate) now accept direct bitcoin donations
- Radarr Postgres Database Support in `nightly` and `develop`
- Prowlarr Postgres Database Support in `nightly` and `develop`
- Readarr Postgres Database Support in `nightly`
- [Lidarr Postgres Database Support in development (Draft PR#2625)](https://github.com/Lidarr/Lidarr/pull/2625)
- \*Arrs Wiki Contributions welcomed and strongly encouraged, simply auth with GitHub on the wiki and update the page
+4 -1
View File
@@ -39,6 +39,7 @@ module.exports = {
plugins: [
'filenames',
'react',
'react-hooks',
'simple-import-sort',
'import'
],
@@ -308,7 +309,9 @@ module.exports = {
'react/react-in-jsx-scope': 2,
'react/self-closing-comp': 2,
'react/sort-comp': 2,
'react/jsx-wrap-multilines': 2
'react/jsx-wrap-multilines': 2,
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'error'
},
overrides: [
{
+2 -2
View File
@@ -142,8 +142,8 @@ module.exports = (env) => {
module: {
rules: [
{
test: /\.js?$/,
exclude: /(node_modules|JsLibraries)/,
test: /\.jsx?$/,
exclude: /[\\/]node_modules[\\/](?!(@sentry\/browser|@sentry\/integrations|chart.js|filesize|normalize.css)[\\/])/,
use: [
{
loader: 'babel-loader',
+5 -4
View File
@@ -1,5 +1,5 @@
import PropTypes from 'prop-types';
import React, { Fragment, useEffect } from 'react';
import React, { Fragment, useCallback, useEffect } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import themes from 'Styles/Themes';
@@ -19,7 +19,8 @@ function createMapStateToProps() {
function ApplyTheme({ theme, children }) {
// Update the CSS Variables
function updateCSSVariables() {
const updateCSSVariables = useCallback(() => {
const arrayOfVariableKeys = Object.keys(themes[theme]);
const arrayOfVariableValues = Object.values(themes[theme]);
@@ -31,12 +32,12 @@ function ApplyTheme({ theme, children }) {
arrayOfVariableValues[index]
);
});
}
}, [theme]);
// On Component Mount and Component Update
useEffect(() => {
updateCSSVariables(theme);
}, [theme]);
}, [updateCSSVariables, theme]);
return <Fragment>{children}</Fragment>;
}
@@ -50,7 +50,7 @@ function CustomFiltersModalContent(props) {
<div className={styles.addButtonContainer}>
<Button onPress={onAddCustomFilter}>
Add Custom Filter
{translate('AddCustomFilter')}
</Button>
</div>
</ModalBody>
@@ -16,6 +16,7 @@ import FormInputHelpText from './FormInputHelpText';
import IndexerFlagsSelectInputConnector from './IndexerFlagsSelectInputConnector';
import InfoInput from './InfoInput';
import KeyValueListInput from './KeyValueListInput';
import NewznabCategorySelectInputConnector from './NewznabCategorySelectInputConnector';
import NumberInput from './NumberInput';
import OAuthInputConnector from './OAuthInputConnector';
import PasswordInput from './PasswordInput';
@@ -68,6 +69,9 @@ function getComponent(type) {
case inputTypes.PATH:
return PathInputConnector;
case inputTypes.CATEGORY_SELECT:
return NewznabCategorySelectInputConnector;
case inputTypes.INDEXER_FLAGS_SELECT:
return IndexerFlagsSelectInputConnector;
@@ -31,7 +31,7 @@ function createMapStateToProps() {
});
return {
value,
value: value || [],
values
};
}
@@ -36,7 +36,6 @@ class TagInputInput extends Component {
<div
ref={forwardedRef}
className={className}
component="div"
onMouseDown={this.onMouseDown}
>
{
+1 -1
View File
@@ -36,5 +36,5 @@
/** Outline **/
.outline {
background-color: var(--white);
background-color: var(--cardBackgroundColor);
}
+1 -1
View File
@@ -108,5 +108,5 @@
/** Outline **/
.outline {
background-color: var(--white);
background-color: var(--cardBackgroundColor);
}
@@ -30,10 +30,10 @@ function ConfirmModal(props) {
useEffect(() => {
if (isOpen) {
bindShortcut('enter', onConfirm);
} else {
unbindShortcut('enter', onConfirm);
return () => unbindShortcut('enter', onConfirm);
}
}, [onConfirm]);
}, [bindShortcut, unbindShortcut, isOpen, onConfirm]);
return (
<Modal
@@ -5,7 +5,7 @@
text-align: center;
&:hover {
color: var(--toobarButtonHoverColor);
color: #515253;
}
}
+7
View File
@@ -4,6 +4,7 @@ import AppUpdatedModalConnector from 'App/AppUpdatedModalConnector';
import ColorImpairedContext from 'App/ColorImpairedContext';
import ConnectionLostModalConnector from 'App/ConnectionLostModalConnector';
import SignalRConnector from 'Components/SignalRConnector';
import AuthenticationRequiredModal from 'FirstRun/AuthenticationRequiredModal';
import locationShape from 'Helpers/Props/Shapes/locationShape';
import PageHeader from './Header/PageHeader';
import PageSidebar from './Sidebar/PageSidebar';
@@ -75,6 +76,7 @@ class Page extends Component {
isSmallScreen,
isSidebarVisible,
enableColorImpairedMode,
authenticationEnabled,
onSidebarToggle,
onSidebarVisibleChange
} = this.props;
@@ -109,6 +111,10 @@ class Page extends Component {
isOpen={this.state.isConnectionLostModalOpen}
onModalClose={this.onConnectionLostModalClose}
/>
<AuthenticationRequiredModal
isOpen={!authenticationEnabled}
/>
</div>
</ColorImpairedContext.Provider>
);
@@ -124,6 +130,7 @@ Page.propTypes = {
isUpdated: PropTypes.bool.isRequired,
isDisconnected: PropTypes.bool.isRequired,
enableColorImpairedMode: PropTypes.bool.isRequired,
authenticationEnabled: PropTypes.bool.isRequired,
onResize: PropTypes.func.isRequired,
onSidebarToggle: PropTypes.func.isRequired,
onSidebarVisibleChange: PropTypes.func.isRequired
@@ -11,6 +11,7 @@ import { fetchAppProfiles, fetchGeneralSettings, fetchIndexerCategories, fetchUI
import { fetchStatus } from 'Store/Actions/systemActions';
import { fetchTags } from 'Store/Actions/tagActions';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createSystemStatusSelector from 'Store/Selectors/createSystemStatusSelector';
import ErrorPage from './ErrorPage';
import LoadingPage from './LoadingPage';
import Page from './Page';
@@ -133,18 +134,21 @@ function createMapStateToProps() {
selectErrors,
selectAppProps,
createDimensionsSelector(),
createSystemStatusSelector(),
(
enableColorImpairedMode,
isPopulated,
errors,
app,
dimensions
dimensions,
systemStatus
) => {
return {
...app,
...errors,
isPopulated,
isSmallScreen: dimensions.isSmallScreen,
authenticationEnabled: systemStatus.authentication !== 'none',
enableColorImpairedMode
};
}
@@ -0,0 +1,34 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import { sizes } from 'Helpers/Props';
import AuthenticationRequiredModalContentConnector from './AuthenticationRequiredModalContentConnector';
function onModalClose() {
// No-op
}
function AuthenticationRequiredModal(props) {
const {
isOpen
} = props;
return (
<Modal
size={sizes.MEDIUM}
isOpen={isOpen}
closeOnBackgroundClick={false}
onModalClose={onModalClose}
>
<AuthenticationRequiredModalContentConnector
onModalClose={onModalClose}
/>
</Modal>
);
}
AuthenticationRequiredModal.propTypes = {
isOpen: PropTypes.bool.isRequired
};
export default AuthenticationRequiredModal;
@@ -0,0 +1,5 @@
.authRequiredAlert {
composes: alert from '~Components/Alert.css';
margin-bottom: 20px;
}
@@ -0,0 +1,165 @@
import PropTypes from 'prop-types';
import React, { useEffect, useRef } from 'react';
import Alert from 'Components/Alert';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import SpinnerButton from 'Components/Link/SpinnerButton';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props';
import { authenticationMethodOptions, authenticationRequiredOptions, authenticationRequiredWarning } from 'Settings/General/SecuritySettings';
import translate from 'Utilities/String/translate';
import styles from './AuthenticationRequiredModalContent.css';
function onModalClose() {
// No-op
}
function AuthenticationRequiredModalContent(props) {
const {
isPopulated,
error,
isSaving,
settings,
onInputChange,
onSavePress,
dispatchFetchStatus
} = props;
const {
authenticationMethod,
authenticationRequired,
username,
password
} = settings;
const authenticationEnabled = authenticationMethod && authenticationMethod.value !== 'none';
const didMount = useRef(false);
useEffect(() => {
if (!isSaving && didMount.current) {
dispatchFetchStatus();
}
didMount.current = true;
}, [isSaving, dispatchFetchStatus]);
return (
<ModalContent
showCloseButton={false}
onModalClose={onModalClose}
>
<ModalHeader>
{translate('AuthenticationRequired')}
</ModalHeader>
<ModalBody>
<Alert
className={styles.authRequiredAlert}
kind={kinds.WARNING}
>
{authenticationRequiredWarning}
</Alert>
{
isPopulated && !error ?
<div>
<FormGroup>
<FormLabel>{translate('Authentication')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="authenticationMethod"
values={authenticationMethodOptions}
helpText={translate('AuthenticationMethodHelpText')}
onChange={onInputChange}
{...authenticationMethod}
/>
</FormGroup>
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('AuthenticationRequired')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="authenticationRequired"
values={authenticationRequiredOptions}
helpText={translate('AuthenticationRequiredHelpText')}
onChange={onInputChange}
{...authenticationRequired}
/>
</FormGroup> :
null
}
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('Username')}</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="username"
onChange={onInputChange}
{...username}
/>
</FormGroup> :
null
}
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('Password')}</FormLabel>
<FormInputGroup
type={inputTypes.PASSWORD}
name="password"
onChange={onInputChange}
{...password}
/>
</FormGroup> :
null
}
</div> :
null
}
{
!isPopulated && !error ? <LoadingIndicator /> : null
}
</ModalBody>
<ModalFooter>
<SpinnerButton
kind={kinds.PRIMARY}
isSpinning={isSaving}
isDisabled={!authenticationEnabled}
onPress={onSavePress}
>
{translate('Save')}
</SpinnerButton>
</ModalFooter>
</ModalContent>
);
}
AuthenticationRequiredModalContent.propTypes = {
isPopulated: PropTypes.bool.isRequired,
error: PropTypes.object,
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
settings: PropTypes.object.isRequired,
onInputChange: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
dispatchFetchStatus: PropTypes.func.isRequired
};
export default AuthenticationRequiredModalContent;
@@ -0,0 +1,86 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearPendingChanges } from 'Store/Actions/baseActions';
import { fetchGeneralSettings, saveGeneralSettings, setGeneralSettingsValue } from 'Store/Actions/settingsActions';
import { fetchStatus } from 'Store/Actions/systemActions';
import createSettingsSectionSelector from 'Store/Selectors/createSettingsSectionSelector';
import AuthenticationRequiredModalContent from './AuthenticationRequiredModalContent';
const SECTION = 'general';
function createMapStateToProps() {
return createSelector(
createSettingsSectionSelector(SECTION),
(sectionSettings) => {
return {
...sectionSettings
};
}
);
}
const mapDispatchToProps = {
dispatchClearPendingChanges: clearPendingChanges,
dispatchSetGeneralSettingsValue: setGeneralSettingsValue,
dispatchSaveGeneralSettings: saveGeneralSettings,
dispatchFetchGeneralSettings: fetchGeneralSettings,
dispatchFetchStatus: fetchStatus
};
class AuthenticationRequiredModalContentConnector extends Component {
//
// Lifecycle
componentDidMount() {
this.props.dispatchFetchGeneralSettings();
}
componentWillUnmount() {
this.props.dispatchClearPendingChanges({ section: `settings.${SECTION}` });
}
//
// Listeners
onInputChange = ({ name, value }) => {
this.props.dispatchSetGeneralSettingsValue({ name, value });
};
onSavePress = () => {
this.props.dispatchSaveGeneralSettings();
};
//
// Render
render() {
const {
dispatchClearPendingChanges,
dispatchFetchGeneralSettings,
dispatchSetGeneralSettingsValue,
dispatchSaveGeneralSettings,
...otherProps
} = this.props;
return (
<AuthenticationRequiredModalContent
{...otherProps}
onInputChange={this.onInputChange}
onSavePress={this.onSavePress}
/>
);
}
}
AuthenticationRequiredModalContentConnector.propTypes = {
dispatchClearPendingChanges: PropTypes.func.isRequired,
dispatchFetchGeneralSettings: PropTypes.func.isRequired,
dispatchSetGeneralSettingsValue: PropTypes.func.isRequired,
dispatchSaveGeneralSettings: PropTypes.func.isRequired,
dispatchFetchStatus: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AuthenticationRequiredModalContentConnector);
+2
View File
@@ -8,6 +8,7 @@ export const DEVICE = 'device';
export const KEY_VALUE_LIST = 'keyValueList';
export const INFO = 'info';
export const MOVIE_MONITORED_SELECT = 'movieMonitoredSelect';
export const CATEGORY_SELECT = 'newznabCategorySelect';
export const NUMBER = 'number';
export const OAUTH = 'oauth';
export const PASSWORD = 'password';
@@ -32,6 +33,7 @@ export const all = [
KEY_VALUE_LIST,
INFO,
MOVIE_MONITORED_SELECT,
CATEGORY_SELECT,
NUMBER,
OAUTH,
PASSWORD,
+45
View File
@@ -226,6 +226,42 @@ class HistoryRow extends Component {
null
}
{
data.label ?
<HistoryRowParameter
title='Label'
value={data.label}
/> :
null
}
{
data.track ?
<HistoryRowParameter
title='Track'
value={data.track}
/> :
null
}
{
data.year ?
<HistoryRowParameter
title='Year'
value={data.year}
/> :
null
}
{
data.genre ?
<HistoryRowParameter
title='Genre'
value={data.genre}
/> :
null
}
{
data.author ?
<HistoryRowParameter
@@ -243,6 +279,15 @@ class HistoryRow extends Component {
/> :
null
}
{
data.publisher ?
<HistoryRowParameter
title='Publisher'
value={data.publisher}
/> :
null
}
</TableRowCell>
);
}
@@ -123,7 +123,7 @@ class AddIndexerModalContent extends Component {
const filteredIndexers = indexers.filter((indexer) => {
const { filter, filterProtocols, filterLanguages, filterPrivacyLevels } = this.state;
if (!indexer.name.toLowerCase().includes(filter.toLocaleLowerCase())) {
if (!indexer.name.toLowerCase().includes(filter.toLocaleLowerCase()) && !indexer.description.toLowerCase().includes(filter.toLocaleLowerCase())) {
return false;
}
@@ -61,15 +61,15 @@ class TagsModalContent extends Component {
} = this.state;
const applyTagsOptions = [
{ key: 'add', value: 'Add' },
{ key: 'remove', value: 'Remove' },
{ key: 'replace', value: 'Replace' }
{ key: 'add', value: translate('Add') },
{ key: 'remove', value: translate('Remove') },
{ key: 'replace', value: translate('Replace') }
];
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Tags
{translate('Tags')}
</ModalHeader>
<ModalBody>
+13 -1
View File
@@ -221,7 +221,7 @@ class IndexerIndex extends Component {
onKeyUp = (event) => {
const jumpBarItems = this.state.jumpBarItems.order;
if (event.path.length === 4) {
if (event.composedPath && event.composedPath().length === 4) {
if (event.keyCode === keyCodes.HOME && event.ctrlKey) {
this.setState({ jumpToCharacter: jumpBarItems[0] });
}
@@ -272,6 +272,7 @@ class IndexerIndex extends Component {
saveError,
isDeleting,
isTestingAll,
isSyncingIndexers,
deleteError,
onScroll,
onSortSelect,
@@ -309,6 +310,15 @@ class IndexerIndex extends Component {
onPress={this.onAddIndexerPress}
/>
<PageToolbarSeparator />
<PageToolbarButton
label={translate('SyncAppIndexers')}
iconName={icons.REFRESH}
isSpinning={isSyncingIndexers}
onPress={this.props.onAppIndexerSyncPress}
/>
<PageToolbarButton
label={translate('TestAllIndexers')}
iconName={icons.TEST}
@@ -493,10 +503,12 @@ IndexerIndex.propTypes = {
saveError: PropTypes.object,
isDeleting: PropTypes.bool.isRequired,
isTestingAll: PropTypes.bool.isRequired,
isSyncingIndexers: PropTypes.bool.isRequired,
deleteError: PropTypes.object,
onSortSelect: PropTypes.func.isRequired,
onFilterSelect: PropTypes.func.isRequired,
onTestAllPress: PropTypes.func.isRequired,
onAppIndexerSyncPress: PropTypes.func.isRequired,
onScroll: PropTypes.func.isRequired,
onSaveSelected: PropTypes.func.isRequired
};
@@ -2,10 +2,13 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import * as commandNames from 'Commands/commandNames';
import withScrollPosition from 'Components/withScrollPosition';
import { executeCommand } from 'Store/Actions/commandActions';
import { testAllIndexers } from 'Store/Actions/indexerActions';
import { saveIndexerEditor, setMovieFilter, setMovieSort, setMovieTableOption } from 'Store/Actions/indexerIndexActions';
import scrollPositions from 'Store/scrollPositions';
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createIndexerClientSideCollectionItemsSelector from 'Store/Selectors/createIndexerClientSideCollectionItemsSelector';
import IndexerIndex from './IndexerIndex';
@@ -13,13 +16,16 @@ import IndexerIndex from './IndexerIndex';
function createMapStateToProps() {
return createSelector(
createIndexerClientSideCollectionItemsSelector('indexerIndex'),
createCommandExecutingSelector(commandNames.APP_INDEXER_SYNC),
createDimensionsSelector(),
(
indexers,
isSyncingIndexers,
dimensionsState
) => {
return {
...indexers,
isSyncingIndexers,
isSmallScreen: dimensionsState.isSmallScreen
};
}
@@ -46,6 +52,12 @@ function createMapDispatchToProps(dispatch, props) {
onTestAllPress() {
dispatch(testAllIndexers());
},
onAppIndexerSyncPress() {
dispatch(executeCommand({
name: commandNames.APP_INDEXER_SYNC
}));
}
};
}
@@ -26,7 +26,7 @@ function IndexerIndexSortMenu(props) {
sortDirection={sortDirection}
onPress={onSortSelect}
>
Status
{translate('Status')}
</SortMenuItem>
<SortMenuItem
@@ -62,7 +62,7 @@ function IndexerIndexSortMenu(props) {
sortDirection={sortDirection}
onPress={onSortSelect}
>
{'Priority'}
{translate('Priority')}
</SortMenuItem>
<SortMenuItem
@@ -71,7 +71,7 @@ function IndexerIndexSortMenu(props) {
sortDirection={sortDirection}
onPress={onSortSelect}
>
{'Protocol'}
{translate('Protocol')}
</SortMenuItem>
<SortMenuItem
@@ -80,7 +80,7 @@ function IndexerIndexSortMenu(props) {
sortDirection={sortDirection}
onPress={onSortSelect}
>
{'Privacy'}
{translate('Privacy')}
</SortMenuItem>
</MenuContent>
</SortMenu>
@@ -14,7 +14,7 @@ function CapabilitiesLabel(props) {
let filteredList = categories.filter((item) => item.id < 100000);
if (categoryFilter.length > 0) {
filteredList = filteredList.filter((item) => categoryFilter.includes(item.id));
filteredList = filteredList.filter((item) => categoryFilter.includes(item.id) || (item.subCategories && item.subCategories.some((r) => categoryFilter.includes(r.id))));
}
const nameList = filteredList.map((item) => item.name).sort();
@@ -79,6 +79,7 @@ class IndexerIndexRow extends Component {
privacy,
priority,
status,
fields,
appProfile,
added,
capabilities,
@@ -96,6 +97,8 @@ class IndexerIndexRow extends Component {
isIndexerInfoModalOpen
} = this.state;
const baseUrl = fields.find((field) => field.name === 'baseUrl')?.value ?? (Array.isArray(indexerUrls) ? indexerUrls[0] : undefined);
return (
<>
{
@@ -245,12 +248,12 @@ class IndexerIndexRow extends Component {
/>
{
indexerUrls ?
baseUrl ?
<IconButton
className={styles.externalLink}
name={icons.EXTERNAL_LINK}
title={translate('Website')}
to={indexerUrls[0].replace('api.', '')}
to={baseUrl.replace(/(:\/\/)api\./, '$1')}
/> : null
}
@@ -299,6 +302,7 @@ IndexerIndexRow.propTypes = {
name: PropTypes.string.isRequired,
enable: PropTypes.bool.isRequired,
redirect: PropTypes.bool.isRequired,
fields: PropTypes.arrayOf(PropTypes.object).isRequired,
appProfile: PropTypes.object.isRequired,
status: PropTypes.object,
capabilities: PropTypes.object,
@@ -20,11 +20,14 @@ function IndexerInfoModalContent(props) {
encoding,
language,
indexerUrls,
fields,
protocol,
capabilities,
onModalClose
} = props;
const baseUrl = fields.find((field) => field.name === 'baseUrl')?.value ?? indexerUrls[0];
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
@@ -57,7 +60,7 @@ function IndexerInfoModalContent(props) {
/>
<DescriptionListItemTitle>{translate('IndexerSite')}</DescriptionListItemTitle>
<DescriptionListItemDescription>
<Link to={indexerUrls[0]}>{indexerUrls[0]}</Link>
<Link to={baseUrl}>{baseUrl}</Link>
</DescriptionListItemDescription>
<DescriptionListItemTitle>{`${protocol === 'usenet' ? 'Newznab' : 'Torznab'} Url`}</DescriptionListItemTitle>
<DescriptionListItemDescription>
@@ -114,6 +117,7 @@ IndexerInfoModalContent.propTypes = {
encoding: PropTypes.string.isRequired,
language: PropTypes.string.isRequired,
indexerUrls: PropTypes.arrayOf(PropTypes.string).isRequired,
fields: PropTypes.arrayOf(PropTypes.object).isRequired,
protocol: PropTypes.string.isRequired,
capabilities: PropTypes.object.isRequired,
onModalClose: PropTypes.func.isRequired
@@ -0,0 +1,49 @@
$hoverScale: 1.05;
.content {
display: flex;
flex-grow: 0;
margin-left: 5px;
}
.container {
border-radius: 4px;
background-color: var(--cardBackgroundColor);
}
.info {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow: hidden;
}
.titleRow {
display: flex;
justify-content: space-between;
flex: 0 0 auto;
margin-bottom: 10px;
height: 38px;
}
.indexerRow {
color: var(--disabledColor);
}
.infoRow {
margin-bottom: 5px;
}
.title {
overflow: hidden;
width: 85%;
font-weight: 500;
font-size: 14px;
overflow-wrap: break-word;
}
.actions {
position: absolute;
right: 0;
white-space: nowrap;
}
@@ -0,0 +1,202 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import TextTruncate from 'react-text-truncate';
import Label from 'Components/Label';
import IconButton from 'Components/Link/IconButton';
import Link from 'Components/Link/Link';
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
import { icons, kinds } from 'Helpers/Props';
import CategoryLabel from 'Search/Table/CategoryLabel';
import Peers from 'Search/Table/Peers';
import ProtocolLabel from 'Search/Table/ProtocolLabel';
import dimensions from 'Styles/Variables/dimensions';
import formatAge from 'Utilities/Number/formatAge';
import formatBytes from 'Utilities/Number/formatBytes';
import translate from 'Utilities/String/translate';
import styles from './SearchIndexOverview.css';
const columnPadding = parseInt(dimensions.movieIndexColumnPadding);
const columnPaddingSmallScreen = parseInt(dimensions.movieIndexColumnPaddingSmallScreen);
function getContentHeight(rowHeight, isSmallScreen) {
const padding = isSmallScreen ? columnPaddingSmallScreen : columnPadding;
return rowHeight - padding;
}
function getDownloadIcon(isGrabbing, isGrabbed, grabError) {
if (isGrabbing) {
return icons.SPINNER;
} else if (isGrabbed) {
return icons.DOWNLOADING;
} else if (grabError) {
return icons.DOWNLOADING;
}
return icons.DOWNLOAD;
}
function getDownloadTooltip(isGrabbing, isGrabbed, grabError) {
if (isGrabbing) {
return '';
} else if (isGrabbed) {
return translate('AddedToDownloadClient');
} else if (grabError) {
return grabError;
}
return translate('AddToDownloadClient');
}
class SearchIndexOverview extends Component {
//
// Listeners
onGrabPress = () => {
const {
guid,
indexerId,
onGrabPress
} = this.props;
onGrabPress({
guid,
indexerId
});
};
//
// Render
render() {
const {
title,
infoUrl,
protocol,
downloadUrl,
categories,
seeders,
leechers,
size,
age,
ageHours,
ageMinutes,
indexer,
rowHeight,
isSmallScreen,
isGrabbed,
isGrabbing,
grabError
} = this.props;
const contentHeight = getContentHeight(rowHeight, isSmallScreen);
return (
<div className={styles.container}>
<div className={styles.content}>
<div className={styles.info} style={{ height: contentHeight }}>
<div className={styles.titleRow}>
<div className={styles.title}>
<Link
to={infoUrl}
title={title}
>
<TextTruncate
line={2}
text={title}
/>
</Link>
</div>
<div className={styles.actions}>
<SpinnerIconButton
name={getDownloadIcon(isGrabbing, isGrabbed, grabError)}
kind={grabError ? kinds.DANGER : kinds.DEFAULT}
title={getDownloadTooltip(isGrabbing, isGrabbed, grabError)}
isDisabled={isGrabbed}
isSpinning={isGrabbing}
onPress={this.onGrabPress}
/>
<IconButton
className={styles.downloadLink}
name={icons.SAVE}
title={translate('Save')}
to={downloadUrl}
/>
</div>
</div>
<div className={styles.indexerRow}>
{indexer}
</div>
<div className={styles.infoRow}>
<ProtocolLabel
protocol={protocol}
/>
{
protocol === 'torrent' &&
<Peers
seeders={seeders}
leechers={leechers}
/>
}
<Label>
{formatBytes(size)}
</Label>
<Label>
{formatAge(age, ageHours, ageMinutes)}
</Label>
<CategoryLabel
categories={categories}
/>
</div>
</div>
</div>
</div>
);
}
}
SearchIndexOverview.propTypes = {
guid: PropTypes.string.isRequired,
categories: PropTypes.arrayOf(PropTypes.object).isRequired,
protocol: PropTypes.string.isRequired,
age: PropTypes.number.isRequired,
ageHours: PropTypes.number.isRequired,
ageMinutes: PropTypes.number.isRequired,
publishDate: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
infoUrl: PropTypes.string.isRequired,
downloadUrl: PropTypes.string.isRequired,
indexerId: PropTypes.number.isRequired,
indexer: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
files: PropTypes.number,
grabs: PropTypes.number,
seeders: PropTypes.number,
leechers: PropTypes.number,
indexerFlags: PropTypes.arrayOf(PropTypes.string).isRequired,
rowHeight: PropTypes.number.isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
longDateFormat: PropTypes.string.isRequired,
timeFormat: PropTypes.string.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
onGrabPress: PropTypes.func.isRequired,
isGrabbing: PropTypes.bool.isRequired,
isGrabbed: PropTypes.bool.isRequired,
grabError: PropTypes.string
};
SearchIndexOverview.defaultProps = {
isGrabbing: false,
isGrabbed: false
};
export default SearchIndexOverview;
@@ -0,0 +1,11 @@
.grid {
flex: 1 0 auto;
}
.container {
&:hover {
.content {
background-color: var(--tableRowHoverBackgroundColor);
}
}
}
@@ -0,0 +1,209 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Grid, WindowScroller } from 'react-virtualized';
import Measure from 'Components/Measure';
import SearchIndexItemConnector from 'Search/Table/SearchIndexItemConnector';
import getIndexOfFirstCharacter from 'Utilities/Array/getIndexOfFirstCharacter';
import hasDifferentItemsOrOrder from 'Utilities/Object/hasDifferentItemsOrOrder';
import SearchIndexOverview from './SearchIndexOverview';
import styles from './SearchIndexOverviews.css';
class SearchIndexOverviews extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
width: 0,
columnCount: 1,
rowHeight: 100,
scrollRestored: false
};
this._grid = null;
}
componentDidUpdate(prevProps, prevState) {
const {
items,
sortKey,
jumpToCharacter,
scrollTop,
isSmallScreen
} = this.props;
const {
width,
rowHeight,
scrollRestored
} = this.state;
if (prevProps.sortKey !== sortKey) {
this.calculateGrid(this.state.width, isSmallScreen);
}
if (
this._grid &&
(prevState.width !== width ||
prevState.rowHeight !== rowHeight ||
hasDifferentItemsOrOrder(prevProps.items, items, 'guid')
)
) {
// recomputeGridSize also forces Grid to discard its cache of rendered cells
this._grid.recomputeGridSize();
}
if (this._grid && scrollTop !== 0 && !scrollRestored) {
this.setState({ scrollRestored: true });
this._grid.scrollToPosition({ scrollTop });
}
if (jumpToCharacter != null && jumpToCharacter !== prevProps.jumpToCharacter) {
const index = getIndexOfFirstCharacter(items, jumpToCharacter);
if (this._grid && index != null) {
this._grid.scrollToCell({
rowIndex: index,
columnIndex: 0
});
}
}
}
//
// Control
setGridRef = (ref) => {
this._grid = ref;
};
calculateGrid = (width = this.state.width, isSmallScreen) => {
const rowHeight = 100;
this.setState({
width,
rowHeight
});
};
cellRenderer = ({ key, rowIndex, style }) => {
const {
items,
showRelativeDates,
shortDateFormat,
longDateFormat,
timeFormat,
isSmallScreen,
onGrabPress
} = this.props;
const {
rowHeight
} = this.state;
const release = items[rowIndex];
return (
<div
className={styles.container}
key={key}
style={style}
>
<SearchIndexItemConnector
key={release.guid}
component={SearchIndexOverview}
rowHeight={rowHeight}
showRelativeDates={showRelativeDates}
shortDateFormat={shortDateFormat}
longDateFormat={longDateFormat}
timeFormat={timeFormat}
isSmallScreen={isSmallScreen}
style={style}
guid={release.guid}
onGrabPress={onGrabPress}
/>
</div>
);
};
//
// Listeners
onMeasure = ({ width }) => {
this.calculateGrid(width, this.props.isSmallScreen);
};
//
// Render
render() {
const {
items
} = this.props;
const {
width,
rowHeight
} = this.state;
return (
<Measure
whitelist={['width']}
onMeasure={this.onMeasure}
>
<WindowScroller
scrollElement={undefined}
>
{({ height, registerChild, onChildScroll, scrollTop }) => {
if (!height) {
return <div />;
}
return (
<div ref={registerChild}>
<Grid
ref={this.setGridRef}
className={styles.grid}
autoHeight={true}
height={height}
columnCount={1}
columnWidth={width}
rowCount={items.length}
rowHeight={rowHeight}
width={width}
onScroll={onChildScroll}
scrollTop={scrollTop}
overscanRowCount={2}
cellRenderer={this.cellRenderer}
scrollToAlignment={'start'}
isScrollingOptOut={true}
/>
</div>
);
}
}
</WindowScroller>
</Measure>
);
}
}
SearchIndexOverviews.propTypes = {
items: PropTypes.arrayOf(PropTypes.object).isRequired,
sortKey: PropTypes.string,
scrollTop: PropTypes.number.isRequired,
jumpToCharacter: PropTypes.string,
scroller: PropTypes.instanceOf(Element).isRequired,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,
longDateFormat: PropTypes.string.isRequired,
isSmallScreen: PropTypes.bool.isRequired,
timeFormat: PropTypes.string.isRequired,
onGrabPress: PropTypes.func.isRequired
};
export default SearchIndexOverviews;
@@ -0,0 +1,32 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { grabRelease } from 'Store/Actions/releaseActions';
import createDimensionsSelector from 'Store/Selectors/createDimensionsSelector';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import SearchIndexOverviews from './SearchIndexOverviews';
function createMapStateToProps() {
return createSelector(
createUISettingsSelector(),
createDimensionsSelector(),
(uiSettings, dimensions) => {
return {
showRelativeDates: uiSettings.showRelativeDates,
shortDateFormat: uiSettings.shortDateFormat,
longDateFormat: uiSettings.longDateFormat,
timeFormat: uiSettings.timeFormat,
isSmallScreen: dimensions.isSmallScreen
};
}
);
}
function createMapDispatchToProps(dispatch, props) {
return {
onGrabPress(payload) {
dispatch(grabRelease(payload));
}
};
}
export default connect(createMapStateToProps, createMapDispatchToProps)(SearchIndexOverviews);
+8 -33
View File
@@ -11,8 +11,6 @@ import PageToolbarSection from 'Components/Page/Toolbar/PageToolbarSection';
import PageToolbarSeparator from 'Components/Page/Toolbar/PageToolbarSeparator';
import TableOptionsModalWrapper from 'Components/Table/TableOptions/TableOptionsModalWrapper';
import { align, icons, sortDirections } from 'Helpers/Props';
import AddIndexerModal from 'Indexer/Add/AddIndexerModal';
import EditIndexerModalConnector from 'Indexer/Edit/EditIndexerModalConnector';
import NoIndexer from 'Indexer/NoIndexer';
import * as keyCodes from 'Utilities/Constants/keyCodes';
import getErrorMessage from 'Utilities/Object/getErrorMessage';
@@ -23,12 +21,17 @@ import selectAll from 'Utilities/Table/selectAll';
import toggleSelected from 'Utilities/Table/toggleSelected';
import SearchIndexFilterMenu from './Menus/SearchIndexFilterMenu';
import SearchIndexSortMenu from './Menus/SearchIndexSortMenu';
import SearchIndexOverviewsConnector from './Mobile/SearchIndexOverviewsConnector';
import NoSearchResults from './NoSearchResults';
import SearchFooterConnector from './SearchFooterConnector';
import SearchIndexTableConnector from './Table/SearchIndexTableConnector';
import styles from './SearchIndex.css';
function getViewComponent() {
function getViewComponent(isSmallScreen) {
if (isSmallScreen) {
return SearchIndexOverviewsConnector;
}
return SearchIndexTableConnector;
}
@@ -44,8 +47,6 @@ class SearchIndex extends Component {
scroller: null,
jumpBarItems: { order: [] },
jumpToCharacter: null,
isAddIndexerModalOpen: false,
isEditIndexerModalOpen: false,
searchType: null,
lastToggled: null,
allSelected: false,
@@ -177,21 +178,6 @@ class SearchIndex extends Component {
//
// Listeners
onAddIndexerPress = () => {
this.setState({ isAddIndexerModalOpen: true });
};
onAddIndexerModalClose = ({ indexerSelected = false } = {}) => {
this.setState({
isAddIndexerModalOpen: false,
isEditIndexerModalOpen: indexerSelected
});
};
onEditIndexerModalClose = () => {
this.setState({ isEditIndexerModalOpen: false });
};
onJumpBarItemPress = (jumpToCharacter) => {
this.setState({ jumpToCharacter });
};
@@ -253,6 +239,7 @@ class SearchIndex extends Component {
onScroll,
onSortSelect,
onFilterSelect,
isSmallScreen,
hasIndexers,
...otherProps
} = this.props;
@@ -260,8 +247,6 @@ class SearchIndex extends Component {
const {
scroller,
jumpBarItems,
isAddIndexerModalOpen,
isEditIndexerModalOpen,
jumpToCharacter,
selectedState,
allSelected,
@@ -270,7 +255,7 @@ class SearchIndex extends Component {
const selectedIndexerIds = this.getSelectedIds();
const ViewComponent = getViewComponent();
const ViewComponent = getViewComponent(isSmallScreen);
const isLoaded = !!(!error && isPopulated && items.length && scroller);
const hasNoIndexer = !totalItems;
@@ -384,16 +369,6 @@ class SearchIndex extends Component {
onSearchPress={this.onSearchPress}
onBulkGrabPress={this.onBulkGrabPress}
/>
<AddIndexerModal
isOpen={isAddIndexerModalOpen}
onModalClose={this.onAddIndexerModalClose}
/>
<EditIndexerModalConnector
isOpen={isEditIndexerModalOpen}
onModalClose={this.onEditIndexerModalClose}
/>
</PageContent>
);
}
@@ -14,7 +14,7 @@
.category {
composes: headerCell from '~Components/Table/VirtualTableHeaderCell.css';
flex: 0 0 110px;
flex: 0 0 130px;
}
.age,
@@ -18,20 +18,20 @@ function createMapStateToProps() {
return createSelector(
createReleaseSelector(),
(
movie
release
) => {
// If a movie is deleted this selector may fire before the parent
// selecors, which will result in an undefined movie, if that happens
// If a release is deleted this selector may fire before the parent
// selecors, which will result in an undefined release, if that happens
// we want to return early here and again in the render function to avoid
// trying to show a movie that has no information available.
// trying to show a release that has no information available.
if (!movie) {
if (!release) {
return {};
}
return {
...movie
...release
};
}
);
@@ -41,7 +41,7 @@ const mapDispatchToProps = {
dispatchExecuteCommand: executeCommand
};
class MovieIndexItemConnector extends Component {
class SearchIndexItemConnector extends Component {
//
// Render
@@ -66,9 +66,9 @@ class MovieIndexItemConnector extends Component {
}
}
MovieIndexItemConnector.propTypes = {
SearchIndexItemConnector.propTypes = {
guid: PropTypes.string,
component: PropTypes.elementType.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(MovieIndexItemConnector);
export default connect(createMapStateToProps, mapDispatchToProps)(SearchIndexItemConnector);
+1 -1
View File
@@ -21,7 +21,7 @@
.category {
composes: cell;
flex: 0 0 110px;
flex: 0 0 130px;
}
.age,
+16 -2
View File
@@ -71,6 +71,19 @@ class SearchIndexRow extends Component {
});
};
onSavePress = () => {
const {
downloadUrl,
fileName,
onSavePress
} = this.props;
onSavePress({
downloadUrl,
fileName
});
};
//
// Render
@@ -85,7 +98,6 @@ class SearchIndexRow extends Component {
publishDate,
title,
infoUrl,
downloadUrl,
indexer,
size,
files,
@@ -300,7 +312,7 @@ class SearchIndexRow extends Component {
className={styles.downloadLink}
name={icons.SAVE}
title={translate('Save')}
to={downloadUrl}
onPress={this.onSavePress}
/>
</VirtualTableRowCell>
);
@@ -323,6 +335,7 @@ SearchIndexRow.propTypes = {
ageMinutes: PropTypes.number.isRequired,
publishDate: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
fileName: PropTypes.string.isRequired,
infoUrl: PropTypes.string.isRequired,
downloadUrl: PropTypes.string.isRequired,
indexerId: PropTypes.number.isRequired,
@@ -335,6 +348,7 @@ SearchIndexRow.propTypes = {
indexerFlags: PropTypes.arrayOf(PropTypes.string).isRequired,
columns: PropTypes.arrayOf(PropTypes.object).isRequired,
onGrabPress: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
isGrabbing: PropTypes.bool.isRequired,
isGrabbed: PropTypes.bool.isRequired,
grabError: PropTypes.string,
@@ -51,7 +51,8 @@ class SearchIndexTable extends Component {
timeFormat,
selectedState,
onSelectedChange,
onGrabPress
onGrabPress,
onSavePress
} = this.props;
const release = items[rowIndex];
@@ -71,6 +72,7 @@ class SearchIndexTable extends Component {
longDateFormat={longDateFormat}
timeFormat={timeFormat}
onGrabPress={onGrabPress}
onSavePress={onSavePress}
/>
</VirtualTableRow>
);
@@ -134,6 +136,7 @@ SearchIndexTable.propTypes = {
timeFormat: PropTypes.string.isRequired,
onSortPress: PropTypes.func.isRequired,
onGrabPress: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
allSelected: PropTypes.bool.isRequired,
allUnselected: PropTypes.bool.isRequired,
selectedState: PropTypes.object.isRequired,
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { grabRelease, setReleasesSort } from 'Store/Actions/releaseActions';
import { grabRelease, saveRelease, setReleasesSort } from 'Store/Actions/releaseActions';
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
import SearchIndexTable from './SearchIndexTable';
@@ -25,6 +25,9 @@ function createMapDispatchToProps(dispatch, props) {
},
onGrabPress(payload) {
dispatch(grabRelease(payload));
},
onSavePress(payload) {
dispatch(saveRelease(payload));
}
};
}
@@ -28,7 +28,7 @@ class AddApplicationModalContent extends Component {
return (
<ModalContent onModalClose={onModalClose}>
<ModalHeader>
Add Application
{translate('AddApplication')}
</ModalHeader>
<ModalBody>
@@ -71,14 +71,14 @@ class Application extends Component {
{
syncLevel === 'addOnly' &&
<Label kind={kinds.WARNING}>
Add and Remove Only
{translate('AddRemoveOnly')}
</Label>
}
{
syncLevel === 'fullSync' &&
<Label kind={kinds.SUCCESS}>
Full Sync
{translate('FullSync')}
</Label>
}
@@ -88,7 +88,7 @@ class Application extends Component {
kind={kinds.DISABLED}
outline={true}
>
Disabled
{translate('Disabled')}
</Label>
}
@@ -0,0 +1,27 @@
import PropTypes from 'prop-types';
import React from 'react';
import Modal from 'Components/Modal/Modal';
import { sizes } from 'Helpers/Props';
import AddCategoryModalContentConnector from './AddCategoryModalContentConnector';
function AddCategoryModal({ isOpen, onModalClose, ...otherProps }) {
return (
<Modal
size={sizes.MEDIUM}
isOpen={isOpen}
onModalClose={onModalClose}
>
<AddCategoryModalContentConnector
{...otherProps}
onModalClose={onModalClose}
/>
</Modal>
);
}
AddCategoryModal.propTypes = {
isOpen: PropTypes.bool.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default AddCategoryModal;
@@ -0,0 +1,50 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { clearPendingChanges } from 'Store/Actions/baseActions';
import AddCategoryModal from './AddCategoryModal';
function createMapDispatchToProps(dispatch, props) {
const section = 'settings.downloadClientCategories';
return {
dispatchClearPendingChanges() {
dispatch(clearPendingChanges({ section }));
}
};
}
class AddCategoryModalConnector extends Component {
//
// Listeners
onModalClose = () => {
this.props.dispatchClearPendingChanges();
this.props.onModalClose();
};
//
// Render
render() {
const {
dispatchClearPendingChanges,
...otherProps
} = this.props;
return (
<AddCategoryModal
{...otherProps}
onModalClose={this.onModalClose}
/>
);
}
}
AddCategoryModalConnector.propTypes = {
onModalClose: PropTypes.func.isRequired,
dispatchClearPendingChanges: PropTypes.func.isRequired
};
export default connect(null, createMapDispatchToProps)(AddCategoryModalConnector);
@@ -0,0 +1,5 @@
.deleteButton {
composes: button from '~Components/Link/Button.css';
margin-right: auto;
}
@@ -0,0 +1,111 @@
import PropTypes from 'prop-types';
import React from 'react';
import Form from 'Components/Form/Form';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import Button from 'Components/Link/Button';
import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import styles from './AddCategoryModalContent.css';
function AddCategoryModalContent(props) {
const {
advancedSettings,
item,
onInputChange,
onFieldChange,
onCancelPress,
onSavePress,
onDeleteSpecificationPress,
...otherProps
} = props;
const {
id,
clientCategory,
categories
} = item;
return (
<ModalContent onModalClose={onCancelPress}>
<ModalHeader>
{`${id ? 'Edit' : 'Add'} Category`}
</ModalHeader>
<ModalBody>
<Form
{...otherProps}
>
<FormGroup>
<FormLabel>
{translate('DownloadClientCategory')}
</FormLabel>
<FormInputGroup
type={inputTypes.TEXT}
name="clientCategory"
{...clientCategory}
onChange={onInputChange}
/>
</FormGroup>
<FormGroup>
<FormLabel>
{translate('MappedCategories')}
</FormLabel>
<FormInputGroup
type={inputTypes.CATEGORY_SELECT}
name="categories"
{...categories}
onChange={onInputChange}
/>
</FormGroup>
</Form>
</ModalBody>
<ModalFooter>
{
id &&
<Button
className={styles.deleteButton}
kind={kinds.DANGER}
onPress={onDeleteSpecificationPress}
>
{translate('Delete')}
</Button>
}
<Button
onPress={onCancelPress}
>
{translate('Cancel')}
</Button>
<SpinnerErrorButton
isSpinning={false}
onPress={onSavePress}
>
{translate('Save')}
</SpinnerErrorButton>
</ModalFooter>
</ModalContent>
);
}
AddCategoryModalContent.propTypes = {
advancedSettings: PropTypes.bool.isRequired,
item: PropTypes.object.isRequired,
onInputChange: PropTypes.func.isRequired,
onFieldChange: PropTypes.func.isRequired,
onCancelPress: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
onDeleteSpecificationPress: PropTypes.func
};
export default AddCategoryModalContent;
@@ -0,0 +1,78 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { clearDownloadClientCategoryPending, saveDownloadClientCategory, setDownloadClientCategoryFieldValue, setDownloadClientCategoryValue } from 'Store/Actions/settingsActions';
import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
import AddCategoryModalContent from './AddCategoryModalContent';
function createMapStateToProps() {
return createSelector(
(state) => state.settings.advancedSettings,
createProviderSettingsSelector('downloadClientCategories'),
(advancedSettings, specification) => {
return {
advancedSettings,
...specification
};
}
);
}
const mapDispatchToProps = {
setDownloadClientCategoryValue,
setDownloadClientCategoryFieldValue,
saveDownloadClientCategory,
clearDownloadClientCategoryPending
};
class AddCategoryModalContentConnector extends Component {
//
// Listeners
onInputChange = ({ name, value }) => {
this.props.setDownloadClientCategoryValue({ name, value });
};
onFieldChange = ({ name, value }) => {
this.props.setDownloadClientCategoryFieldValue({ name, value });
};
onCancelPress = () => {
this.props.clearDownloadClientCategoryPending();
this.props.onModalClose();
};
onSavePress = () => {
this.props.saveDownloadClientCategory({ id: this.props.id });
this.props.onModalClose();
};
//
// Render
render() {
return (
<AddCategoryModalContent
{...this.props}
onCancelPress={this.onCancelPress}
onSavePress={this.onSavePress}
onInputChange={this.onInputChange}
onFieldChange={this.onFieldChange}
/>
);
}
}
AddCategoryModalContentConnector.propTypes = {
id: PropTypes.number,
item: PropTypes.object.isRequired,
setDownloadClientCategoryValue: PropTypes.func.isRequired,
setDownloadClientCategoryFieldValue: PropTypes.func.isRequired,
clearDownloadClientCategoryPending: PropTypes.func.isRequired,
saveDownloadClientCategory: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired
};
export default connect(createMapStateToProps, mapDispatchToProps)(AddCategoryModalContentConnector);
@@ -0,0 +1,32 @@
.customFormat {
composes: card from '~Components/Card.css';
width: 300px;
}
.nameContainer {
display: flex;
justify-content: space-between;
}
.name {
@add-mixin truncate;
margin-bottom: 5px;
font-weight: 300;
font-size: 20px;
}
.labels {
display: flex;
flex-wrap: wrap;
margin-top: 5px;
pointer-events: all;
}
.tooltipLabel {
composes: label from '~Components/Label.css';
margin: 0;
border: none;
}
@@ -0,0 +1,111 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Card from 'Components/Card';
import Label from 'Components/Label';
import ConfirmModal from 'Components/Modal/ConfirmModal';
import { kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import AddCategoryModalConnector from './AddCategoryModalConnector';
import styles from './Category.css';
class Category extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
isEditSpecificationModalOpen: false,
isDeleteSpecificationModalOpen: false
};
}
//
// Listeners
onEditSpecificationPress = () => {
this.setState({ isEditSpecificationModalOpen: true });
};
onEditSpecificationModalClose = () => {
this.setState({ isEditSpecificationModalOpen: false });
};
onDeleteSpecificationPress = () => {
this.setState({
isEditSpecificationModalOpen: false,
isDeleteSpecificationModalOpen: true
});
};
onDeleteSpecificationModalClose = () => {
this.setState({ isDeleteSpecificationModalOpen: false });
};
onConfirmDeleteSpecification = () => {
this.props.onConfirmDeleteSpecification(this.props.id);
};
//
// Lifecycle
render() {
const {
id,
clientCategory,
categories
} = this.props;
return (
<Card
className={styles.customFormat}
overlayContent={true}
onPress={this.onEditSpecificationPress}
>
<div className={styles.nameContainer}>
<div className={styles.name}>
{clientCategory}
</div>
</div>
<Label kind={kinds.PRIMARY}>
{`${categories.length} ${categories.length > 1 ? translate('Categories') : translate('Category')}`}
</Label>
<AddCategoryModalConnector
id={id}
isOpen={this.state.isEditSpecificationModalOpen}
onModalClose={this.onEditSpecificationModalClose}
onDeleteSpecificationPress={this.onDeleteSpecificationPress}
/>
<ConfirmModal
isOpen={this.state.isDeleteSpecificationModalOpen}
kind={kinds.DANGER}
title={translate('DeleteClientCategory')}
message={
<div>
<div>
{translate('AreYouSureYouWantToDeleteCategory', [name])}
</div>
</div>
}
confirmLabel={translate('Delete')}
onConfirm={this.onConfirmDeleteSpecification}
onCancel={this.onDeleteSpecificationModalClose}
/>
</Card>
);
}
}
Category.propTypes = {
id: PropTypes.number.isRequired,
categories: PropTypes.arrayOf(PropTypes.number).isRequired,
clientCategory: PropTypes.string.isRequired,
onConfirmDeleteSpecification: PropTypes.func.isRequired
};
export default Category;
@@ -1,11 +1,14 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import Alert from 'Components/Alert';
import Card from 'Components/Card';
import FieldSet from 'Components/FieldSet';
import Form from 'Components/Form/Form';
import FormGroup from 'Components/Form/FormGroup';
import FormInputGroup from 'Components/Form/FormInputGroup';
import FormLabel from 'Components/Form/FormLabel';
import ProviderFieldFormGroup from 'Components/Form/ProviderFieldFormGroup';
import Icon from 'Components/Icon';
import Button from 'Components/Link/Button';
import SpinnerErrorButton from 'Components/Link/SpinnerErrorButton';
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
@@ -13,12 +16,33 @@ import ModalBody from 'Components/Modal/ModalBody';
import ModalContent from 'Components/Modal/ModalContent';
import ModalFooter from 'Components/Modal/ModalFooter';
import ModalHeader from 'Components/Modal/ModalHeader';
import { inputTypes, kinds } from 'Helpers/Props';
import { icons, inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
import AddCategoryModalConnector from './Categories/AddCategoryModalConnector';
import Category from './Categories/Category';
import styles from './EditDownloadClientModalContent.css';
class EditDownloadClientModalContent extends Component {
//
// Lifecycle
constructor(props, context) {
super(props, context);
this.state = {
isAddCategoryModalOpen: false
};
}
onAddCategoryPress = () => {
this.setState({ isAddCategoryModalOpen: true });
};
onAddCategoryModalClose = () => {
this.setState({ isAddCategoryModalOpen: false });
};
//
// Render
@@ -27,6 +51,7 @@ class EditDownloadClientModalContent extends Component {
advancedSettings,
isFetching,
error,
categories,
isSaving,
isTesting,
saveError,
@@ -37,15 +62,21 @@ class EditDownloadClientModalContent extends Component {
onSavePress,
onTestPress,
onDeleteDownloadClientPress,
onConfirmDeleteCategory,
...otherProps
} = this.props;
const {
isAddCategoryModalOpen
} = this.state;
const {
id,
implementationName,
name,
enable,
priority,
supportsCategories,
fields,
message
} = item;
@@ -136,6 +167,43 @@ class EditDownloadClientModalContent extends Component {
/>
</FormGroup>
{
supportsCategories.value ?
<FieldSet legend={translate('MappedCategories')}>
<div className={styles.customFormats}>
{
categories.map((tag) => {
return (
<Category
key={tag.id}
{...tag}
onConfirmDeleteSpecification={onConfirmDeleteCategory}
/>
);
})
}
<Card
className={styles.addCategory}
onPress={this.onAddCategoryPress}
>
<div className={styles.center}>
<Icon
name={icons.ADD}
size={25}
/>
</div>
</Card>
</div>
</FieldSet> :
null
}
<AddCategoryModalConnector
isOpen={isAddCategoryModalOpen}
onModalClose={this.onAddCategoryModalClose}
/>
</Form>
}
</ModalBody>
@@ -185,13 +253,15 @@ EditDownloadClientModalContent.propTypes = {
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
isTesting: PropTypes.bool.isRequired,
categories: PropTypes.arrayOf(PropTypes.object),
item: PropTypes.object.isRequired,
onInputChange: PropTypes.func.isRequired,
onFieldChange: PropTypes.func.isRequired,
onModalClose: PropTypes.func.isRequired,
onSavePress: PropTypes.func.isRequired,
onTestPress: PropTypes.func.isRequired,
onDeleteDownloadClientPress: PropTypes.func
onDeleteDownloadClientPress: PropTypes.func,
onConfirmDeleteCategory: PropTypes.func.isRequired
};
export default EditDownloadClientModalContent;
@@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { createSelector } from 'reselect';
import { saveDownloadClient, setDownloadClientFieldValue, setDownloadClientValue, testDownloadClient } from 'Store/Actions/settingsActions';
import { deleteDownloadClientCategory, fetchDownloadClientCategories, saveDownloadClient, setDownloadClientFieldValue, setDownloadClientValue, testDownloadClient } from 'Store/Actions/settingsActions';
import createProviderSettingsSelector from 'Store/Selectors/createProviderSettingsSelector';
import EditDownloadClientModalContent from './EditDownloadClientModalContent';
@@ -10,10 +10,12 @@ function createMapStateToProps() {
return createSelector(
(state) => state.settings.advancedSettings,
createProviderSettingsSelector('downloadClients'),
(advancedSettings, downloadClient) => {
(state) => state.settings.downloadClientCategories,
(advancedSettings, downloadClient, categories) => {
return {
advancedSettings,
...downloadClient
...downloadClient,
categories: categories.items
};
}
);
@@ -23,7 +25,9 @@ const mapDispatchToProps = {
setDownloadClientValue,
setDownloadClientFieldValue,
saveDownloadClient,
testDownloadClient
testDownloadClient,
fetchDownloadClientCategories,
deleteDownloadClientCategory
};
class EditDownloadClientModalContentConnector extends Component {
@@ -31,6 +35,14 @@ class EditDownloadClientModalContentConnector extends Component {
//
// Lifecycle
componentDidMount() {
const {
id,
tagsFromId
} = this.props;
this.props.fetchDownloadClientCategories({ id: tagsFromId || id });
}
componentDidUpdate(prevProps, prevState) {
if (prevProps.isSaving && !this.props.isSaving && !this.props.saveError) {
this.props.onModalClose();
@@ -56,6 +68,10 @@ class EditDownloadClientModalContentConnector extends Component {
this.props.testDownloadClient({ id: this.props.id });
};
onConfirmDeleteCategory = (id) => {
this.props.deleteDownloadClientCategory({ id });
};
//
// Render
@@ -67,6 +83,7 @@ class EditDownloadClientModalContentConnector extends Component {
onTestPress={this.onTestPress}
onInputChange={this.onInputChange}
onFieldChange={this.onFieldChange}
onConfirmDeleteCategory={this.onConfirmDeleteCategory}
/>
);
}
@@ -74,10 +91,13 @@ class EditDownloadClientModalContentConnector extends Component {
EditDownloadClientModalContentConnector.propTypes = {
id: PropTypes.number,
tagsFromId: PropTypes.number,
isFetching: PropTypes.bool.isRequired,
isSaving: PropTypes.bool.isRequired,
saveError: PropTypes.object,
item: PropTypes.object.isRequired,
fetchDownloadClientCategories: PropTypes.func.isRequired,
deleteDownloadClientCategory: PropTypes.func.isRequired,
setDownloadClientValue: PropTypes.func.isRequired,
setDownloadClientFieldValue: PropTypes.func.isRequired,
saveDownloadClient: PropTypes.func.isRequired,
@@ -11,12 +11,20 @@ import ConfirmModal from 'Components/Modal/ConfirmModal';
import { icons, inputTypes, kinds } from 'Helpers/Props';
import translate from 'Utilities/String/translate';
const authenticationMethodOptions = [
{ key: 'none', value: 'None' },
export const authenticationRequiredWarning = translate('AuthenticationRequiredWarning');
export const authenticationMethodOptions = [
{ key: 'none', value: 'None', isDisabled: true },
{ key: 'external', value: 'External', isHidden: true },
{ key: 'basic', value: 'Basic (Browser Popup)' },
{ key: 'forms', value: 'Forms (Login Page)' }
];
export const authenticationRequiredOptions = [
{ key: 'enabled', value: 'Enabled' },
{ key: 'disabledForLocalAddresses', value: 'Disabled for Local Addresses' }
];
const certificateValidationOptions = [
{ key: 'enabled', value: 'Enabled' },
{ key: 'disabledForLocalAddresses', value: 'Disabled for Local Addresses' },
@@ -68,6 +76,7 @@ class SecuritySettings extends Component {
const {
authenticationMethod,
authenticationRequired,
username,
password,
apiKey,
@@ -86,13 +95,31 @@ class SecuritySettings extends Component {
name="authenticationMethod"
values={authenticationMethodOptions}
helpText={translate('AuthenticationMethodHelpText')}
helpTextWarning={authenticationRequiredWarning}
onChange={onInputChange}
{...authenticationMethod}
/>
</FormGroup>
{
authenticationEnabled &&
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('AuthenticationRequired')}</FormLabel>
<FormInputGroup
type={inputTypes.SELECT}
name="authenticationRequired"
values={authenticationRequiredOptions}
helpText={translate('AuthenticationRequiredHelpText')}
onChange={onInputChange}
{...authenticationRequired}
/>
</FormGroup> :
null
}
{
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('Username')}</FormLabel>
@@ -102,11 +129,12 @@ class SecuritySettings extends Component {
onChange={onInputChange}
{...username}
/>
</FormGroup>
</FormGroup> :
null
}
{
authenticationEnabled &&
authenticationEnabled ?
<FormGroup>
<FormLabel>{translate('Password')}</FormLabel>
@@ -116,7 +144,8 @@ class SecuritySettings extends Component {
onChange={onInputChange}
{...password}
/>
</FormGroup>
</FormGroup> :
null
}
<FormGroup>
@@ -106,7 +106,7 @@ class IndexerProxy extends Component {
kind={kinds.DISABLED}
outline={true}
>
Disabled
{translate('Disabled')}
</Label> :
null
}
@@ -56,17 +56,9 @@ class Notification extends Component {
id,
name,
onGrab,
onDownload,
onUpgrade,
onRename,
onDelete,
onHealthIssue,
onApplicationUpdate,
supportsOnGrab,
supportsOnDownload,
supportsOnUpgrade,
supportsOnRename,
supportsOnDelete,
supportsOnHealthIssue,
supportsOnApplicationUpdate
} = this.props;
@@ -88,34 +80,6 @@ class Notification extends Component {
</Label>
}
{
supportsOnDelete && onDelete &&
<Label kind={kinds.SUCCESS}>
{translate('OnDelete')}
</Label>
}
{
supportsOnDownload && onDownload &&
<Label kind={kinds.SUCCESS}>
{translate('OnImport')}
</Label>
}
{
supportsOnUpgrade && onDownload && onUpgrade &&
<Label kind={kinds.SUCCESS}>
{translate('OnUpgrade')}
</Label>
}
{
supportsOnRename && onRename &&
<Label kind={kinds.SUCCESS}>
{translate('OnRename')}
</Label>
}
{
supportsOnHealthIssue && onHealthIssue &&
<Label kind={kinds.SUCCESS}>
@@ -132,7 +96,7 @@ class Notification extends Component {
}
{
!onGrab && !onDownload && !onRename && !onHealthIssue && !onDelete && !onApplicationUpdate ?
!onGrab && !onHealthIssue && !onApplicationUpdate ?
<Label
kind={kinds.DISABLED}
outline={true}
@@ -167,17 +131,9 @@ Notification.propTypes = {
id: PropTypes.number.isRequired,
name: PropTypes.string.isRequired,
onGrab: PropTypes.bool.isRequired,
onDownload: PropTypes.bool.isRequired,
onUpgrade: PropTypes.bool.isRequired,
onRename: PropTypes.bool.isRequired,
onDelete: PropTypes.bool.isRequired,
onHealthIssue: PropTypes.bool.isRequired,
onApplicationUpdate: PropTypes.bool.isRequired,
supportsOnGrab: PropTypes.bool.isRequired,
supportsOnDownload: PropTypes.bool.isRequired,
supportsOnDelete: PropTypes.bool.isRequired,
supportsOnUpgrade: PropTypes.bool.isRequired,
supportsOnRename: PropTypes.bool.isRequired,
supportsOnHealthIssue: PropTypes.bool.isRequired,
supportsOnApplicationUpdate: PropTypes.bool.isRequired,
onConfirmDeleteNotification: PropTypes.func.isRequired
@@ -15,8 +15,11 @@ function NotificationEventItems(props) {
} = props;
const {
onGrab,
onHealthIssue,
onApplicationUpdate,
supportsOnGrab,
includeManualGrabs,
supportsOnHealthIssue,
includeHealthWarnings,
supportsOnApplicationUpdate
@@ -31,6 +34,31 @@ function NotificationEventItems(props) {
link="https://wiki.servarr.com/prowlarr/settings#connections"
/>
<div className={styles.events}>
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="onGrab"
helpText={translate('OnGrabHelpText')}
isDisabled={!supportsOnGrab.value}
{...onGrab}
onChange={onInputChange}
/>
</div>
{
onGrab.value &&
<div>
<FormInputGroup
type={inputTypes.CHECK}
name="includeManualGrabs"
helpText={translate('IncludeManualGrabsHelpText')}
isDisabled={!supportsOnGrab.value}
{...includeManualGrabs}
onChange={onInputChange}
/>
</div>
}
<div>
<FormInputGroup
type={inputTypes.CHECK}
+1 -1
View File
@@ -20,7 +20,7 @@ function PendingChangesModal(props) {
useEffect(() => {
bindShortcut('enter', onConfirm);
}, [onConfirm]);
}, [bindShortcut, onConfirm]);
return (
<Modal
@@ -14,8 +14,6 @@ function createLanguagesSelector() {
return createSelector(
(state) => state.localization,
(localization) => {
console.log(localization);
const items = localization.items;
if (!items) {
@@ -0,0 +1,169 @@
import { createAction } from 'redux-actions';
import { batchActions } from 'redux-batched-actions';
import createClearReducer from 'Store/Actions/Creators/Reducers/createClearReducer';
import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/createSetProviderFieldValueReducer';
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
import { createThunk } from 'Store/thunks';
import getNextId from 'Utilities/State/getNextId';
import getProviderState from 'Utilities/State/getProviderState';
import getSectionState from 'Utilities/State/getSectionState';
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
import { removeItem, set, update, updateItem } from '../baseActions';
//
// Variables
const section = 'settings.downloadClientCategories';
//
// Actions Types
export const FETCH_DOWNLOAD_CLIENT_CATEGORIES = 'settings/downloadClientCategories/fetchDownloadClientCategories';
export const FETCH_DOWNLOAD_CLIENT_CATEGORY_SCHEMA = 'settings/downloadClientCategories/fetchDownloadClientCategorySchema';
export const SELECT_DOWNLOAD_CLIENT_CATEGORY_SCHEMA = 'settings/downloadClientCategories/selectDownloadClientCategorySchema';
export const SET_DOWNLOAD_CLIENT_CATEGORY_VALUE = 'settings/downloadClientCategories/setDownloadClientCategoryValue';
export const SET_DOWNLOAD_CLIENT_CATEGORY_FIELD_VALUE = 'settings/downloadClientCategories/setDownloadClientCategoryFieldValue';
export const SAVE_DOWNLOAD_CLIENT_CATEGORY = 'settings/downloadClientCategories/saveDownloadClientCategory';
export const DELETE_DOWNLOAD_CLIENT_CATEGORY = 'settings/downloadClientCategories/deleteDownloadClientCategory';
export const DELETE_ALL_DOWNLOAD_CLIENT_CATEGORY = 'settings/downloadClientCategories/deleteAllDownloadClientCategory';
export const CLEAR_DOWNLOAD_CLIENT_CATEGORIES = 'settings/downloadClientCategories/clearDownloadClientCategories';
export const CLEAR_DOWNLOAD_CLIENT_CATEGORY_PENDING = 'settings/downloadClientCategories/clearDownloadClientCategoryPending';
//
// Action Creators
export const fetchDownloadClientCategories = createThunk(FETCH_DOWNLOAD_CLIENT_CATEGORIES);
export const fetchDownloadClientCategorySchema = createThunk(FETCH_DOWNLOAD_CLIENT_CATEGORY_SCHEMA);
export const selectDownloadClientCategorySchema = createAction(SELECT_DOWNLOAD_CLIENT_CATEGORY_SCHEMA);
export const saveDownloadClientCategory = createThunk(SAVE_DOWNLOAD_CLIENT_CATEGORY);
export const deleteDownloadClientCategory = createThunk(DELETE_DOWNLOAD_CLIENT_CATEGORY);
export const deleteAllDownloadClientCategory = createThunk(DELETE_ALL_DOWNLOAD_CLIENT_CATEGORY);
export const setDownloadClientCategoryValue = createAction(SET_DOWNLOAD_CLIENT_CATEGORY_VALUE, (payload) => {
return {
section,
...payload
};
});
export const setDownloadClientCategoryFieldValue = createAction(SET_DOWNLOAD_CLIENT_CATEGORY_FIELD_VALUE, (payload) => {
return {
section,
...payload
};
});
export const clearDownloadClientCategory = createAction(CLEAR_DOWNLOAD_CLIENT_CATEGORIES);
export const clearDownloadClientCategoryPending = createThunk(CLEAR_DOWNLOAD_CLIENT_CATEGORY_PENDING);
//
// Details
export default {
//
// State
defaultState: {
isPopulated: false,
error: null,
isSchemaFetching: false,
isSchemaPopulated: false,
schemaError: null,
schema: [],
selectedSchema: {},
isSaving: false,
saveError: null,
items: [],
pendingChanges: {}
},
//
// Action Handlers
actionHandlers: {
[FETCH_DOWNLOAD_CLIENT_CATEGORIES]: (getState, payload, dispatch) => {
let tags = [];
if (payload.id) {
const cfState = getSectionState(getState(), 'settings.downloadClients', true);
const cf = cfState.items[cfState.itemMap[payload.id]];
tags = cf.categories.map((tag, i) => {
return {
id: i + 1,
...tag
};
});
}
dispatch(batchActions([
update({ section, data: tags }),
set({
section,
isPopulated: true
})
]));
},
[SAVE_DOWNLOAD_CLIENT_CATEGORY]: (getState, payload, dispatch) => {
const {
id,
...otherPayload
} = payload;
const saveData = getProviderState({ id, ...otherPayload }, getState, section, false);
// we have to set id since not actually posting to server yet
if (!saveData.id) {
saveData.id = getNextId(getState().settings.downloadClientCategories.items);
}
dispatch(batchActions([
updateItem({ section, ...saveData }),
set({
section,
pendingChanges: {}
})
]));
},
[DELETE_DOWNLOAD_CLIENT_CATEGORY]: (getState, payload, dispatch) => {
const id = payload.id;
return dispatch(removeItem({ section, id }));
},
[DELETE_ALL_DOWNLOAD_CLIENT_CATEGORY]: (getState, payload, dispatch) => {
return dispatch(set({
section,
items: []
}));
},
[CLEAR_DOWNLOAD_CLIENT_CATEGORY_PENDING]: (getState, payload, dispatch) => {
return dispatch(set({
section,
pendingChanges: {}
}));
}
},
//
// Reducers
reducers: {
[SET_DOWNLOAD_CLIENT_CATEGORY_VALUE]: createSetSettingValueReducer(section),
[SET_DOWNLOAD_CLIENT_CATEGORY_FIELD_VALUE]: createSetProviderFieldValueReducer(section),
[SELECT_DOWNLOAD_CLIENT_CATEGORY_SCHEMA]: (state, { payload }) => {
return selectProviderSchema(state, section, payload, (selectedSchema) => {
return selectedSchema;
});
},
[CLEAR_DOWNLOAD_CLIENT_CATEGORIES]: createClearReducer(section, {
isPopulated: false,
error: null,
items: []
})
}
};
@@ -9,6 +9,7 @@ import createSetProviderFieldValueReducer from 'Store/Actions/Creators/Reducers/
import createSetSettingValueReducer from 'Store/Actions/Creators/Reducers/createSetSettingValueReducer';
import { createThunk } from 'Store/thunks';
import selectProviderSchema from 'Utilities/State/selectProviderSchema';
import { set } from '../baseActions';
//
// Variables
@@ -90,10 +91,34 @@ export default {
[FETCH_DOWNLOAD_CLIENTS]: createFetchHandler(section, '/downloadclient'),
[FETCH_DOWNLOAD_CLIENT_SCHEMA]: createFetchSchemaHandler(section, '/downloadclient/schema'),
[SAVE_DOWNLOAD_CLIENT]: createSaveProviderHandler(section, '/downloadclient'),
[SAVE_DOWNLOAD_CLIENT]: (getState, payload, dispatch) => {
// move the format tags in as a pending change
const state = getState();
const pendingChanges = state.settings.downloadClients.pendingChanges;
pendingChanges.categories = state.settings.downloadClientCategories.items;
dispatch(set({
section,
pendingChanges
}));
createSaveProviderHandler(section, '/downloadclient')(getState, payload, dispatch);
},
[CANCEL_SAVE_DOWNLOAD_CLIENT]: createCancelSaveProviderHandler(section),
[DELETE_DOWNLOAD_CLIENT]: createRemoveItemHandler(section, '/downloadclient'),
[TEST_DOWNLOAD_CLIENT]: createTestProviderHandler(section, '/downloadclient'),
[TEST_DOWNLOAD_CLIENT]: (getState, payload, dispatch) => {
const state = getState();
const pendingChanges = state.settings.downloadClients.pendingChanges;
pendingChanges.categories = state.settings.downloadClientCategories.items;
dispatch(set({
section,
pendingChanges
}));
createTestProviderHandler(section, '/downloadclient')(getState, payload, dispatch);
},
[CANCEL_TEST_DOWNLOAD_CLIENT]: createCancelTestProviderHandler(section),
[TEST_ALL_DOWNLOAD_CLIENTS]: createTestAllProvidersHandler(section, '/downloadclient')
},
@@ -103,9 +103,6 @@ export default {
[SELECT_NOTIFICATION_SCHEMA]: (state, { payload }) => {
return selectProviderSchema(state, section, payload, (selectedSchema) => {
selectedSchema.onGrab = selectedSchema.supportsOnGrab;
selectedSchema.onDownload = selectedSchema.supportsOnDownload;
selectedSchema.onUpgrade = selectedSchema.supportsOnUpgrade;
selectedSchema.onRename = selectedSchema.supportsOnRename;
selectedSchema.onApplicationUpdate = selectedSchema.supportsOnApplicationUpdate;
return selectedSchema;
+2 -2
View File
@@ -54,7 +54,7 @@ export const defaultState = {
},
{
name: 'grabTitle',
label: translate('Grab Title'),
label: translate('GrabTitle'),
isSortable: false,
isVisible: false
},
@@ -78,7 +78,7 @@ export const defaultState = {
},
{
name: 'elapsedTime',
label: translate('Elapsed Time'),
label: translate('ElapsedTime'),
isSortable: false,
isVisible: true
},
+29 -2
View File
@@ -1,3 +1,4 @@
import $ from 'jquery';
import { createAction } from 'redux-actions';
import { batchActions } from 'redux-batched-actions';
import { filterBuilderTypes, filterBuilderValueTypes, sortDirections } from 'Helpers/Props';
@@ -229,6 +230,7 @@ export const CANCEL_FETCH_RELEASES = 'releases/cancelFetchReleases';
export const SET_RELEASES_SORT = 'releases/setReleasesSort';
export const CLEAR_RELEASES = 'releases/clearReleases';
export const GRAB_RELEASE = 'releases/grabRelease';
export const SAVE_RELEASE = 'releases/saveRelease';
export const BULK_GRAB_RELEASES = 'release/bulkGrabReleases';
export const UPDATE_RELEASE = 'releases/updateRelease';
export const SET_RELEASES_FILTER = 'releases/setReleasesFilter';
@@ -243,6 +245,7 @@ export const cancelFetchReleases = createThunk(CANCEL_FETCH_RELEASES);
export const setReleasesSort = createAction(SET_RELEASES_SORT);
export const clearReleases = createAction(CLEAR_RELEASES);
export const grabRelease = createThunk(GRAB_RELEASE);
export const saveRelease = createThunk(SAVE_RELEASE);
export const bulkGrabReleases = createThunk(BULK_GRAB_RELEASES);
export const updateRelease = createAction(UPDATE_RELEASE);
export const setReleasesFilter = createAction(SET_RELEASES_FILTER);
@@ -304,14 +307,38 @@ export const actionHandlers = handleThunks({
});
},
[SAVE_RELEASE]: function(getState, payload, dispatch) {
const link = payload.downloadUrl;
const file = payload.fileName;
$.ajax({
url: link,
method: 'GET',
headers: {
'X-Prowlarr-Client': true
},
xhrFields: {
responseType: 'blob'
},
success: function(data) {
const a = document.createElement('a');
const url = window.URL.createObjectURL(data);
a.href = url;
a.download = file;
document.body.append(a);
a.click();
a.remove();
window.URL.revokeObjectURL(url);
}
});
},
[BULK_GRAB_RELEASES]: function(getState, payload, dispatch) {
dispatch(set({
section,
isGrabbing: true
}));
console.log(payload);
const promise = createAjaxRequest({
url: '/search/bulk',
method: 'POST',
@@ -4,6 +4,7 @@ import createHandleActions from './Creators/createHandleActions';
import applications from './Settings/applications';
import appProfiles from './Settings/appProfiles';
import development from './Settings/development';
import downloadClientCategories from './Settings/downloadClientCategories';
import downloadClients from './Settings/downloadClients';
import general from './Settings/general';
import indexerCategories from './Settings/indexerCategories';
@@ -11,6 +12,7 @@ import indexerProxies from './Settings/indexerProxies';
import notifications from './Settings/notifications';
import ui from './Settings/ui';
export * from './Settings/downloadClientCategories';
export * from './Settings/downloadClients';
export * from './Settings/general';
export * from './Settings/indexerCategories';
@@ -32,6 +34,7 @@ export const section = 'settings';
export const defaultState = {
advancedSettings: false,
downloadClientCategories: downloadClientCategories.defaultState,
downloadClients: downloadClients.defaultState,
general: general.defaultState,
indexerCategories: indexerCategories.defaultState,
@@ -61,6 +64,7 @@ export const toggleAdvancedSettings = createAction(TOGGLE_ADVANCED_SETTINGS);
// Action Handlers
export const actionHandlers = handleThunks({
...downloadClientCategories.actionHandlers,
...downloadClients.actionHandlers,
...general.actionHandlers,
...indexerCategories.actionHandlers,
@@ -81,6 +85,7 @@ export const reducers = createHandleActions({
return Object.assign({}, state, { advancedSettings: !state.advancedSettings });
},
...downloadClientCategories.reducers,
...downloadClients.reducers,
...general.reducers,
...indexerCategories.reducers,
+4
View File
@@ -1,7 +1,11 @@
import * as dark from './dark';
import * as light from './light';
const defaultDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
const auto = defaultDark ? { ...dark } : { ...light };
export default {
auto,
light,
dark
};
+1 -1
View File
@@ -25,7 +25,7 @@ const columns = [
},
{
name: 'size',
label: 'Size',
label: translate('Size'),
isVisible: true
},
{
+1 -1
View File
@@ -113,7 +113,7 @@ class Updates extends Component {
/>
<div className={styles.message}>
The latest version of Prowlarr is already installed
{translate('TheLatestVersionIsAlreadyInstalled', ['Prowlarr'])}
</div>
{
+1 -1
View File
@@ -1,4 +1,4 @@
import filesize from 'filesize';
import { filesize } from 'filesize';
function formatBytes(input) {
const size = Number(input);
@@ -16,6 +16,11 @@ function addApiKey(ajaxOptions) {
ajaxOptions.headers['X-Api-Key'] = window.Prowlarr.apiKey;
}
function addUIHeader(ajaxOptions) {
ajaxOptions.headers = ajaxOptions.headers || {};
ajaxOptions.headers['X-Prowlarr-Client'] = true;
}
function addContentType(ajaxOptions) {
if (
ajaxOptions.contentType == null &&
@@ -42,6 +47,7 @@ export default function createAjaxRequest(originalAjaxOptions) {
if (isRelative(ajaxOptions)) {
addRootUrl(ajaxOptions);
addApiKey(ajaxOptions);
addUIHeader(ajaxOptions);
addContentType(ajaxOptions);
}
+2 -2
View File
@@ -11,7 +11,7 @@
<!-- Windows Phone -->
<meta name="msapplication-navbutton-color" content="#3a3f51" />
<meta name="description" content="Prowlarr (Preview)" />
<meta name="description" content="Prowlarr" />
<link
rel="apple-touch-icon"
@@ -50,7 +50,7 @@
<link rel="stylesheet" type="text/css" href="/Content/Fonts/fonts.css">
<!-- webpack bundles head -->
<title>Prowlarr (Preview)</title>
<title>Prowlarr</title>
<!--
The super basic styling for .root will live here,
+58 -54
View File
@@ -11,7 +11,8 @@
"lint": "esprint check",
"lint-fix": "esprint check --fix",
"stylelint-linux": "stylelint $(find frontend -name '*.css') --config frontend/.stylelintrc",
"stylelint-windows": "stylelint frontend/**/*.css --config frontend/.stylelintrc"
"stylelint-windows": "stylelint frontend/**/*.css --config frontend/.stylelintrc",
"check-modules": "are-you-es5 check . -r"
},
"repository": "https://github.com/Prowlarr/Prowlarr",
"author": "Team Prowlarr",
@@ -25,107 +26,110 @@
"not chrome < 60"
],
"dependencies": {
"@fortawesome/fontawesome-free": "6.1.1",
"@fortawesome/fontawesome-svg-core": "6.1.1",
"@fortawesome/free-regular-svg-icons": "6.1.1",
"@fortawesome/free-solid-svg-icons": "6.1.1",
"@fortawesome/react-fontawesome": "0.1.18",
"@microsoft/signalr": "6.0.6",
"@sentry/browser": "6.19.2",
"@sentry/integrations": "6.19.2",
"chart.js": "3.7.1",
"classnames": "2.3.1",
"clipboard": "2.0.10",
"connected-react-router": "6.9.1",
"@fortawesome/fontawesome-free": "6.2.1",
"@fortawesome/fontawesome-svg-core": "6.2.1",
"@fortawesome/free-regular-svg-icons": "6.2.1",
"@fortawesome/free-solid-svg-icons": "6.2.1",
"@fortawesome/react-fontawesome": "0.2.0",
"@microsoft/signalr": "6.0.13",
"@sentry/browser": "7.28.0",
"@sentry/integrations": "7.28.0",
"chart.js": "4.1.1",
"classnames": "2.3.2",
"clipboard": "2.0.11",
"connected-react-router": "6.9.3",
"element-class": "0.2.2",
"filesize": "6.3.0",
"filesize": "10.0.6",
"history": "4.10.1",
"https-browserify": "1.0.0",
"jdu": "1.0.0",
"jquery": "3.6.0",
"jquery": "3.6.2",
"lodash": "4.17.21",
"mobile-detect": "1.4.5",
"moment": "2.29.2",
"moment": "2.29.4",
"mousetrap": "1.6.5",
"normalize.css": "8.0.1",
"prop-types": "15.8.1",
"qs": "6.10.3",
"qs": "6.11.0",
"react": "17.0.2",
"react-addons-shallow-compare": "15.6.3",
"react-async-script": "1.2.0",
"react-autosuggest": "10.1.0",
"react-custom-scrollbars-2": "4.4.0",
"react-custom-scrollbars-2": "4.5.0",
"react-dnd": "14.0.4",
"react-dnd-html5-backend": "14.0.2",
"react-dnd-multi-backend": "6.0.2",
"react-dnd-touch-backend": "14.1.1",
"react-document-title": "2.0.3",
"react-dom": "17.0.2",
"react-focus-lock": "2.5.0",
"react-focus-lock": "2.9.2",
"react-google-recaptcha": "2.1.0",
"react-lazyload": "3.2.0",
"react-measure": "1.4.7",
"react-popper": "1.3.7",
"react-redux": "7.2.4",
"react-redux": "8.0.5",
"react-router": "5.2.0",
"react-router-dom": "5.2.0",
"react-text-truncate": "0.19.0",
"react-virtualized": "9.21.1",
"redux": "4.1.0",
"redux": "4.2.0",
"redux-actions": "2.6.5",
"redux-batched-actions": "0.5.0",
"redux-localstorage": "0.4.1",
"redux-thunk": "2.3.0",
"reselect": "4.0.0"
"redux-thunk": "2.4.2",
"reselect": "4.1.7"
},
"devDependencies": {
"@babel/core": "7.18.2",
"@babel/eslint-parser": "7.18.2",
"@babel/plugin-proposal-class-properties": "7.17.12",
"@babel/plugin-proposal-decorators": "7.18.2",
"@babel/plugin-proposal-export-default-from": "7.17.12",
"@babel/plugin-proposal-export-namespace-from": "7.17.12",
"@babel/plugin-proposal-function-sent": "7.18.2",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.17.12",
"@babel/plugin-proposal-numeric-separator": "7.16.7",
"@babel/plugin-proposal-optional-chaining": "7.17.12",
"@babel/plugin-proposal-throw-expressions": "7.16.7",
"@babel/core": "7.20.5",
"@babel/eslint-parser": "7.19.1",
"@babel/plugin-proposal-class-properties": "7.18.6",
"@babel/plugin-proposal-decorators": "7.20.5",
"@babel/plugin-proposal-export-default-from": "7.18.10",
"@babel/plugin-proposal-export-namespace-from": "7.18.9",
"@babel/plugin-proposal-function-sent": "7.18.6",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.18.6",
"@babel/plugin-proposal-numeric-separator": "7.18.6",
"@babel/plugin-proposal-optional-chaining": "7.18.9",
"@babel/plugin-proposal-throw-expressions": "7.18.6",
"@babel/plugin-syntax-dynamic-import": "7.8.3",
"@babel/preset-env": "7.18.2",
"@babel/preset-react": "7.17.12",
"autoprefixer": "10.4.7",
"babel-loader": "8.2.5",
"@babel/preset-env": "7.20.2",
"@babel/preset-react": "7.18.6",
"are-you-es5": "2.1.2",
"autoprefixer": "10.4.13",
"babel-loader": "9.1.0",
"babel-plugin-inline-classnames": "2.0.1",
"babel-plugin-transform-react-remove-prop-types": "0.4.24",
"core-js": "3.22.8",
"css-loader": "6.7.1",
"eslint": "8.17.0",
"core-js": "3.26.1",
"css-loader": "6.7.3",
"eslint": "8.30.0",
"eslint-plugin-filenames": "1.3.2",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-react": "7.30.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-simple-import-sort": "8.0.0",
"esprint": "3.6.0",
"file-loader": "6.2.0",
"filemanager-webpack-plugin": "6.1.7",
"filemanager-webpack-plugin": "8.0.0",
"html-webpack-plugin": "5.5.0",
"loader-utils": "^3.0.0",
"mini-css-extract-plugin": "2.6.0",
"postcss": "8.4.14",
"loader-utils": "^3.2.1",
"mini-css-extract-plugin": "2.7.2",
"postcss": "8.4.20",
"postcss-color-function": "4.1.0",
"postcss-loader": "6.2.1",
"postcss-mixins": "9.0.2",
"postcss-nested": "5.0.6",
"postcss-simple-vars": "6.0.3",
"postcss-loader": "7.0.2",
"postcss-mixins": "9.0.4",
"postcss-nested": "6.0.0",
"postcss-simple-vars": "7.0.1",
"postcss-url": "10.1.3",
"require-nocache": "1.0.0",
"rimraf": "3.0.2",
"run-sequence": "2.2.1",
"streamqueue": "1.1.2",
"style-loader": "3.3.1",
"stylelint": "14.8.5",
"stylelint": "14.16.0",
"stylelint-order": "5.0.0",
"url-loader": "4.1.1",
"webpack": "5.73.0",
"webpack-cli": "4.9.2",
"webpack": "5.75.0",
"webpack-cli": "5.0.1",
"webpack-livereload-plugin": "3.0.2"
}
}
-105
View File
@@ -1,105 +0,0 @@
#!/bin/bash
# Generate a Markdown change log of pull requests from commits between two tags
scriptDir=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)
ghRepo="Prowlarr"
#branch="develop"
#read -r -p "What Repo?: " ghRepo
#read -r -p "What Org?: [Default:$ghRepo]" ghOrg
read -r -p "What Branch? [master|develop|nightly]:" branch
ghOrg=${ghOrg:-$ghRepo}
ghRepoUrl=https://github.com/$ghOrg/$ghRepo
case "${branch}" in
master)
hotioBranch='release'
lsioBranch='latest'
branchType='Stable'
;;
develop)
hotioBranch='testing'
lsioBranch='develop'
branchType='Beta'
;;
nightly)
hotioBranch='nightly'
lsioBranch='nightly'
branchType='Alpha'
;;
esac
baseDir=$(dirname "$scriptDir")
changelogDir="$baseDir/changelogs/"
templateDir="$changelogDir/templates/"
# Get a list of all tags in reverse order
# Assumes the tags are in version format like v1.2.3
gitTags=$(git ls-remote -t --exit-code --refs --sort='-v:refname' "$ghRepoUrl" | sed -E 's/^[[:xdigit:]]+[[:space:]]+refs\/tags\/(.+)/\1/g')
# Make the tags an array
# shellcheck disable=SC2206
tags=($gitTags)
latestTag=${tags[0]}
previousTag=${tags[1]}
# Get a log of commits that occurred between two tags
# See Pretty format placeholders at https://git-scm.com/docs/pretty-formats
# -i -E --grep="(Fixed:|New:)"'
commits=$(git log --pretty=format:' - %s%n' "$previousTag".."$latestTag")
# Store our changelog in a variable to be saved to a file at the end
markdown="# New ${branchType^} Release"
markdown+='\n\n'
markdown+="$ghRepo $latestTag has been released on \`$branch\`"
markdown+='\n\n'
branchmsg=$(cat "$templateDir"/branch-$branch.md)
if [ -n "$branchmsg" ]; then
{
markdown+=$branchmsg
markdown+='\n\n'
}
fi
markdown+="# Announcements"
markdown+='\n\n'
markdown+=$(cat "$templateDir"/announcements.md)
markdown+='\n\n'
markdown+="# Additional Commentary"
markdown+='\n\n'
markdown+=$(cat "$templateDir"/commentary.md)
markdown+='\n\n'
markdown+="# Releases"
markdown+='\n\n'
markdown+="## Native"
markdown+="\n\n"
markdown+="- [GitHub Releases]($ghRepoUrl/releases)"
markdown+="\n\n"
markdown+="- [Wiki Installation Instructions](https://wiki.servarr.com/${ghRepo,,}/installation)"
markdown+="\n\n"
markdown+="## Docker"
markdown+="\n\n"
markdown+="- [hotio/$ghRepo:$hotioBranch](https://hotio.dev/containers/${ghRepo,,})"
markdown+="\n\n"
markdown+="- [lscr.io/linuxserver/$ghRepo:$lsioBranch](https://docs.linuxserver.io/images/docker-${ghRepo,,})"
markdown+="\n\n"
markdown+="## NAS Packages"
markdown+="\n\n"
markdown+="- Synology - Please ask the SynoCommunity to update the base package; however, you can update in-app normally"
markdown+="\n\n"
markdown+="- QNAP - Please ask the QNAP to update the base package; however, you should be able to update in-app normally"
markdown+="\n\n"
markdown+="------------"
markdown+="\n\n"
markdown+="# Release Notes"
markdown+="\n\n"
markdown+="## $latestTag (changes since $previousTag)"
markdown+="\n\n"
markdown+="$commits"
markdown+="\n\n"
markdown+=" - Other bug fixes and improvements, see GitHub history"
# Loop over each commit and look for merged pull requests
#for COMMIT in $COMMITS; do
#done
# Save our markdown to a file
mkdir -p "$changelogDir"
echo -e "$markdown" >"$changelogDir/CHANGELOG-$latestTag.md"
exit 0
+3
View File
@@ -0,0 +1,3 @@
is_global = true
dotnet_diagnostic.CA1014.severity = none
+2 -1
View File
@@ -1,6 +1,7 @@
<Project>
<!-- Common to all Prowlarr Projects -->
<PropertyGroup>
<AnalysisLevel>6.0-all</AnalysisLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -94,7 +95,7 @@
<!-- Standard testing packages -->
<ItemGroup Condition="'$(TestProject)'=='true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />
@@ -46,7 +46,7 @@ namespace NzbDrone.Automation.Test
_runner = new NzbDroneRunner(LogManager.GetCurrentClassLogger(), null);
_runner.KillAll();
_runner.Start();
_runner.Start(true);
driver.Url = "http://localhost:9696";
@@ -0,0 +1,25 @@
using System.Globalization;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Common.Test.ExtensionTests.StringExtensionTests
{
[TestFixture]
public class IsValidIPAddressFixture
{
[TestCase("192.168.0.1")]
[TestCase("::1")]
[TestCase("2001:db8:4006:812::200e")]
public void should_validate_ip_address(string input)
{
input.IsValidIpAddress().Should().BeTrue();
}
[TestCase("sonarr.tv")]
public void should_not_parse_non_ip_address(string input)
{
input.IsValidIpAddress().Should().BeFalse();
}
}
}
@@ -212,6 +212,7 @@ namespace NzbDrone.Common.Test.Http
}
[Test]
[Platform(Exclude = "MacOsX", Reason = "Azure agent update prevents brotli on OSX")]
public void should_execute_get_using_brotli()
{
var request = new HttpRequest($"https://{_httpBinHost}/brotli");
@@ -1,4 +1,4 @@
using FluentAssertions;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Test.Common;
@@ -10,6 +10,7 @@ namespace NzbDrone.Common.Test.Http
[TestCase("abc://my_host.com:8080/root/api/")]
[TestCase("abc://my_host.com:8080//root/api/")]
[TestCase("abc://my_host.com:8080/root//api/")]
[TestCase("abc://[::1]:8080/root//api/")]
public void should_parse(string uri)
{
var newUri = new HttpUri(uri);
@@ -52,6 +53,26 @@ namespace NzbDrone.Common.Test.Http
newUri.FullUri.Should().Be(expected);
}
[TestCase("", "./relative", "relative")]
[TestCase("/", "./relative", "/relative")]
[TestCase("/base", "./relative", "/relative")]
[TestCase("/base/sub", "./relative", "/base/relative")]
[TestCase("/base/sub/", "./relative", "/base/sub/relative")]
[TestCase("base/sub", "./relative", "base/relative")]
[TestCase("base/sub/", "./relative", "base/sub/relative")]
[TestCase("", "../relative", "relative")]
[TestCase("/", "../relative", "/relative")]
[TestCase("/base", "../relative", "/relative")]
[TestCase("/base/sub", "../relative", "/base/relative")]
[TestCase("/base/sub/", "../relative", "/base/sub/relative")]
[TestCase("base/sub", "../relative", "base/relative")]
[TestCase("base/sub/", "../relative", "base/sub/relative")]
public void should_combine_uri_with_dot_segment(string basePath, string relativePath, string expected)
{
var newUri = new HttpUri(basePath) + new HttpUri(relativePath);
newUri.FullUri.Should().Be(expected);
}
[TestCase("", "", "")]
[TestCase("/", "", "/")]
[TestCase("base", "", "base")]
@@ -24,12 +24,16 @@ namespace NzbDrone.Common.Test.InstrumentationTests
[TestCase(@"https://beyond-hd.me/api/torrents/2b51db35e1912ffc138825a12b9933d2")]
[TestCase(@"Req: [POST] https://www3.yggtorrent.nz/user/login: id=mySecret&pass=mySecret&ci_csrf_token=2b51db35e1912ffc138825a12b9933d2")]
[TestCase(@"https://torrentseeds.org/api/torrents/filter?api_token=2b51db35e1912ffc138825a12b9933d2&name=&sortField=created_at&sortDirection=desc&perPage=100&page=1")]
[TestCase(@"https://beyond-hd.me/torrent/download/the-next-365-days-2022-2160p-nf-web-dl-dual-ddp-51-dovi-hdr-hevc-apex.225146.2b51db35e1912ffc138825a12b9933d2")]
[TestCase(@"https://anthelion.me/api.php?api_key=2b51db35e1910123321025a12b9933d2&o=json&t=movie&q=&tmdb=&imdb=&cat=&limit=100&offset=0")]
[TestCase(@"https://avistaz.to/api/v1/jackett/auth: username=mySecret&password=mySecret&pid=mySecret")]
// Indexer and Download Client Responses
// avistaz response
[TestCase(@"""download"":""https://avistaz.to/rss/download/2b51db35e1910123321025a12b9933d2/tb51db35e1910123321025a12b9933d2.torrent"",")]
[TestCase(@",""info_hash"":""2b51db35e1910123321025a12b9933d2"",")]
[TestCase(@"""token"":""2b51db35e1910123321025a12b9933d2""")]
// animebytes response
[TestCase(@"""Link"":""https://animebytes.tv/torrent/994064/download/tb51db35e1910123321025a12b9933d2"",")]
@@ -98,15 +102,30 @@ namespace NzbDrone.Common.Test.InstrumentationTests
// Internal
[TestCase(@"[Info] MigrationController: *** Migrating Database=prowlarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;Enlist=False ***")]
[TestCase("/readarr/signalr/messages/negotiate?access_token=1234530f422f4aacb6b301233210aaaa&negotiateVersion=1")]
[TestCase(@"[Info] MigrationController: *** Migrating Database=prowlarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;token=mySecret;Enlist=False&username=mySecret;mypassword=mySecret;mypass=shouldkeep1;test_token=mySecret;password=123%@%_@!#^#@;use_password=mySecret;get_token=shouldkeep2;usetoken=shouldkeep3;passwrd=mySecret;")]
public void should_clean_message(string message)
{
var cleansedMessage = CleanseLogMessage.Cleanse(message);
cleansedMessage.Should().NotContain("mySecret");
cleansedMessage.Should().NotContain("123%@%_@!#^#@");
cleansedMessage.Should().NotContain("01233210");
}
[TestCase(@"[Info] MigrationController: *** Migrating Database=radarr-main;Host=postgres14;Username=mySecret;Password=mySecret;Port=5432;token=mySecret;Enlist=False&username=mySecret;mypassword=mySecret;mypass=shouldkeep1;test_token=mySecret;password=123%@%_@!#^#@;use_password=mySecret;get_token=shouldkeep2;usetoken=shouldkeep3;passwrd=mySecret;")]
public void should_keep_message(string message)
{
var cleansedMessage = CleanseLogMessage.Cleanse(message);
cleansedMessage.Should().NotContain("mySecret");
cleansedMessage.Should().NotContain("123%@%_@!#^#@");
cleansedMessage.Should().NotContain("01233210");
cleansedMessage.Should().Contain("shouldkeep1");
cleansedMessage.Should().Contain("shouldkeep2");
cleansedMessage.Should().Contain("shouldkeep3");
}
[TestCase(@"Some message (from 32.2.3.5 user agent)")]
[TestCase(@"Auth-Invalidated ip 32.2.3.5")]
[TestCase(@"Auth-Success ip 32.2.3.5")]
@@ -278,7 +278,7 @@ namespace NzbDrone.Common.Test
[Test]
public void GetUpdateClientExePath()
{
GetIAppDirectoryInfo().GetUpdateClientExePath(PlatformType.DotNet).Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr.Update.exe".AsOsAgnostic());
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\prowlarr_update\Prowlarr.Update".AsOsAgnostic().ProcessNameToExe());
}
[Test]
@@ -9,6 +9,7 @@ namespace NzbDrone.Common.EnvironmentInfo
bool IsAdmin { get; }
bool IsWindowsService { get; }
bool IsWindowsTray { get; }
bool IsStarting { get; set; }
bool IsExiting { get; set; }
bool IsTray { get; }
RuntimeMode Mode { get; }
@@ -2,13 +2,6 @@ using System;
namespace NzbDrone.Common.EnvironmentInfo
{
public enum PlatformType
{
DotNet = 0,
Mono = 1,
NetCore = 2
}
public interface IPlatformInfo
{
Version Version { get; }
@@ -16,36 +9,18 @@ namespace NzbDrone.Common.EnvironmentInfo
public class PlatformInfo : IPlatformInfo
{
private static PlatformType _platform;
private static Version _version;
static PlatformInfo()
{
_platform = PlatformType.NetCore;
_version = Environment.Version;
}
public static PlatformType Platform => _platform;
public static bool IsMono => Platform == PlatformType.Mono;
public static bool IsDotNet => Platform == PlatformType.DotNet;
public static bool IsNetCore => Platform == PlatformType.NetCore;
public static string PlatformName
{
get
{
if (IsDotNet)
{
return ".NET";
}
else if (IsMono)
{
return "Mono";
}
else
{
return ".NET Core";
}
return ".NET";
}
}
@@ -19,6 +19,7 @@ namespace NzbDrone.Common.EnvironmentInfo
_logger = logger;
IsWindowsService = hostLifetime is WindowsServiceLifetime;
IsStarting = true;
// net6.0 will return Radarr.dll for entry assembly, we need the actual
// executable name (Radarr on linux). On mono this will return the location of
@@ -82,6 +83,7 @@ namespace NzbDrone.Common.EnvironmentInfo
public bool IsWindowsService { get; private set; }
public bool IsStarting { get; set; }
public bool IsExiting { get; set; }
public bool IsTray
{
@@ -7,34 +7,50 @@ namespace NzbDrone.Common.Extensions
{
public static bool IsLocalAddress(this IPAddress ipAddress)
{
if (ipAddress.IsIPv6LinkLocal)
// Map back to IPv4 if mapped to IPv6, for example "::ffff:1.2.3.4" to "1.2.3.4".
if (ipAddress.IsIPv4MappedToIPv6)
{
return true;
ipAddress = ipAddress.MapToIPv4();
}
// Checks loopback ranges for both IPv4 and IPv6.
if (IPAddress.IsLoopback(ipAddress))
{
return true;
}
// IPv4
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
{
byte[] bytes = ipAddress.GetAddressBytes();
switch (bytes[0])
{
case 10:
case 127:
return true;
case 172:
return bytes[1] < 32 && bytes[1] >= 16;
case 192:
return bytes[1] == 168;
default:
return false;
}
return IsLocalIPv4(ipAddress.GetAddressBytes());
}
// IPv6
if (ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
return ipAddress.IsIPv6LinkLocal ||
ipAddress.IsIPv6UniqueLocal ||
ipAddress.IsIPv6SiteLocal;
}
return false;
}
private static bool IsLocalIPv4(byte[] ipv4Bytes)
{
// Link local (no IP assigned by DHCP): 169.254.0.0 to 169.254.255.255 (169.254.0.0/16)
bool IsLinkLocal() => ipv4Bytes[0] == 169 && ipv4Bytes[1] == 254;
// Class A private range: 10.0.0.0 10.255.255.255 (10.0.0.0/8)
bool IsClassA() => ipv4Bytes[0] == 10;
// Class B private range: 172.16.0.0 172.31.255.255 (172.16.0.0/12)
bool IsClassB() => ipv4Bytes[0] == 172 && ipv4Bytes[1] >= 16 && ipv4Bytes[1] <= 31;
// Class C private range: 192.168.0.0 192.168.255.255 (192.168.0.0/16)
bool IsClassC() => ipv4Bytes[0] == 192 && ipv4Bytes[1] == 168;
return IsLinkLocal() || IsClassA() || IsClassC() || IsClassB();
}
}
}
@@ -33,7 +33,7 @@ namespace NzbDrone.Common.Extensions
var info = new FileInfo(path.Trim());
//UNC
// UNC
if (OsInfo.IsWindows && info.FullName.StartsWith(@"\\"))
{
return info.FullName.TrimEnd('/', '\\', ' ');
@@ -166,7 +166,7 @@ namespace NzbDrone.Common.Extensions
var parentDirInfo = dirInfo.Parent;
if (parentDirInfo == null)
{
//Drive letter
// Drive letter
return dirInfo.Name.ToUpper();
}
@@ -238,9 +238,9 @@ namespace NzbDrone.Common.Extensions
return null;
}
public static string ProcessNameToExe(this string processName, PlatformType runtime)
public static string ProcessNameToExe(this string processName)
{
if (OsInfo.IsWindows || runtime != PlatformType.NetCore)
if (OsInfo.IsWindows)
{
processName += ".exe";
}
@@ -248,11 +248,6 @@ namespace NzbDrone.Common.Extensions
return processName;
}
public static string ProcessNameToExe(this string processName)
{
return processName.ProcessNameToExe(PlatformInfo.Platform);
}
public static string GetAppDataPath(this IAppFolderInfo appFolderInfo)
{
return appFolderInfo.AppDataFolder;
@@ -318,9 +313,9 @@ namespace NzbDrone.Common.Extensions
return Path.Combine(GetUpdatePackageFolder(appFolderInfo), UPDATE_CLIENT_FOLDER_NAME);
}
public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo, PlatformType runtime)
public static string GetUpdateClientExePath(this IAppFolderInfo appFolderInfo)
{
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe(runtime);
return Path.Combine(GetUpdateSandboxFolder(appFolderInfo), UPDATE_CLIENT_EXE_NAME).ProcessNameToExe();
}
public static string GetDatabase(this IAppFolderInfo appFolderInfo)
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Text.RegularExpressions;
@@ -130,7 +131,7 @@ namespace NzbDrone.Common.Extensions
public static string WrapInQuotes(this string text)
{
if (!text.Contains(" "))
if (!text.Contains(' '))
{
return text;
}
@@ -231,5 +232,43 @@ namespace NzbDrone.Common.Extensions
.Replace("'", "%27")
.Replace("%7E", "~");
}
public static bool IsValidIpAddress(this string value)
{
if (!IPAddress.TryParse(value, out var parsedAddress))
{
return false;
}
if (parsedAddress.Equals(IPAddress.Parse("255.255.255.255")))
{
return false;
}
if (parsedAddress.IsIPv6Multicast)
{
return false;
}
return parsedAddress.AddressFamily == AddressFamily.InterNetwork || parsedAddress.AddressFamily == AddressFamily.InterNetworkV6;
}
public static string ToUrlHost(this string input)
{
return input.Contains(':') ? $"[{input}]" : input;
}
public static bool IsAllDigits(this string input)
{
foreach (var c in input)
{
if (c < '0' || c > '9')
{
return false;
}
}
return true;
}
}
}

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