1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-03-06 13:31:28 -05:00

Compare commits

...

66 Commits

Author SHA1 Message Date
Qstick
bb573594d9 Fix Blocklist Tests 2023-04-13 22:35:22 -05:00
Qstick
12e360ab4f Fixed: Some posters not showing for new movies search results
Fixes #8175

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
2023-04-13 22:09:55 -05:00
Qstick
bae555f63e Fixed: Custom Format calculation error on Blocklist by Movie
Fixes #8136
2023-04-13 21:55:01 -05:00
Qstick
31abb93d8c Bump dotnet to 6.0.16 2023-04-13 19:15:09 -05:00
LarsHelo
75035035e1 Fixed: Remote path mapping UI being partially hidden on smaller screens 2023-04-13 19:08:19 -05:00
bakerboy448
c1e5990a58 Update library clean helptext 2023-04-13 19:07:39 -05:00
Weblate
4a42ebe44c Translated using Weblate (German) [skip ci]
Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Czech) [skip ci]

Currently translated at 90.7% (1052 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Hebrew) [skip ci]

Currently translated at 92.9% (1077 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 95.4% (1106 of 1159 strings)

Translated using Weblate (Arabic) [skip ci]

Currently translated at 90.4% (1048 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 94.6% (1097 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Norwegian Bokmål) [skip ci]

Currently translated at 22.5% (261 of 1159 strings)

Translated using Weblate (Greek) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 94.3% (1094 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 99.5% (1154 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Croatian) [skip ci]

Currently translated at 21.4% (249 of 1159 strings)

Co-authored-by: Bendik Remoy <Bendikremoy@hotmail.com>
Co-authored-by: Cassio Rizzi <clrizzi@gmail.com>
Co-authored-by: Deflector8249 <lh2jwko5@gomail.me>
Co-authored-by: Elias Benbourenane <eliasbenbourenane@gmail.com>
Co-authored-by: Florian <sephrat.flo@gmail.com>
Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: Ivan Mazzoli <dreadtank27@gmail.com>
Co-authored-by: Lizandra Candido da Silva <lizandra.c.s@gmail.com>
Co-authored-by: Michele Caputo <michele@caputoweb.xyz>
Co-authored-by: Nir Israel Hen <nirisraelh@gmail.com>
Co-authored-by: Remy <remy@mrbk.fr>
Co-authored-by: TheHrle <Hpranjkovic@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: federicofortini <federico.fortini@yahoo.it>
Co-authored-by: libsu <libsu@qq.com>
Co-authored-by: reloxx <reloxx@interia.pl>
Co-authored-by: tomas15420 <tomas15420@gmail.com>
Co-authored-by: zobe123 <manuel.zobl@gmx.at>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-04-13 19:06:57 -05:00
Qstick
c82aa5c2c7 Fixed: Validation for CleanOriginalTitle
Fixes #8331
Closes #8332

Co-Authored-By: bakerboy448 <55419169+bakerboy448@users.noreply.github.com>
2023-04-13 19:03:13 -05:00
Qstick
d1bae32e1c Fixed: Correct TitleThe naming token parsing 2023-04-13 18:59:15 -05:00
Qstick
c514c7cac0 Fixed: Default value in new Delay Profile 2023-04-13 18:52:13 -05:00
Qstick
3d244057b5 Fixed: Don't grab propers/repacks when item in queue meets cutoff and propers/repacks are not downloaded automatically
Fixes #8134
2023-04-13 18:47:21 -05:00
Bakerboy448
323510300c Fixed: Cleanup erroneous QBittorrent Seeding calls 2023-04-13 18:14:36 -05:00
Bakerboy448
669d87b7ef Fixed: Include Digital Only Releases for Recent Movie determination
Use most recent of physical or digital release date
2023-04-13 18:14:08 -05:00
Bakerboy448
ec7f7b085a New: More information on on why hardlinks should be used over copying
Closes #8327

(cherry picked from commit 83a9d15ff8721c8effdc2c8055e37bfb757022d4)
2023-04-13 18:13:43 -05:00
Bogdan
ecc906a754 Fixed: Config file settings do not need to be case-sensitive
(cherry picked from commit 2107635b7e7e5392624f2957af7d7b88ba6be283)
2023-04-11 20:00:35 -05:00
Bogdan
d0fcac389c Fixed: Ensure default config file on starting app
(cherry picked from commit 5326a102e23eacfc1132eb544a92af737a531df5)
2023-04-11 20:00:35 -05:00
Qstick
621acbef9a Bump version to 4.4.4 2023-04-09 12:23:51 -05:00
Mark McDowall
7fb1163b23 Fixed: Number input changing while scrolling
(cherry picked from commit cc46ed56b4b70fe1f1443c0a927383f19c989c47)
2023-04-09 12:12:29 -05:00
Sergey M
b48eda95dd Fixed: Mapping by MovieTitles collection instead of PrimaryMovieTitle (#8157)
Co-authored-by: Sergey M <msergein>
2023-04-02 16:53:24 -05:00
Mark McDowall
4627093616 Fixed: Multiple Downloaded Episodes Scan commands should not run in parallel
(cherry picked from commit b3d1e4f520d14c41aa6a7dff049ee9b9ef48fecb)
2023-04-02 15:28:14 -05:00
Lagicrus
a006984d5e Fixed: Lock rating to 0 decimal places in Discovery (#8279)
* Locks to 1 decimal place instead of infinite
2023-04-02 15:27:36 -05:00
Qstick
7d9183ef12 Fixed: Queue error for language custom format on unknown items 2023-03-29 19:21:35 -05:00
Qstick
d35c6683e9 New: Add indexer option for Discord on grab notifications
Fixes #8242

Co-Authored-By: lodu <48859312+lodu@users.noreply.github.com>
2023-03-29 19:01:11 -05:00
Qstick
ac26bcddd9 Fixed: Page Plex Watchlist results
Fixes #8223
Fixes #8042
2023-03-29 18:44:18 -05:00
Devin Buhl
15bafce8cc Add Overview to CustomScript and Webhook Notifications (#8239)
* Add Overview to customscript
2023-03-29 18:34:29 -05:00
Qstick
2167da87ce Enable all analyzers and enforce code style on build
Fixes #8201
Fixes #8202
Fixes #8203
Fixes #8204
Fixes #8205
Fixes #8207
Fixes #8208
Fixes #8209
Fixes #8210
Fixes #8211
Fixes #8212
Fixes #8213
Fixes #8214
Fixes #8215
Closes #8216
Fixes #8217
Closes #8218
Fixes #8219
Closes #8220
2023-03-29 18:27:30 -05:00
Mark McDowall
926d37a572 Fixed: Permissions after installing on Windows and opening Firewall port
(cherry picked from commit ff2e8ffc372a34d08028db3c49f603cdfb87d832)
2023-03-29 17:43:11 -05:00
Bogdan
42c9e4e3e5 Fixed: Parsing of RoDubbed releases as Romanian 2023-03-24 20:40:01 -04:00
bakerboy448
89b609a221 Fixed: Improve some request failure messaging
(cherry picked from commit e968919e63616e30cc401964bd51db8e9e0e26de)

Fixes #8152
2023-03-24 20:38:48 -04:00
Qstick
dfc9f74116 Fixed broken path tests
Fixes #8132

(cherry picked from commit 5a22afc42bb03c9cdfb0a46d470d084dbdd495d5)
2023-03-12 16:56:29 -05:00
Mark McDowall
189603c756 Fixed: USB drives mounted to folders are treated as different mounts
(cherry picked from commit 75378f7bde90b9d3d9b72404c25c017da2cd147c)
2023-03-12 16:56:29 -05:00
Mark McDowall
a78693a2f7 Fixed: Prevent getting disk space from returning no information when it partially fails
(cherry picked from commit 2c65e4fa41418157d0d27b34c3bab80158cff219)
2023-03-12 16:07:22 -05:00
Servarr
cea0c5033a Automated API Docs update 2023-03-12 16:02:48 -05:00
Derek Antrican
1e3a42bf42 Implemented OnMovieAdded for Discord 2023-03-12 16:00:41 -05:00
Qstick
030744ab7b Fixed: Indexer Flags CF Scores not shown in Search
Fixes #8165
2023-03-12 15:51:39 -05:00
Qstick
17fda02d8c Fixed: Drag with touch on Profiles page 2023-03-12 15:32:58 -05:00
cicomalieran
aabf6b9ff8 Fixed: Processing very long ETA from Transmission
(cherry picked from commit 9800bd6b439257e73e3545e125cd03900a3036bb)
2023-03-12 12:28:33 -05:00
Mark McDowall
7b2fd5140b Switch to eslint for linting
(cherry picked from commit a18c3774661f466727ab46315211aecb43ef1def)
2023-03-08 14:31:03 +00:00
Weblate
b6b10d7c6f Translated using Weblate (Croatian) [skip ci]
Currently translated at 19.7% (229 of 1159 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Russian) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 98.8% (1146 of 1159 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.5% (1107 of 1159 strings)

Translated using Weblate (Spanish) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Spanish) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Update translation files  [skip ci]

Updated by "Remove blank strings" hook in Weblate.

Translated using Weblate (Spanish) [skip ci]

Currently translated at 98.7% (1145 of 1159 strings)

Translated using Weblate (Croatian) [skip ci]

Currently translated at 16.1% (187 of 1159 strings)

Translated using Weblate (Croatian) [skip ci]

Currently translated at 16.1% (187 of 1159 strings)

Translated using Weblate (Catalan) [skip ci]

Currently translated at 100.0% (1159 of 1159 strings)

Translated using Weblate (Croatian) [skip ci]

Currently translated at 13.2% (153 of 1159 strings)

Translated using Weblate (Croatian) [skip ci]

Currently translated at 13.2% (153 of 1159 strings)

Translated using Weblate (Chinese (Traditional) (zh_TW)) [skip ci]

Currently translated at 1.6% (19 of 1159 strings)

Translated using Weblate (Ukrainian) [skip ci]

Currently translated at 99.8% (1157 of 1159 strings)

Translated using Weblate (Slovak) [skip ci]

Currently translated at 21.4% (249 of 1159 strings)

Translated using Weblate (Norwegian Bokmål) [skip ci]

Currently translated at 22.1% (257 of 1159 strings)

Translated using Weblate (Catalan) [skip ci]

Currently translated at 98.9% (1147 of 1159 strings)

Translated using Weblate (Arabic) [skip ci]

Currently translated at 90.3% (1047 of 1159 strings)

Translated using Weblate (Chinese (Simplified) (zh_CN)) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Translated using Weblate (Thai) [skip ci]

Currently translated at 89.9% (1042 of 1159 strings)

Translated using Weblate (Bulgarian) [skip ci]

Currently translated at 87.8% (1018 of 1159 strings)

Translated using Weblate (Hindi) [skip ci]

Currently translated at 89.9% (1042 of 1159 strings)

Translated using Weblate (Romanian) [skip ci]

Currently translated at 87.5% (1015 of 1159 strings)

Translated using Weblate (Vietnamese) [skip ci]

Currently translated at 89.9% (1042 of 1159 strings)

Translated using Weblate (Turkish) [skip ci]

Currently translated at 89.7% (1040 of 1159 strings)

Translated using Weblate (Swedish) [skip ci]

Currently translated at 90.7% (1052 of 1159 strings)

Translated using Weblate (Russian) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Translated using Weblate (Portuguese) [skip ci]

Currently translated at 98.8% (1146 of 1159 strings)

Translated using Weblate (Polish) [skip ci]

Currently translated at 98.8% (1146 of 1159 strings)

Translated using Weblate (Dutch) [skip ci]

Currently translated at 95.5% (1107 of 1159 strings)

Translated using Weblate (Korean) [skip ci]

Currently translated at 21.8% (253 of 1159 strings)

Translated using Weblate (Japanese) [skip ci]

Currently translated at 89.9% (1042 of 1159 strings)

Translated using Weblate (Icelandic) [skip ci]

Currently translated at 89.9% (1042 of 1159 strings)

Translated using Weblate (Hungarian) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Translated using Weblate (Hebrew) [skip ci]

Currently translated at 92.8% (1076 of 1159 strings)

Translated using Weblate (Finnish) [skip ci]

Currently translated at 99.8% (1157 of 1159 strings)

Translated using Weblate (Greek) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Translated using Weblate (Danish) [skip ci]

Currently translated at 89.9% (1042 of 1159 strings)

Translated using Weblate (Czech) [skip ci]

Currently translated at 90.7% (1052 of 1159 strings)

Translated using Weblate (Italian) [skip ci]

Currently translated at 94.3% (1094 of 1159 strings)

Translated using Weblate (Spanish) [skip ci]

Currently translated at 98.5% (1142 of 1159 strings)

Translated using Weblate (French) [skip ci]

Currently translated at 99.5% (1154 of 1159 strings)

Translated using Weblate (German) [skip ci]

Currently translated at 99.9% (1158 of 1159 strings)

Added translation using Weblate (Tamil) [skip ci]

Added translation using Weblate (Indonesian) [skip ci]

Added translation using Weblate (Estonian) [skip ci]

Added translation using Weblate (Serbian) [skip ci]

Added translation using Weblate (Croatian) [skip ci]

Added translation using Weblate (Bosnian) [skip ci]

Translated using Weblate (Chinese (Traditional) (zh_TW)) [skip ci]

Currently translated at 1.5% (18 of 1157 strings)

Added translation using Weblate (Spanish (Mexico)) [skip ci]

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: RicardoVelaC <ricardovelac@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>
Co-authored-by: libsu <libsu@qq.com>
Co-authored-by: pedrom20 <pedrom20@gmail.com>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ar/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/bg/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ca/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/cs/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/da/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/de/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/el/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/es/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/he/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/hu/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/is/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/it/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ja/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ko/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nb_NO/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/nl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pl/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ro/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/ru/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/sk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/sv/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/th/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/tr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/uk/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/vi/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_CN/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/zh_TW/
Translation: Servarr/Radarr
2023-02-27 19:12:11 -06:00
Qstick
16fcf0b56b New: Additional custom filter predicates for strings
(cherry picked from commit 6082253166b67d59d7907d83c362116d47bcdaeb)
2023-02-27 19:10:58 -06:00
Bakerboy448
c222a1a434 New: Use Best PageSize for Newznab/Torznab
Max of Default or Max and no more than 100
2023-02-12 18:34:22 -06:00
Qstick
c6e91e028b New: Add Additional Languages
Fixes #6257
Fixes #7967
Closes #7592
Reference #7788

Co-Authored-By: dtalens <6631832+dtalens@users.noreply.github.com>
2023-02-12 15:03:45 -06:00
Bakerboy448
fcf5984944 Fixed: Translations 2023-02-12 13:29:46 -06:00
Mark McDowall
fdfe8ca656 New: Return static response to requests while app is starting
(cherry picked from commit 303fc5d786ccf2ad14c8523fc239696c5d37ea53)

Fixes #8079
Closes #8080
2023-02-12 13:29:46 -06:00
Qstick
150a5c1fc6 Bump version to 4.4.2 2023-02-11 13:23:52 -06:00
Matthew Barrington
9ea0957351 New: Add Ireland as a Certification Country (#8085)
Co-authored-by: Matthew Barrington <git@barrington.it>
2023-02-11 12:36:04 -06:00
Weblate
8befa436cc Translated using Weblate (French) [skip ci]
Currently translated at 99.6% (1153 of 1157 strings)

Translated using Weblate (Portuguese (Brazil)) [skip ci]

Currently translated at 100.0% (1157 of 1157 strings)

Co-authored-by: Havok Dan <havokdan@yahoo.com.br>
Co-authored-by: KevoM <lilmarsu@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/fr/
Translate-URL: https://translate.servarr.com/projects/servarr/radarr/pt_BR/
Translation: Servarr/Radarr
2023-02-11 12:35:19 -06:00
Qstick
53fdb6f07f Delete azuresync.yml 2023-02-11 10:36:40 -06:00
Servarr
0697dbff96 Automated API Docs update 2023-02-07 20:26:31 -06:00
Qstick
34924859aa Fixed: Settings fail to save for some auth setups
(cherry picked from commit a379d0c403449b2623f84aa6851c850971528ff8)
2023-02-07 20:24:48 -06:00
Qstick
9c86598b54 Fixup language specification tests 2023-02-06 19:38:44 -06:00
Qstick
0fe2262162 Fixed: Releases incorrectly rejected due to language 2023-02-06 19:06:03 -06:00
Qstick
47353aea75 Fixed: Avoid failure on null SceneName 2023-02-05 23:31:00 -06:00
Giulia Petenazzi
af43cb2aca New: Added release year to queue ( issue #6330) (#8019) 2023-02-05 19:09:20 -06:00
Fuochi
bc838b74c7 Fixed: Remove initial dot in filename (#4509) 2023-02-05 17:22:07 -06:00
Qstick
cbcf3d1058 New: Custom Format Updates (#8067) 2023-02-05 17:09:37 -06:00
Qstick
c72e64f081 Bump version to 4.4.2 2023-02-04 21:15:36 -06:00
Qstick
e09607edb0 Remove old, broken test
Fixes #7186
2023-02-04 21:12:22 -06:00
Winter
d91578aee3 Fixed: Releases from PTP showing skewed publish date
PTP returns UTC timestamps, without a timezone specifier. Previously, users
would see skewed publish dates, as the UTC timestamps were being parsed
as if they were in the system's timezone. To fix this, we just assume the
publish date is in UTC.
2023-02-04 17:46:23 -06:00
Mark McDowall
affedd7f9d Fixed: Ping endpoint no longer requires authentication
(cherry picked from commit ad42d4a14c814d5911dafb5e78e97ec09b4b13a5)
2023-02-04 17:44:37 -06:00
Qstick
c3665e9fea New: Spanish (Latino) languages
Closes #7914
Closes #3467
Closes #6415
2023-02-04 17:42:39 -06:00
Mark McDowall
364d8bd7c5 Fixed: Don't try to remove the same item from queue multiple times
Closes #7932

(cherry picked from commit 2491da067815e129df3a3a79c0cc7221a9d87094)
2023-02-04 17:32:18 -06:00
Mark McDowall
7142d1f224 Improve usage of Original Title renaming token
Closes #7168

Fixed: Don't recursively add the current file name to new file name when '{Original Title}' is used in addition to other naming tokens
(cherry picked from commit ebb48a19cc792c71bfbd57d5f106067190d95339)
2023-02-04 17:26:07 -06:00
Stevie Robinson
86777e021b Fixed: Mass Editor Footer on Smaller Screens
Closes #6968

(cherry picked from commit 9afcec8b1ffc11da93ae50b73f77f5ebe6e12391)
2023-02-04 17:26:07 -06:00
bakerboy448
9d2dacea97 New: Improve Manual Import logging when not parsing files
Closes #8059

(cherry picked from commit 83f63590630ae0728fd9f9f03567a294934eebcc)
2023-02-04 17:26:07 -06:00
Mark McDowall
d98c86c3d9 Fixed: Parse year in title from square brackets
(cherry picked from commit 99e60196a4e513d6340a090de4a5517f205e7a29)
2023-02-04 17:22:26 -06:00
238 changed files with 2058 additions and 1796 deletions

View File

@@ -19,10 +19,10 @@ indent_size = 4
dotnet_sort_system_directives_first = true
# Avoid "this." and "Me." if not necessary
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_event = false:warning
dotnet_style_qualification_for_field = false:refactoring
dotnet_style_qualification_for_property = false:refactoring
dotnet_style_qualification_for_method = false:refactoring
dotnet_style_qualification_for_event = false:refactoring
# Indentation preferences
csharp_indent_block_contents = true
@@ -32,6 +32,10 @@ csharp_indent_case_contents_when_block = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
dotnet_naming_style.instance_field_style.capitalization = camel_case
dotnet_naming_style.instance_field_style.required_prefix = _
@@ -64,6 +68,7 @@ dotnet_diagnostic.SA1406.severity = suggestion
dotnet_diagnostic.SA1410.severity = suggestion
dotnet_diagnostic.SA1411.severity = suggestion
dotnet_diagnostic.SA1413.severity = none
dotnet_diagnostic.SA1512.severity = none
dotnet_diagnostic.SA1516.severity = none
dotnet_diagnostic.SA1600.severity = none
dotnet_diagnostic.SA1601.severity = none
@@ -162,6 +167,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
@@ -177,9 +183,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
@@ -191,13 +194,11 @@ dotnet_diagnostic.CA1819.severity = suggestion
dotnet_diagnostic.CA1822.severity = suggestion
dotnet_diagnostic.CA1823.severity = suggestion
dotnet_diagnostic.CA1824.severity = suggestion
dotnet_diagnostic.CA1848.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
@@ -228,6 +229,9 @@ dotnet_diagnostic.CA2243.severity = suggestion
dotnet_diagnostic.CA2244.severity = suggestion
dotnet_diagnostic.CA2245.severity = suggestion
dotnet_diagnostic.CA2246.severity = suggestion
dotnet_diagnostic.CA2249.severity = suggestion
dotnet_diagnostic.CA2251.severity = suggestion
dotnet_diagnostic.CA2254.severity = suggestion
dotnet_diagnostic.CA3061.severity = suggestion
dotnet_diagnostic.CA3075.severity = suggestion
dotnet_diagnostic.CA3076.severity = suggestion
@@ -255,7 +259,7 @@ dotnet_diagnostic.CA5392.severity = suggestion
dotnet_diagnostic.CA5394.severity = suggestion
dotnet_diagnostic.CA5397.severity = suggestion
dotnet_diagnostic.SYSLIB0006.severity = none
[*.{js,html,js,hbs,less,css}]
charset = utf-8

View File

@@ -1,9 +0,0 @@
{
"paths": [
"frontend/src/**/*.js"
],
"ignored": [
"**/node_modules/**/*"
],
"port": 5004
}

View File

@@ -1,45 +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 }}
permissions: {}
jobs:
alert:
permissions:
issues: write # to update issue body
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\\Radarr"
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\\Radarr"
ado_wit: "User Story"
ado_new_state: "New"
ado_active_state: "Active"
ado_close_state: "Closed"
ado_bypassrules: true
log_level: 100

View File

@@ -9,13 +9,13 @@ variables:
testsFolder: './_tests'
yarnCacheFolder: $(Pipeline.Workspace)/.yarn
nugetCacheFolder: $(Pipeline.Workspace)/.nuget/packages
majorVersion: '4.4.1'
majorVersion: '4.4.4'
minorVersion: $[counter('minorVersion', 2000)]
radarrVersion: '$(majorVersion).$(minorVersion)'
buildName: '$(Build.SourceBranchName).$(radarrVersion)'
sentryOrg: 'servarr'
sentryUrl: 'https://sentry.servarr.com'
dotnetVersion: '6.0.400'
dotnetVersion: '6.0.408'
nodeVersion: '16.X'
innoVersion: '6.2.0'
windowsImage: 'windows-2022'

View File

@@ -1,3 +1,4 @@
// eslint-disable-next-line filenames/match-exported
const loaderUtils = require('loader-utils');
module.exports = function cssVariablesLoader(source) {

View File

@@ -56,6 +56,7 @@ class HistoryRow extends Component {
movie,
quality,
customFormats,
customFormatScore,
languages,
qualityCutoffNotMet,
eventType,
@@ -175,7 +176,7 @@ class HistoryRow extends Component {
key={name}
className={styles.customFormatScore}
>
{formatCustomFormatScore(data.customFormatScore)}
{formatCustomFormatScore(customFormatScore)}
</TableRowCell>
);
}
@@ -241,8 +242,9 @@ HistoryRow.propTypes = {
movie: PropTypes.object.isRequired,
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
quality: PropTypes.object.isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object),
customFormatScore: PropTypes.number.isRequired,
qualityCutoffNotMet: PropTypes.bool.isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object).isRequired,
eventType: PropTypes.string.isRequired,
sourceTitle: PropTypes.string.isRequired,
date: PropTypes.string.isRequired,

View File

@@ -128,6 +128,7 @@ class QueueRow extends Component {
{
columns.map((column) => {
const {
name,
isVisible
@@ -234,6 +235,16 @@ class QueueRow extends Component {
);
}
if (name === 'year') {
return (
<TableRowCell key={name}>
{
movie ? movie.year : ''
}
</TableRowCell>
);
}
if (name === 'title') {
return (
<TableRowCell key={name}>
@@ -362,6 +373,7 @@ QueueRow.propTypes = {
estimatedCompletionTime: PropTypes.string,
timeleft: PropTypes.string,
size: PropTypes.number,
year: PropTypes.number,
sizeleft: PropTypes.number,
showRelativeDates: PropTypes.bool.isRequired,
shortDateFormat: PropTypes.string.isRequired,

View File

@@ -113,6 +113,7 @@ class AddNewMovieSearchResult extends Component {
images={images}
size={250}
overflow={true}
lazy={false}
/>
</div>

View File

@@ -162,7 +162,7 @@ class CalendarOptionsModalContent extends Component {
values={weekColumnOptions}
value={calendarWeekColumnHeader}
onChange={this.onGlobalInputChange}
helpText={translate('HelpText')}
helpText={translate('SettingsWeekColumnHeaderHelpText')}
/>
</FormGroup>

View File

@@ -112,6 +112,12 @@ class TextInput extends Component {
this._isMouseTarget = false;
};
onWheel = () => {
if (this.props.type === 'number') {
this._input.blur();
}
};
//
// Render
@@ -161,6 +167,7 @@ class TextInput extends Component {
onKeyUp={this.onKeyUp}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}
onWheel={this.onWheel}
/>
);
}

View File

@@ -1,6 +1,7 @@
/* eslint-disable no-bitwise */
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import translate from 'Utilities/String/translate';
import EnhancedSelectInput from './EnhancedSelectInput';
import styles from './UMaskInput.css';
@@ -101,16 +102,16 @@ class UMaskInput extends Component {
</div>
<div className={styles.details}>
<div>
<label>UMask</label>
<label>{translate('UMask')}</label>
<div className={styles.value}>{umask}</div>
</div>
<div>
<label>Folder</label>
<label>{translate('Folder')}</label>
<div className={styles.value}>{folder}</div>
<div className={styles.unit}>d{formatPermissions(folderNum)}</div>
</div>
<div>
<label>File</label>
<label>{translate('File')}</label>
<div className={styles.value}>{file}</div>
<div className={styles.unit}>{formatPermissions(fileNum)}</div>
</div>

View File

@@ -19,7 +19,7 @@
}
}
@media only screen and (max-width: $breakpointLarge) {
@media only screen and (max-width: $breakpointExtraLarge) {
.contentFooter {
flex-wrap: wrap;
}

View File

@@ -73,7 +73,7 @@ function getInfoRowProps(row, props) {
return {
title: translate('Ratings'),
iconName: icons.HEART,
label: `${props.ratings.tmdb.value * 10}%`
label: `${(props.ratings.tmdb.value * 10).toFixed()}%`
};
}

View File

@@ -47,6 +47,10 @@ export const possibleFilterTypes = {
{ key: filterTypes.CONTAINS, value: 'contains' },
{ key: filterTypes.NOT_CONTAINS, value: 'does not contain' },
{ key: filterTypes.EQUAL, value: 'equal' },
{ key: filterTypes.NOT_EQUAL, value: 'not equal' }
{ key: filterTypes.NOT_EQUAL, value: 'not equal' },
{ key: filterTypes.STARTS_WITH, value: 'starts with' },
{ key: filterTypes.NOT_STARTS_WITH, value: 'does not start with' },
{ key: filterTypes.ENDS_WITH, value: 'ends with' },
{ key: filterTypes.NOT_ENDS_WITH, value: 'does not end with' }
]
};

View File

@@ -39,6 +39,22 @@ const filterTypePredicates = {
[filterTypes.NOT_EQUAL]: function(itemValue, filterValue) {
return itemValue !== filterValue;
},
[filterTypes.STARTS_WITH]: function(itemValue, filterValue) {
return itemValue.toLowerCase().startsWith(filterValue.toLowerCase());
},
[filterTypes.NOT_STARTS_WITH]: function(itemValue, filterValue) {
return !itemValue.toLowerCase().startsWith(filterValue.toLowerCase());
},
[filterTypes.ENDS_WITH]: function(itemValue, filterValue) {
return itemValue.toLowerCase().endsWith(filterValue.toLowerCase());
},
[filterTypes.NOT_ENDS_WITH]: function(itemValue, filterValue) {
return !itemValue.toLowerCase().endsWith(filterValue.toLowerCase());
}
};

View File

@@ -10,6 +10,10 @@ export const LESS_THAN = 'lessThan';
export const LESS_THAN_OR_EQUAL = 'lessThanOrEqual';
export const NOT_CONTAINS = 'notContains';
export const NOT_EQUAL = 'notEqual';
export const STARTS_WITH = 'startsWith';
export const NOT_STARTS_WITH = 'notStartsWith';
export const ENDS_WITH = 'endsWith';
export const NOT_ENDS_WITH = 'notEndsWith';
export const all = [
CONTAINS,
@@ -23,5 +27,9 @@ export const all = [
IN_LAST,
NOT_IN_LAST,
IN_NEXT,
NOT_IN_NEXT
NOT_IN_NEXT,
STARTS_WITH,
NOT_STARTS_WITH,
ENDS_WITH,
NOT_ENDS_WITH
];

View File

@@ -64,6 +64,15 @@ const columns = [
isSortable: true,
isVisible: true
},
{
name: 'customFormats',
label: React.createElement(Icon, {
name: icons.INTERACTIVE,
title: translate('CustomFormat')
}),
isSortable: true,
isVisible: true
},
{
name: 'rejections',
label: React.createElement(Icon, {

View File

@@ -5,8 +5,10 @@
}
.quality,
.language {
.languages {
composes: cell from '~Components/Table/Cells/TableRowCell.css';
text-align: center;
}
.label {
@@ -21,3 +23,7 @@
margin-top: 0;
text-align: start;
}
.customFormatTooltip {
max-width: 250px;
}

View File

@@ -12,6 +12,7 @@ import SelectLanguageModal from 'InteractiveImport/Language/SelectLanguageModal'
import SelectMovieModal from 'InteractiveImport/Movie/SelectMovieModal';
import SelectQualityModal from 'InteractiveImport/Quality/SelectQualityModal';
import SelectReleaseGroupModal from 'InteractiveImport/ReleaseGroup/SelectReleaseGroupModal';
import MovieFormats from 'Movie/MovieFormats';
import MovieLanguage from 'Movie/MovieLanguage';
import MovieQuality from 'Movie/MovieQuality';
import formatBytes from 'Utilities/Number/formatBytes';
@@ -150,6 +151,7 @@ class InteractiveImportRow extends Component {
languages,
releaseGroup,
size,
customFormats,
rejections,
isReprocessing,
isSelected,
@@ -226,7 +228,7 @@ class InteractiveImportRow extends Component {
</TableRowCellButton>
<TableRowCellButton
className={styles.language}
className={styles.languages}
title={translate('ClickToChangeLanguage')}
onPress={this.onSelectLanguagePress}
>
@@ -259,7 +261,26 @@ class InteractiveImportRow extends Component {
<TableRowCell>
{
!!rejections.length &&
customFormats?.length ?
<Popover
anchor={
<Icon name={icons.INTERACTIVE} />
}
title={translate('Formats')}
body={
<div className={styles.customFormatTooltip}>
<MovieFormats formats={customFormats} />
</div>
}
position={tooltipPositions.LEFT}
/> :
null
}
</TableRowCell>
<TableRowCell>
{
rejections.length ?
<Popover
anchor={
<Icon
@@ -282,7 +303,9 @@ class InteractiveImportRow extends Component {
</ul>
}
position={tooltipPositions.LEFT}
/>
canFlip={false}
/> :
null
}
</TableRowCell>
@@ -330,6 +353,7 @@ InteractiveImportRow.propTypes = {
languages: PropTypes.arrayOf(PropTypes.object),
releaseGroup: PropTypes.string,
size: PropTypes.number.isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object),
rejections: PropTypes.arrayOf(PropTypes.object).isRequired,
isReprocessing: PropTypes.bool,
isSelected: PropTypes.bool,

View File

@@ -62,6 +62,7 @@ class MovieHistoryRow extends Component {
sourceTitle,
quality,
customFormats,
customFormatScore,
languages,
qualityCutoffNotMet,
date,
@@ -106,7 +107,7 @@ class MovieHistoryRow extends Component {
</TableRowCell>
<TableRowCell key={name}>
{formatCustomFormatScore(data.customFormatScore)}
{formatCustomFormatScore(customFormatScore)}
</TableRowCell>
<RelativeDateCellConnector
@@ -161,7 +162,8 @@ MovieHistoryRow.propTypes = {
sourceTitle: PropTypes.string.isRequired,
languages: PropTypes.arrayOf(PropTypes.object).isRequired,
quality: PropTypes.object.isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object).isRequired,
customFormats: PropTypes.arrayOf(PropTypes.object),
customFormatScore: PropTypes.number.isRequired,
qualityCutoffNotMet: PropTypes.bool.isRequired,
date: PropTypes.string.isRequired,
data: PropTypes.object.isRequired,

View File

@@ -8,11 +8,15 @@
}
.host {
flex: 0 0 300px;
@add-mixin truncate;
flex: 0 1 300px;
}
.path {
flex: 0 0 400px;
@add-mixin truncate;
flex: 0 1 400px;
}
.actions {

View File

@@ -1,15 +1,20 @@
.remotePathMappingsHeader {
display: flex;
margin-bottom: 10px;
padding-right: 24px;
font-weight: bold;
}
.host {
flex: 0 0 300px;
@add-mixin truncate;
flex: 0 1 300px;
}
.path {
flex: 0 0 400px;
@add-mixin truncate;
flex: 0 1 400px;
}
.addRemotePathMapping {

View File

@@ -18,6 +18,7 @@ export const certificationCountryOptions = [
{ key: 'fr', value: 'France' },
{ key: 'de', value: 'Germany' },
{ key: 'gb', value: 'Great Britain' },
{ key: 'ie', value: 'Ireland' },
{ key: 'it', value: 'Italy' },
{ key: 'es', value: 'Spain' },
{ key: 'us', value: 'United States' },

View File

@@ -191,6 +191,7 @@ const delayProfileShape = {
enableTorrent: PropTypes.shape(boolSettingShape).isRequired,
usenetDelay: PropTypes.shape(numberSettingShape).isRequired,
torrentDelay: PropTypes.shape(numberSettingShape).isRequired,
bypassIfHighestQuality: PropTypes.shape(boolSettingShape).isRequired,
order: PropTypes.shape(numberSettingShape),
tags: PropTypes.shape(tagSettingShape).isRequired
};

View File

@@ -13,6 +13,7 @@ const newDelayProfile = {
preferredProtocol: 'usenet',
usenetDelay: 0,
torrentDelay: 0,
bypassIfHighestQuality: false,
tags: []
};

View File

@@ -1,6 +1,6 @@
import React, { Component } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { DndProvider } from 'react-dnd-multi-backend';
import HTML5toTouch from 'react-dnd-multi-backend/dist/esm/HTML5toTouch';
import Link from 'Components/Link/Link';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
@@ -25,7 +25,7 @@ class Profiles extends Component {
/>
<PageContentBody>
<DndProvider backend={HTML5Backend}>
<DndProvider options={HTML5toTouch}>
<QualityProfilesConnector />
<DelayProfilesConnector />
<div className={styles.addCustomFormatMessage}>

View File

@@ -118,6 +118,12 @@ export const defaultState = {
isSortable: true,
isVisible: false
},
{
name: 'year',
label: translate('Year'),
isSortable: true,
isVisible: true
},
{
name: 'outputPath',
label: translate('OutputPath'),

View File

@@ -1,5 +1,4 @@
function formatCustomFormatScore(input) {
function formatCustomFormatScore(input, customFormatsLength = 0) {
const score = Number(input);
if (score > 0) {
@@ -10,7 +9,7 @@ function formatCustomFormatScore(input) {
return score;
}
return '';
return customFormatsLength > 0 ? '+0' : '';
}
export default formatCustomFormatScore;

View File

@@ -8,8 +8,8 @@
"clean": "rimraf ./_output/UI && rimraf \"**/*.js.map\"",
"start": "webpack --watch --config ./frontend/build/webpack.config.js",
"watch": "webpack --watch --config ./frontend/build/webpack.config.js",
"lint": "esprint check",
"lint-fix": "esprint check --fix",
"lint": "eslint --config frontend/.eslintrc.js --ignore-path frontend/.eslintignore frontend/",
"lint-fix": "yarn lint --fix",
"stylelint-linux": "stylelint $(find frontend -name '*.css') --config frontend/.stylelintrc",
"stylelint-windows": "stylelint frontend/**/*.css --config frontend/.stylelintrc"
},
@@ -30,7 +30,7 @@
"@fortawesome/free-regular-svg-icons": "6.1.0",
"@fortawesome/free-solid-svg-icons": "6.1.0",
"@fortawesome/react-fontawesome": "0.1.18",
"@microsoft/signalr": "6.0.8",
"@microsoft/signalr": "6.0.16",
"@sentry/browser": "6.18.2",
"@sentry/integrations": "6.18.2",
"classnames": "2.3.1",
@@ -108,8 +108,7 @@
"eslint-plugin-json": "3.1.0",
"eslint-plugin-react": "7.29.4",
"eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-simple-import-sort": "7.0.0",
"esprint": "3.3.0",
"eslint-plugin-simple-import-sort": "8.0.0",
"file-loader": "6.2.0",
"filemanager-webpack-plugin": "5.0.0",
"html-webpack-plugin": "5.3.1",

3
src/.globalconfig Normal file
View File

@@ -0,0 +1,3 @@
is_global = true
dotnet_diagnostic.CA1014.severity = none

View File

@@ -1,7 +1,9 @@
<Project>
<!-- Common to all Radarr Projects -->
<PropertyGroup>
<AnalysisLevel>6.0-all</AnalysisLevel>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<ErrorOnDuplicatePublishOutputFiles>false</ErrorOnDuplicatePublishOutputFiles>
<PlatformTarget>AnyCPU</PlatformTarget>
@@ -90,7 +92,7 @@
<!-- Standard testing packages -->
<ItemGroup Condition="'$(TestProject)'=='true'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="NUnit3TestAdapter" Version="4.1.0" />
<PackageReference Include="NunitXml.TestLogger" Version="3.0.117" />

View File

@@ -356,7 +356,7 @@ namespace NzbDrone.Common.Disk
}
}
public string GetPathRoot(string path)
public virtual string GetPathRoot(string path)
{
Ensure.That(path, () => path).IsValidPath();

View File

@@ -11,6 +11,7 @@ namespace NzbDrone.Common.EnvironmentInfo
public interface IAppFolderFactory
{
void Register();
void SetPermissions();
}
public class AppFolderFactory : IAppFolderFactory
@@ -58,7 +59,7 @@ namespace NzbDrone.Common.EnvironmentInfo
InitializeMonoApplicationData();
}
private void SetPermissions()
public void SetPermissions()
{
try
{

View File

@@ -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; }

View File

@@ -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
{

View File

@@ -131,7 +131,7 @@ namespace NzbDrone.Common.Extensions
public static string WrapInQuotes(this string text)
{
if (!text.Contains(" "))
if (!text.Contains(' '))
{
return text;
}
@@ -217,7 +217,7 @@ namespace NzbDrone.Common.Extensions
public static string ToUrlHost(this string input)
{
return input.Contains(":") ? $"[{input}]" : input;
return input.Contains(':') ? $"[{input}]" : input;
}
}
}

View File

@@ -216,7 +216,7 @@ namespace NzbDrone.Common.Http.Dispatchers
}
}
private void AddContentHeader(HttpRequestMessage request, string header, string value)
private static void AddContentHeader(HttpRequestMessage request, string header, string value)
{
var headers = request.Content?.Headers;
if (headers == null)

View File

@@ -170,7 +170,7 @@ namespace NzbDrone.Common.Http
if (baseSlashIndex >= 0)
{
return basePath.Substring(0, baseSlashIndex) + "/" + relativePath;
return $"{basePath.AsSpan(0, baseSlashIndex)}/{relativePath}";
}
return relativePath;

View File

@@ -5,8 +5,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DryIoc.dll" Version="5.3.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.1" />
<PackageReference Include="Microsoft.Extensions.Hosting.WindowsServices" Version="6.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
<PackageReference Include="NLog" Version="5.0.1" />
<PackageReference Include="NLog.Extensions.Logging" Version="5.0.0" />
@@ -14,10 +14,10 @@
<PackageReference Include="Sentry" Version="3.23.1" />
<PackageReference Include="NLog.Targets.Syslog" Version="7.0.0" />
<PackageReference Include="SharpZipLib" Version="1.3.3" />
<PackageReference Include="System.Text.Json" Version="6.0.5" />
<PackageReference Include="System.Text.Json" Version="6.0.7" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<PackageReference Include="System.Data.SQLite.Core.Servarr" Version="1.0.115.5-18" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" />
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.1" />
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="5.0.0" />
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
<PackageReference Include="System.ServiceProcess.ServiceController" Version="6.0.0" />

View File

@@ -64,7 +64,7 @@ namespace NzbDrone.Common
var args = $"create {serviceName} " +
$"DisplayName= \"{serviceName}\" " +
$"binpath= \"{Process.GetCurrentProcess().MainModule.FileName}\" " +
$"binpath= \"{Environment.ProcessPath}\" " +
"start= auto " +
"depend= EventLog/Tcpip/http " +
"obj= \"NT AUTHORITY\\LocalService\"";

View File

@@ -19,7 +19,7 @@ namespace NzbDrone.Common.TPL
private readonly int _maxDegreeOfParallelism;
/// <summary>Whether the scheduler is currently processing work items.</summary>
private int _delegatesQueuedOrRunning = 0;
private int _delegatesQueuedOrRunning;
/// <summary>
/// Initializes an instance of the LimitedConcurrencyLevelTaskScheduler class with the

View File

@@ -81,8 +81,9 @@ namespace NzbDrone.Core.Test.Blocklisting
Subject.DeleteForMovies(new List<int> { _movie1.Id });
var removedMovieBlocklists = Subject.BlocklistedByMovie(_movie1.Id);
var nonRemovedMovieBlocklists = Subject.BlocklistedByMovie(_movie2.Id);
var blocklist = Subject.All();
var removedMovieBlocklists = blocklist.Where(b => b.MovieId == _movie1.Id);
var nonRemovedMovieBlocklists = blocklist.Where(b => b.MovieId == _movie2.Id);
removedMovieBlocklists.Should().HaveCount(0);
nonRemovedMovieBlocklists.Should().HaveCount(1);

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
@@ -9,7 +9,7 @@ using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.CustomFormats
{
[TestFixture]
public class CustomFormatsFixture : CoreTest
public class CustomFormatsTestHelpers : CoreTest
{
private static List<CustomFormat> _customFormats { get; set; }

View File

@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.Datastore.Migration
[TestFixture]
public class custom_formatsFixture : MigrationTest<add_custom_formats>
{
public static Dictionary<int, int> QualityToDefinition = null;
public static Dictionary<int, int> QualityToDefinition;
public void AddDefaultProfile(add_custom_formats m, string name, Quality cutoff, params Quality[] allowed)
{

View File

@@ -46,14 +46,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
ParsedMovieInfo = new ParsedMovieInfo { Quality = new QualityModel(Quality.DVD, new Revision(version: 2)) },
};
CustomFormatsFixture.GivenCustomFormats(_format1, _format2);
CustomFormatsTestHelpers.GivenCustomFormats(_format1, _format2);
}
[Test]
public void should_allow_if_format_score_greater_than_min()
{
_remoteMovie.CustomFormats = new List<CustomFormat> { _format1 };
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(_format1.Name);
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_format1.Name);
_remoteMovie.CustomFormatScore = _remoteMovie.Movie.Profile.CalculateCustomFormatScore(_remoteMovie.CustomFormats);
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
@@ -63,7 +63,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_deny_if_format_score_not_greater_than_min()
{
_remoteMovie.CustomFormats = new List<CustomFormat> { _format2 };
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(_format1.Name);
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_format1.Name);
_remoteMovie.CustomFormatScore = _remoteMovie.Movie.Profile.CalculateCustomFormatScore(_remoteMovie.CustomFormats);
Console.WriteLine(_remoteMovie.CustomFormatScore);
@@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_deny_if_format_score_not_greater_than_min_2()
{
_remoteMovie.CustomFormats = new List<CustomFormat> { _format2, _format1 };
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(_format1.Name);
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_format1.Name);
_remoteMovie.CustomFormatScore = _remoteMovie.Movie.Profile.CalculateCustomFormatScore(_remoteMovie.CustomFormats);
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
@@ -86,7 +86,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_allow_if_all_format_is_defined_in_profile()
{
_remoteMovie.CustomFormats = new List<CustomFormat> { _format2, _format1 };
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(_format1.Name, _format2.Name);
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_format1.Name, _format2.Name);
_remoteMovie.CustomFormatScore = _remoteMovie.Movie.Profile.CalculateCustomFormatScore(_remoteMovie.CustomFormats);
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
@@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_deny_if_no_format_was_parsed_and_min_score_positive()
{
_remoteMovie.CustomFormats = new List<CustomFormat> { };
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(_format1.Name, _format2.Name);
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_format1.Name, _format2.Name);
_remoteMovie.CustomFormatScore = _remoteMovie.Movie.Profile.CalculateCustomFormatScore(_remoteMovie.CustomFormats);
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
@@ -106,7 +106,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
public void should_allow_if_no_format_was_parsed_min_score_is_zero()
{
_remoteMovie.CustomFormats = new List<CustomFormat> { };
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(_format1.Name, _format2.Name);
_remoteMovie.Movie.Profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_format1.Name, _format2.Name);
_remoteMovie.Movie.Profile.MinFormatScore = 0;
_remoteMovie.CustomFormatScore = _remoteMovie.Movie.Profile.CalculateCustomFormatScore(_remoteMovie.CustomFormats);

View File

@@ -40,8 +40,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void GivenProfile(Profile profile)
{
CustomFormatsFixture.GivenCustomFormats();
profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems();
CustomFormatsTestHelpers.GivenCustomFormats();
profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems();
profile.MinFormatScore = 0;
_remoteMovie.Movie.Profile = profile;
@@ -74,7 +74,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
_customFormat = new CustomFormat("My Format", new ResolutionSpecification { Value = (int)Resolution.R1080p }) { Id = 1 };
CustomFormatsFixture.GivenCustomFormats(_customFormat);
CustomFormatsTestHelpers.GivenCustomFormats(_customFormat);
}
[Test]
@@ -157,7 +157,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Cutoff = Quality.HDTV720p.Id,
Items = Qualities.QualityFixture.GetDefaultQualities(),
MinFormatScore = 0,
FormatItems = CustomFormatsFixture.GetSampleFormatItems("My Format"),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems("My Format"),
UpgradeAllowed = true
});

View File

@@ -38,14 +38,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Mocker.Resolve<UpgradableSpecification>();
_upgradeHistory = Mocker.Resolve<HistorySpecification>();
CustomFormatsFixture.GivenCustomFormats();
CustomFormatsTestHelpers.GivenCustomFormats();
_fakeMovie = Builder<Movie>.CreateNew()
.With(c => c.Profile = new Profile
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
Cutoff = Quality.Bluray1080p.Id,
FormatItems = CustomFormatsFixture.GetSampleFormatItems("None"),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems("None"),
MinFormatScore = 0,
UpgradeAllowed = true
})
@@ -66,7 +66,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Returns(true);
Mocker.GetMock<ICustomFormatCalculationService>()
.Setup(x => x.ParseCustomFormat(It.IsAny<MovieHistory>()))
.Setup(x => x.ParseCustomFormat(It.IsAny<MovieHistory>(), It.IsAny<Movie>()))
.Returns(new List<CustomFormat>());
}
@@ -163,7 +163,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
Cutoff = Quality.Bluray1080p.Id,
FormatItems = CustomFormatsFixture.GetSampleFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(),
MinFormatScore = 0
};
@@ -171,7 +171,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, new Revision(version: 1));
Mocker.GetMock<ICustomFormatCalculationService>()
.Setup(x => x.ParseCustomFormat(It.IsAny<MovieHistory>()))
.Setup(x => x.ParseCustomFormat(It.IsAny<MovieHistory>(), It.IsAny<Movie>()))
.Returns(new List<CustomFormat>());
GivenMostRecentForEpisode(FIRST_EPISODE_ID, string.Empty, _upgradableQuality, DateTime.UtcNow, MovieHistoryEventType.Grabbed);
@@ -186,7 +186,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
Cutoff = Quality.WEBDL1080p.Id,
FormatItems = CustomFormatsFixture.GetSampleFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(),
MinFormatScore = 0
};
@@ -221,7 +221,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
Cutoff = Quality.WEBDL1080p.Id,
FormatItems = CustomFormatsFixture.GetSampleFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(),
MinFormatScore = 0
};

View File

@@ -41,17 +41,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private void WithEnglishRelease()
{
_remoteMovie.ParsedMovieInfo.Languages = new List<Language> { Language.English };
_remoteMovie.Languages = new List<Language> { Language.English };
}
private void WithGermanRelease()
{
_remoteMovie.ParsedMovieInfo.Languages = new List<Language> { Language.German };
_remoteMovie.Languages = new List<Language> { Language.German };
}
private void WithFrenchRelease()
{
_remoteMovie.ParsedMovieInfo.Languages = new List<Language> { Language.French };
_remoteMovie.Languages = new List<Language> { Language.French };
}
[Test]

View File

@@ -37,7 +37,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_customFormat1 = new CustomFormat("My Format 1", new LanguageSpecification { Value = (int)Language.English }) { Id = 1 };
_customFormat2 = new CustomFormat("My Format 2", new LanguageSpecification { Value = (int)Language.French }) { Id = 2 };
CustomFormatsFixture.GivenCustomFormats(_customFormat1, _customFormat2);
CustomFormatsTestHelpers.GivenCustomFormats(_customFormat1, _customFormat2);
Mocker.GetMock<IQualityDefinitionService>()
.Setup(s => s.Get(It.IsAny<Quality>()))
@@ -62,7 +62,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
remoteMovie.Movie = Builder<Movie>.CreateNew().With(m => m.Profile = new Profile
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
FormatItems = CustomFormatsFixture.GetSampleFormatItems(_customFormat1.Name, _customFormat2.Name),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_customFormat1.Name, _customFormat2.Name),
MinFormatScore = 0
})
.With(m => m.Title = "A Movie")

View File

@@ -48,7 +48,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[SetUp]
public void Setup()
{
CustomFormatsFixture.GivenCustomFormats(_customFormat1, _customFormat2);
CustomFormatsTestHelpers.GivenCustomFormats(_customFormat1, _customFormat2);
}
private void GivenAutoDownloadPropers(ProperDownloadTypes type)
@@ -73,7 +73,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
var profile = new Profile
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
FormatItems = CustomFormatsFixture.GetSampleFormatItems(_customFormat1.Name, _customFormat2.Name),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(_customFormat1.Name, _customFormat2.Name),
MinFormatScore = 0
};

View File

@@ -4,9 +4,11 @@ using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Download.TrackedDownloads;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Profiles;
@@ -32,13 +34,13 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{
Mocker.Resolve<UpgradableSpecification>();
CustomFormatsFixture.GivenCustomFormats();
CustomFormatsTestHelpers.GivenCustomFormats();
_movie = Builder<Movie>.CreateNew()
.With(e => e.Profile = new Profile
{
Items = Qualities.QualityFixture.GetDefaultQualities(),
FormatItems = CustomFormatsFixture.GetSampleFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(),
MinFormatScore = 0,
UpgradeAllowed = true
})
@@ -58,7 +60,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.Build();
Mocker.GetMock<ICustomFormatCalculationService>()
.Setup(x => x.ParseCustomFormat(It.IsAny<ParsedMovieInfo>(), _movie))
.Setup(x => x.ParseCustomFormat(It.IsAny<RemoteMovie>(), It.IsAny<long>()))
.Returns(new List<CustomFormat>());
}
@@ -204,5 +206,31 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_false_if_same_quality_non_proper_in_queue_and_download_propers_is_do_not_upgrade()
{
_remoteMovie.ParsedMovieInfo.Quality = new QualityModel(Quality.HDTV720p, new Revision(2));
_movie.Profile.Cutoff = _remoteMovie.ParsedMovieInfo.Quality.Quality.Id;
Mocker.GetMock<IConfigService>()
.Setup(s => s.DownloadPropersAndRepacks)
.Returns(ProperDownloadTypes.DoNotUpgrade);
var remoteMovie = Builder<RemoteMovie>.CreateNew()
.With(r => r.Movie = _movie)
.With(r => r.ParsedMovieInfo = new ParsedMovieInfo
{
Quality = new QualityModel(Quality.HDTV720p),
Languages = new List<Language> { Language.English }
})
.With(r => r.Release = _releaseInfo)
.With(r => r.CustomFormats = new List<CustomFormat>())
.Build();
GivenQueue(new List<RemoteMovie> { remoteMovie });
Subject.IsSatisfiedBy(_remoteMovie, null).Accepted.Should().BeFalse();
}
}
}

View File

@@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Mocker.Resolve<UpgradableSpecification>();
_upgradeDisk = Mocker.Resolve<UpgradeDiskSpecification>();
CustomFormatsFixture.GivenCustomFormats();
CustomFormatsTestHelpers.GivenCustomFormats();
_firstFile = new MovieFile { Quality = new QualityModel(Quality.Bluray1080p, new Revision(version: 2)), DateAdded = DateTime.Now };
@@ -39,7 +39,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
.With(c => c.Profile = new Profile
{
Cutoff = Quality.Bluray1080p.Id, Items = Qualities.QualityFixture.GetDefaultQualities(),
FormatItems = CustomFormatsFixture.GetSampleFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(),
MinFormatScore = 0
})
.With(e => e.MovieFile = _firstFile)

View File

@@ -0,0 +1,112 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Download.Aggregation.Aggregators;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Download.Aggregation.Aggregators
{
[TestFixture]
public class AggregateLanguagesFixture : CoreTest<AggregateLanguages>
{
private RemoteMovie _remoteMovie;
private Movie _movie;
private string _simpleReleaseTitle = "Series.Title.S01E01.xyz-RlsGroup";
[SetUp]
public void Setup()
{
_movie = Builder<Movie>.CreateNew()
.With(m => m.MovieMetadata = new MovieMetadata
{
Title = "Some Movie",
OriginalLanguage = Language.English
})
.Build();
_remoteMovie = Builder<RemoteMovie>.CreateNew()
.With(l => l.ParsedMovieInfo = null)
.With(l => l.Movie = _movie)
.Build();
}
private ParsedMovieInfo GetParsedMovieInfo(List<Language> languages, string releaseTitle, string releaseTokens = "")
{
return new ParsedMovieInfo
{
Languages = languages,
ReleaseTitle = releaseTitle,
SimpleReleaseTitle = releaseTokens
};
}
[Test]
public void should_return_existing_language_if_episode_title_does_not_have_language()
{
_remoteMovie.ParsedMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Original }, _simpleReleaseTitle);
Subject.Aggregate(_remoteMovie).Languages.Should().Contain(_movie.MovieMetadata.Value.OriginalLanguage);
}
[Test]
public void should_return_parsed_language()
{
_remoteMovie.ParsedMovieInfo = GetParsedMovieInfo(new List<Language> { Language.French }, _simpleReleaseTitle);
Subject.Aggregate(_remoteMovie).Languages.Should().Equal(_remoteMovie.ParsedMovieInfo.Languages);
}
[Test]
public void should_exclude_language_that_is_part_of_episode_title_when_release_tokens_contains_episode_title()
{
var releaseTitle = "Series.Title.S01E01.Jimmy.The.Greek.xyz-RlsGroup";
var releaseTokens = ".Jimmy.The.Greek.xyz-RlsGroup";
_remoteMovie.Movie.Title = "Jimmy The Greek";
_remoteMovie.ParsedMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Greek }, releaseTitle, releaseTokens);
Subject.Aggregate(_remoteMovie).Languages.Should().Equal(_movie.MovieMetadata.Value.OriginalLanguage);
}
[Test]
public void should_remove_parsed_language_that_is_part_of_episode_title_when_release_tokens_contains_episode_title()
{
var releaseTitle = "Series.Title.S01E01.Jimmy.The.Greek.French.xyz-RlsGroup";
var releaseTokens = ".Jimmy.The.Greek.French.xyz-RlsGroup";
_remoteMovie.Movie.Title = "Jimmy The Greek";
_remoteMovie.ParsedMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Greek, Language.French }, releaseTitle, releaseTokens);
Subject.Aggregate(_remoteMovie).Languages.Should().Equal(Language.French);
}
[Test]
public void should_not_exclude_language_that_is_part_of_episode_title_when_release_tokens_does_not_contain_episode_title()
{
var releaseTitle = "Series.Title.S01E01.xyz-RlsGroup";
var releaseTokens = ".xyz-RlsGroup";
_remoteMovie.Movie.Title = "Jimmy The Greek";
_remoteMovie.ParsedMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Greek }, releaseTitle, releaseTokens);
Subject.Aggregate(_remoteMovie).Languages.Should().Equal(Language.Greek);
}
[Test]
public void should_use_reparse_language_after_determining_languages_that_are_in_episode_titles()
{
var releaseTitle = "Series.Title.S01E01.Jimmy.The.Greek.Greek.xyz-RlsGroup";
var releaseTokens = ".Jimmy.The.Greek.Greek.xyz-RlsGroup";
_remoteMovie.Movie.Title = "Jimmy The Greek";
_remoteMovie.ParsedMovieInfo = GetParsedMovieInfo(new List<Language> { Language.Greek }, releaseTitle, releaseTokens);
Subject.Aggregate(_remoteMovie).Languages.Should().Equal(Language.Greek);
}
}
}

View File

@@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.FreeboxDownloadTests
Mocker.GetMock<IHttpClient>()
.Setup(s => s.Get(It.IsAny<HttpRequest>()))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0]));
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), Array.Empty<byte>()));
}
protected void GivenCategory()

View File

@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
@@ -275,7 +276,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[TestCase(-1)] // Infinite/Unknown
[TestCase(-2)] // Magnet Downloading
public void should_ignore_negative_eta(int eta)
public void should_ignore_negative_eta(long eta)
{
_completed.Eta = eta;
@@ -284,6 +285,26 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
item.RemainingTime.Should().NotHaveValue();
}
[TestCase(2147483648)] // 2038-01-19T03:14:08Z > int.MaxValue as unix timestamp can be either an int or a long
public void should_support_long_values_for_eta_in_seconds(long eta)
{
_downloading.Eta = eta;
PrepareClientToReturnDownloadingItem();
var item = Subject.GetItems().Single();
item.RemainingTime.Should().Be(TimeSpan.FromSeconds(eta));
}
[TestCase(2147483648000)] // works with milliseconds format too
public void should_support_long_values_for_eta_in_milliseconds(long eta)
{
_downloading.Eta = eta;
PrepareClientToReturnDownloadingItem();
var item = Subject.GetItems().Single();
item.RemainingTime.Should().Be(TimeSpan.FromMilliseconds(eta));
}
[Test]
public void should_not_be_removable_and_should_not_allow_move_files_if_max_ratio_reached_and_not_stopped()
{

View File

@@ -271,7 +271,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[TestCase(-1)] // Infinite/Unknown
[TestCase(-2)] // Magnet Downloading
public void should_ignore_negative_eta(int eta)
public void should_ignore_negative_eta(long eta)
{
_completed.Eta = eta;

View File

@@ -54,6 +54,7 @@ namespace NzbDrone.Core.Test.Download.Pending.PendingReleaseServiceTests
Id = id,
Title = "Movie.Title.2020.720p-Radarr",
ParsedMovieInfo = new ParsedMovieInfo { MovieTitles = new List<string> { title }, Year = year },
Release = Builder<ReleaseInfo>.CreateNew().Build(),
MovieId = _movie.Id
});
}

View File

@@ -62,7 +62,7 @@ namespace NzbDrone.Core.Test.Extras.Others
var results = Subject.ImportFiles(_localMovie, _movieFile, files, true).ToList();
results.Count().Should().Be(1);
results.Count.Should().Be(1);
results[0].RelativePath.AsOsAgnostic().PathEquals(expectedOutputPath.AsOsAgnostic()).Should().Be(true);
}
@@ -78,7 +78,7 @@ namespace NzbDrone.Core.Test.Extras.Others
var results = Subject.ImportFiles(_localMovie, _movieFile, files, true).ToList();
results.Count().Should().Be(1);
results.Count.Should().Be(1);
}
}
}

View File

@@ -67,7 +67,7 @@ namespace NzbDrone.Core.Test.Extras.Subtitles
var results = Subject.ImportFiles(_localMovie, _movieFile, files, true).ToList();
results.Count().Should().Be(0);
results.Count.Should().Be(0);
}
[Test]
@@ -84,7 +84,7 @@ namespace NzbDrone.Core.Test.Extras.Subtitles
var results = Subject.ImportFiles(_localMovie, _movieFile, files, true).ToList();
results.Count().Should().Be(1);
results.Count.Should().Be(1);
results[0].RelativePath.AsOsAgnostic().PathEquals(expectedOutputPath.AsOsAgnostic()).Should().Be(true);
}
@@ -110,7 +110,7 @@ namespace NzbDrone.Core.Test.Extras.Subtitles
var results = Subject.ImportFiles(_localMovie, _movieFile, files, true).ToList();
results.Count().Should().Be(expectedOutputs.Length);
results.Count.Should().Be(expectedOutputs.Length);
for (int i = 0; i < expectedOutputs.Length; i++)
{
@@ -139,7 +139,7 @@ namespace NzbDrone.Core.Test.Extras.Subtitles
var results = Subject.ImportFiles(_localMovie, _movieFile, files, true).ToList();
results.Count().Should().Be(expectedOutputs.Length);
results.Count.Should().Be(expectedOutputs.Length);
for (int i = 0; i < expectedOutputs.Length; i++)
{
@@ -169,7 +169,7 @@ namespace NzbDrone.Core.Test.Extras.Subtitles
var results = Subject.ImportFiles(_localMovie, _movieFile, new List<string> { subtitleFile }, true).ToList();
results.Count().Should().Be(1);
results.Count.Should().Be(1);
results[0].RelativePath.AsOsAgnostic().PathEquals(expectedOutputPath.AsOsAgnostic()).Should().Be(true);

View File

@@ -62,13 +62,21 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
releaseInfo.Size.Should().Be(1183105773);
}
[Test]
public void should_use_pagesize_reported_by_caps()
public void should_use_best_pagesize_reported_by_caps()
{
_caps.MaxPageSize = 30;
_caps.DefaultPageSize = 25;
Subject.PageSize.Should().Be(25);
Subject.PageSize.Should().Be(30);
}
[Test]
public void should_not_use_pagesize_over_100_even_if_reported_in_caps()
{
_caps.MaxPageSize = 250;
_caps.DefaultPageSize = 25;
Subject.PageSize.Should().Be(100);
}
}
}

View File

@@ -1,3 +1,4 @@
using System;
using System.Linq;
using System.Net.Http;
using FluentAssertions;
@@ -55,7 +56,7 @@ namespace NzbDrone.Core.Test.IndexerTests.PTPTests
first.DownloadUrl.Should().Be("https://passthepopcorn.me/torrents.php?action=download&id=452135&authkey=00000000000000000000000000000000&torrent_pass=00000000000000000000000000000000");
first.InfoUrl.Should().Be("https://passthepopcorn.me/torrents.php?id=148131&torrentid=452135");
// first.PublishDate.Should().Be(DateTime.Parse("2017-04-17T12:13:42+0000").ToUniversalTime()); stupid timezones
first.PublishDate.Should().Be(DateTime.Parse("2016-10-18T23:40:59+0000").ToUniversalTime());
first.Size.Should().Be(2466170624L);
first.InfoHash.Should().BeNullOrEmpty();
first.MagnetUrl.Should().BeNullOrEmpty();

View File

@@ -135,12 +135,21 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
}
[Test]
public void should_use_pagesize_reported_by_caps()
public void should_use_best_pagesize_reported_by_caps()
{
_caps.MaxPageSize = 30;
_caps.DefaultPageSize = 25;
Subject.PageSize.Should().Be(25);
Subject.PageSize.Should().Be(30);
}
[Test]
public void should_not_use_pagesize_over_100_even_if_reported_in_caps()
{
_caps.MaxPageSize = 250;
_caps.DefaultPageSize = 25;
Subject.PageSize.Should().Be(100);
}
[TestCase("http://localhost:9117/", "/api")]

View File

@@ -49,6 +49,14 @@ namespace NzbDrone.Core.Test.Languages
new object[] { 34, Language.Bengali },
new object[] { 35, Language.Slovak },
new object[] { 36, Language.Latvian },
new object[] { 37, Language.SpanishLatino },
new object[] { 38, Language.Catalan },
new object[] { 39, Language.Croatian },
new object[] { 40, Language.Serbian },
new object[] { 41, Language.Bosnian },
new object[] { 42, Language.Estonian },
new object[] { 43, Language.Tamil },
new object[] { 44, Language.Indonesian }
};
public static object[] ToIntCases =
@@ -92,6 +100,14 @@ namespace NzbDrone.Core.Test.Languages
new object[] { Language.Bengali, 34 },
new object[] { Language.Slovak, 35 },
new object[] { Language.Latvian, 36 },
new object[] { Language.SpanishLatino, 37 },
new object[] { Language.Catalan, 38 },
new object[] { Language.Croatian, 39 },
new object[] { Language.Serbian, 40 },
new object[] { Language.Bosnian, 41 },
new object[] { Language.Estonian, 42 },
new object[] { Language.Tamil, 43 },
new object[] { Language.Indonesian, 44 }
};
[Test]

View File

@@ -14,7 +14,7 @@ namespace NzbDrone.Core.Test.MediaFiles.MediaFileDeletionService
[TestFixture]
public class DeleteMovieFileFixture : CoreTest<Core.MediaFiles.MediaFileDeletionService>
{
private static readonly string RootFolder = @"C:\Test\Movies";
private const string RootFolder = @"C:\Test\Movies";
private Movie _movie;
private MovieFile _movieFile;

View File

@@ -35,7 +35,7 @@ namespace NzbDrone.Core.Test.MovieTests.MovieRepositoryTests
var profile = new Profile
{
Items = Qualities.QualityFixture.GetDefaultQualities(Quality.Bluray1080p, Quality.DVD, Quality.HDTV720p),
FormatItems = CustomFormatsFixture.GetDefaultFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetDefaultFormatItems(),
MinFormatScore = 0,
Cutoff = Quality.Bluray1080p.Id,
Name = "TestProfile"

View File

@@ -10,6 +10,8 @@ namespace NzbDrone.Core.Test.OrganizerTests
{
[TestCase("Mission: Impossible - no [HDTV-720p]",
"Mission Impossible - no [HDTV-720p]")]
[TestCase(".45 (2006)", "45 (2006)")]
[TestCase(" The Movie Title ", "The Movie Title")]
public void CleanFileName(string name, string expectedName)
{
FileNameBuilder.CleanFileName(name).Should().Be(expectedName);

View File

@@ -562,19 +562,6 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
.Should().Be(string.Format("HDTV-720p{0}South{0}Park", separator));
}
[Test]
public void should_be_able_to_use_original_filename()
{
_movie.Title = "30 Rock";
_namingConfig.StandardMovieFormat = "{Movie Title} - {Original Filename}";
_movieFile.SceneName = "30.Rock.S01E01.xvid-LOL";
_movieFile.RelativePath = "30 Rock - S01E01 - Test";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("30 Rock - 30 Rock - S01E01 - Test");
}
[TestCase("en-US")]
[TestCase("fr-FR")]
[TestCase("az")]

View File

@@ -0,0 +1,88 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.CustomFormats;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
{
[TestFixture]
public class OriginalTitleFixture : CoreTest<FileNameBuilder>
{
private Movie _movie;
private MovieFile _movieFile;
private NamingConfig _namingConfig;
[SetUp]
public void Setup()
{
_movie = Builder<Movie>
.CreateNew()
.With(s => s.Title = "My Movie")
.Build();
_movieFile = new MovieFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "RadarrTest" };
_namingConfig = NamingConfig.Default;
_namingConfig.RenameMovies = true;
Mocker.GetMock<INamingConfigService>()
.Setup(c => c.GetConfig()).Returns(_namingConfig);
Mocker.GetMock<IQualityDefinitionService>()
.Setup(v => v.Get(Moq.It.IsAny<Quality>()))
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
Mocker.GetMock<ICustomFormatService>()
.Setup(v => v.All())
.Returns(new List<CustomFormat>());
}
[Test]
public void should_not_recursively_include_current_filename()
{
_movieFile.RelativePath = "My Movie";
_namingConfig.StandardMovieFormat = "{Movie Title} {[Original Title]}";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("My Movie");
}
[Test]
public void should_include_original_title_if_not_current_file_name()
{
_movieFile.SceneName = "my.movie.2008";
_movieFile.RelativePath = "My Movie";
_namingConfig.StandardMovieFormat = "{Movie Title} {[Original Title]}";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("My Movie [my.movie.2008]");
}
[Test]
public void should_include_current_filename_if_not_renaming_files()
{
_movieFile.SceneName = "my.movie.2008";
_namingConfig.RenameMovies = false;
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("my.movie.2008");
}
[Test]
public void should_include_current_filename_if_not_including_multiple_naming_tokens()
{
_movieFile.RelativePath = "My Movie";
_namingConfig.StandardMovieFormat = "{Original Title}";
Subject.BuildFileName(_movie, _movieFile)
.Should().Be("My Movie");
}
}
}

View File

@@ -22,7 +22,6 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("enus")]
[TestCase("enusa")]
[TestCase("wo")]
[TestCase("ca-IT")]
[TestCase("fr-CA")]
public void unknown_or_invalid_code_should_return_null(string isoCode)
{

View File

@@ -1,3 +1,4 @@
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Languages;
@@ -146,6 +147,7 @@ namespace NzbDrone.Core.Test.ParserTests
}
[TestCase("Movie.Title.1994.Romanian.1080p.XviD-LOL")]
[TestCase("Movie.Title.1994.1080p.XviD.RoDubbed-LOL")]
public void should_parse_language_romanian(string postTitle)
{
var result = Parser.Parser.ParseMovieTitle(postTitle, true);
@@ -380,6 +382,26 @@ namespace NzbDrone.Core.Test.ParserTests
result.Languages.Should().BeEquivalentTo(Language.Latvian);
}
[TestCase("Movie.Title.2019.720p_Eng-Spa(Latino)_MovieClubMx")]
[TestCase("Movie.Title.1.WEB-DL.720p.Complete.Latino.YG")]
[TestCase("Movie.Title.1080p.WEB.H264.Latino.YG")]
[TestCase("Movie Title latino")]
[TestCase("Movie Title (Temporada 11 Completa) Audio Dual Ingles/Latino 1920x1080")]
[TestCase("Movie title 7x4 audio latino")]
public void should_parse_language_spanish_latino(string postTitle)
{
var result = LanguageParser.ParseLanguages(postTitle);
result.First().Id.Should().Be(Language.SpanishLatino.Id);
}
[TestCase("Movie.Title.1994.Catalan.1080p.XviD-LOL")]
public void should_parse_language_catalan(string postTitle)
{
var result = Parser.Parser.ParseMovieTitle(postTitle, true);
result.Languages.Should().BeEquivalentTo(Language.Catalan);
}
[TestCase("Movie.Title.en.sub")]
[TestCase("Movie Title.eng.sub")]
[TestCase("Movie.Title.eng.forced.sub")]

View File

@@ -215,6 +215,7 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Movie Name FRENCH BluRay 720p 2016 kjhlj", 2016)]
[TestCase("Der.Movie.German.Bluray.FuckYou.Pso.Why.cant.you.follow.scene.rules.1998", 1998)]
[TestCase("Movie Name (1897) [DVD].mp4", 1897)]
[TestCase("World Movie Z Movie [2023]", 2023)]
public void should_parse_movie_year(string postTitle, int year)
{
Parser.Parser.ParseMovieTitle(postTitle).Year.Should().Be(year);
@@ -254,6 +255,18 @@ namespace NzbDrone.Core.Test.ParserTests
parsed.Languages.Should().Contain(Language.German);
}
[TestCase("Movie.Title.2016.1080p.KORSUB.WEBRip.x264.AAC2.0-RADARR", "KORSUB")]
[TestCase("Movie.Title.2016.1080p.KORSUBS.WEBRip.x264.AAC2.0-RADARR", "KORSUBS")]
[TestCase("Movie Title 2017 HC 720p HDRiP DD5 1 x264-LEGi0N", "Generic Hardcoded Subs")]
[TestCase("Movie.Title.2017.720p.SUBBED.HDRip.V2.XViD-26k.avi", "Generic Hardcoded Subs")]
[TestCase("Movie.Title.2000.1080p.BlueRay.x264.DTS.RoSubbed-playHD", null)]
[TestCase("Movie Title! 2018 [Web][MKV][h264][480p][AAC 2.0][Softsubs]", null)]
[TestCase("Movie Title! 2019 [HorribleSubs][Web][MKV][h264][848x480][AAC 2.0][Softsubs(HorribleSubs)]", null)]
public void should_parse_hardcoded_subs(string postTitle, string sub)
{
Parser.Parser.ParseMovieTitle(postTitle).HardcodedSubs.Should().Be(sub);
}
[TestCase("That Italian Movie 2008 [tt1234567] 720p BluRay X264", "tt1234567")]
[TestCase("That Italian Movie 2008 [tt12345678] 720p BluRay X264", "tt12345678")]
public void should_parse_imdb_in_title(string postTitle, string imdb)

View File

@@ -1,28 +0,0 @@
using System.Collections.Generic;
using NUnit.Framework;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public abstract class AugmentMovieInfoFixture<TAugmenter> : CoreTest<TAugmenter>
where TAugmenter : class, IAugmentParsedMovieInfo
{
protected ParsedMovieInfo MovieInfo;
[SetUp]
public virtual void Setup()
{
MovieInfo = new ParsedMovieInfo
{
MovieTitles = new List<string> { "A Movie" },
Year = 1998,
SimpleReleaseTitle = "A Movie Title 1998 Bluray 1080p",
Quality = new QualityModel(Quality.Bluray1080p)
};
}
}
}

View File

@@ -1,23 +0,0 @@
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public class AugmentWithFileSizeFixture : AugmentMovieInfoFixture<AugmentWithFileSize>
{
[Test]
public void should_add_file_size()
{
var localMovie = new LocalMovie
{
Size = 1500
};
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, localMovie);
movieInfo.ExtraInfo["Size"].Should().BeEquivalentTo(1500);
}
}
}

View File

@@ -1,109 +0,0 @@
using System;
using System.Collections.Generic;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.History;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Rarbg;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public class AugmentWithHistoryFixture : AugmentMovieInfoFixture<AugmentWithHistory>
{
private AugmentWithHistory _customSubject { get; set; }
[SetUp]
public override void Setup()
{
base.Setup();
// Add multi indexer
GivenIndexerSettings(new RarbgSettings
{
MultiLanguages = new List<int>
{
(int)Language.English,
(int)Language.French,
}
});
}
protected new AugmentWithHistory Subject
{
get
{
if (_customSubject == null)
{
_customSubject = new AugmentWithHistory(new List<Lazy<IAugmentParsedMovieInfo>> { new (Mocker.Resolve<AugmentWithReleaseInfo>()) });
}
return _customSubject;
}
}
private void GivenIndexerSettings(IIndexerSettings indexerSettings)
{
Mocker.GetMock<IIndexerFactory>().Setup(f => f.Get(It.IsAny<int>())).Returns(new IndexerDefinition
{
Settings = indexerSettings
});
}
private MovieHistory HistoryWithData(params string[] data)
{
var dict = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
for (var i = 0; i < data.Length; i += 2)
{
dict.Add(data[i], data[i + 1]);
}
return new MovieHistory
{
Data = dict,
EventType = MovieHistoryEventType.Grabbed
};
}
[Test]
public void should_add_indexer_flags()
{
var history = HistoryWithData("IndexerFlags", (IndexerFlags.PTP_Approved | IndexerFlags.PTP_Golden).ToString());
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, history);
movieInfo.ExtraInfo["IndexerFlags"].Should().BeEquivalentTo(IndexerFlags.PTP_Golden | IndexerFlags.PTP_Approved);
}
[Test]
public void should_add_size()
{
var history = HistoryWithData("Size", 9663676416.ToString());
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, history);
movieInfo.ExtraInfo["Size"].Should().BeEquivalentTo(9663676416);
}
[Test]
public void should_use_settings_languages_when_necessary()
{
var history = HistoryWithData("IndexerId", 1.ToString());
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, history);
movieInfo.Languages.Should().BeEquivalentTo();
MovieInfo.SimpleReleaseTitle = "A Movie 1998 Bluray 1080p MULTI";
var multiInfo = Subject.AugmentMovieInfo(MovieInfo, history);
multiInfo.Languages.Should().BeEquivalentTo(Language.English, Language.French);
}
[Test]
public void should_not_use_settings_languages()
{
var unknownIndexer = HistoryWithData();
var unknownIndexerInfo = Subject.AugmentMovieInfo(MovieInfo, unknownIndexer);
unknownIndexerInfo.Languages.Should().BeEquivalentTo();
}
}
}

View File

@@ -1,90 +0,0 @@
// using FluentAssertions;
// using NUnit.Framework;
// using NzbDrone.Core.CustomFormats;
// using NzbDrone.Core.MediaFiles.MediaInfo;
// using NzbDrone.Core.Parser;
// using NzbDrone.Core.Parser.Augmenters;
// using NzbDrone.Core.Qualities;
// namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
// {
// [TestFixture]
// public class AugmentWithMediaInfoFixture : AugmentMovieInfoFixture<AugmentWithMediaInfo>
// {
// [TestCase(Resolution.R720p, Source.BLURAY, Resolution.R1080p)]
// [TestCase(Resolution.R1080p, Source.TV, Resolution.R720p)]
// public void should_correct_resolution(Resolution resolution, Source source, Resolution realResolution)
// {
// var quality = new QualityModel
// {
// Source = source,
// Resolution = resolution,
// };
// MovieInfo.Quality = quality;
// var realWidth = 480;
// switch (realResolution)
// {
// case Resolution.R720p:
// realWidth = 1280;
// break;
// case Resolution.R1080p:
// realWidth = 1920;
// break;
// case Resolution.R2160p:
// realWidth = 2160;
// break;
// }
// var mediaInfo = new MediaInfoModel
// {
// Width = realWidth
// };
// var movieInfo = Subject.AugmentMovieInfo(MovieInfo, mediaInfo);
// movieInfo.Quality.Resolution.Should().BeEquivalentTo(realResolution);
// movieInfo.Quality.QualityDetectionSource.Should().BeEquivalentTo(QualityDetectionSource.MediaInfo);
// }
// [TestCase(Resolution.R720P, Source.BLURAY, Resolution.R1080P, Modifier.BRDISK)]
// [TestCase(Resolution.R1080P, Source.BLURAY, Resolution.R720P, Modifier.REMUX)]
// [TestCase(Resolution.R480P, Source.BLURAY, Resolution.R720P)]
// [TestCase(Resolution.R720P, Source.DVD, Resolution.R480P)]
// public void should_not_correct_resolution(Resolution resolution, Source source, Resolution realResolution, Modifier modifier = Modifier.NONE)
// {
// var quality = new QualityModel
// {
// Source = source,
// Resolution = resolution,
// Modifier = modifier,
// };
// MovieInfo.Quality = quality;
// var realWidth = 480;
// switch (realResolution)
// {
// case Resolution.R720P:
// realWidth = 1280;
// break;
// case Resolution.R1080P:
// realWidth = 1920;
// break;
// case Resolution.R2160P:
// realWidth = 2160;
// break;
// }
// var mediaInfo = new MediaInfoModel
// {
// Width = realWidth
// };
// var movieInfo = Subject.AugmentMovieInfo(MovieInfo, mediaInfo);
// movieInfo.Quality.Resolution.Should().BeEquivalentTo(resolution);
// movieInfo.Quality.QualityDetectionSource.Should().BeEquivalentTo(QualityDetectionSource.Name);
// }
// }
// }

View File

@@ -1,29 +0,0 @@
using System;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public class AugmentWithOriginalLanguageFixture : AugmentMovieInfoFixture<AugmentWithOriginalLanguage>
{
[Test]
public void should_add_movie_original_language()
{
var releaseInfo = new ParsedMovieInfo();
var movie = new Movies.Movie
{
MovieMetadata = new Movies.MovieMetadata
{
OriginalLanguage = Language.English
}
};
var result = Subject.AugmentMovieInfo(releaseInfo, movie);
result.ExtraInfo.Should().ContainKey("OriginalLanguage");
result.ExtraInfo["OriginalLanguage"].Should().Be(Language.English);
}
}
}

View File

@@ -1,77 +0,0 @@
using System.Collections.Generic;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public class AugmentWithParsedMovieInfoFixture : AugmentMovieInfoFixture<AugmentWithParsedMovieInfo>
{
[Test]
public void should_add_edition_if_null()
{
var folderInfo = new ParsedMovieInfo
{
Edition = "Directors Cut"
};
var result = Subject.AugmentMovieInfo(MovieInfo, folderInfo);
result.Edition.Should().Be(folderInfo.Edition);
}
[Test]
public void should_preferr_longer_edition()
{
var folderInfo = new ParsedMovieInfo
{
Edition = "Super duper cut"
};
MovieInfo.Edition = "Rogue";
var result = Subject.AugmentMovieInfo(MovieInfo, folderInfo);
result.Edition.Should().Be(folderInfo.Edition);
MovieInfo.Edition = "Super duper awesome cut";
result = Subject.AugmentMovieInfo(MovieInfo, folderInfo);
result.Edition.Should().Be(MovieInfo.Edition);
}
[Test]
public void should_combine_languages()
{
var folderInfo = new ParsedMovieInfo
{
Languages = new List<Language> { Language.French }
};
MovieInfo.Languages = new List<Language> { Language.English };
var result = Subject.AugmentMovieInfo(MovieInfo, folderInfo);
result.Languages.Should().BeEquivalentTo(Language.English, Language.French);
}
[Test]
public void should_use_folder_release_group()
{
var folderInfo = new ParsedMovieInfo
{
ReleaseGroup = "AwesomeGroup"
};
MovieInfo.ReleaseGroup = "";
var result = Subject.AugmentMovieInfo(MovieInfo, folderInfo);
result.ReleaseGroup.Should().BeEquivalentTo(folderInfo.ReleaseGroup);
}
}
}

View File

@@ -1,82 +0,0 @@
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.Rarbg;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Parser.Augmenters;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests.AugmentersTests
{
[TestFixture]
public class AugmentWithReleaseInfoFixture : AugmentMovieInfoFixture<AugmentWithReleaseInfo>
{
private IndexerDefinition _indexerDefinition;
private ReleaseInfo ReleaseInfoWithLanguages(params Language[] languages)
{
_indexerDefinition = new IndexerDefinition
{
Settings = new RarbgSettings { MultiLanguages = languages.ToList().Select(l => (int)l) }
};
Mocker.GetMock<IIndexerFactory>()
.Setup(v => v.Get(1))
.Returns(_indexerDefinition);
return new ReleaseInfo
{
IndexerId = 1
};
}
[Test]
public void should_add_language_from_indexer()
{
var releaseInfo = ReleaseInfoWithLanguages(Language.English, Language.French);
MovieInfo.SimpleReleaseTitle = "A Movie Title 1998 Bluray 1080p MULTI";
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, releaseInfo);
movieInfo.Languages.Count.Should().Be(2);
movieInfo.Languages.Should().BeEquivalentTo(Language.English, Language.French);
}
[Test]
public void should_add_size_info()
{
var releaseInfo = new ReleaseInfo
{
Size = 1500
};
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, releaseInfo);
movieInfo.ExtraInfo["Size"].Should().BeEquivalentTo(1500);
}
[Test]
public void should_not_add_size_when_already_present()
{
var releaseInfo = new ReleaseInfo
{
Size = 1500
};
MovieInfo.ExtraInfo["Size"] = 1600;
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, releaseInfo);
movieInfo.ExtraInfo["Size"].Should().BeEquivalentTo(1600);
}
[Test]
public void should_add_indexer_flags()
{
var releaseInfo = new ReleaseInfo
{
IndexerFlags = IndexerFlags.PTP_Approved | IndexerFlags.PTP_Golden
};
var movieInfo = Subject.AugmentMovieInfo(MovieInfo, releaseInfo);
movieInfo.ExtraInfo["IndexerFlags"].Should().BeEquivalentTo(IndexerFlags.PTP_Approved | IndexerFlags.PTP_Golden);
}
}
}

View File

@@ -194,20 +194,5 @@ namespace NzbDrone.Core.Test.ParserTests.ParsingServiceTests
Subject.Map(_umlautInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
Subject.Map(_umlautAltInfo, "", _movieSearchCriteria).Movie.Should().Be(_movieSearchCriteria.Movie);
}
[Test]
public void should_convert_original()
{
Subject.Map(_multiLanguageInfo, "", _movieSearchCriteria).RemoteMovie.ParsedMovieInfo.Languages.Should().Contain(Language.English);
Subject.Map(_multiLanguageInfo, "", _movieSearchCriteria).RemoteMovie.ParsedMovieInfo.Languages.Should().Contain(Language.French);
}
[Test]
public void should_remove_original_as_already_exists()
{
Subject.Map(_multiLanguageWithOriginalInfo, "", _movieSearchCriteria).RemoteMovie.ParsedMovieInfo.Languages.Should().Contain(Language.English);
Subject.Map(_multiLanguageWithOriginalInfo, "", _movieSearchCriteria).RemoteMovie.ParsedMovieInfo.Languages.Should().Contain(Language.French);
Subject.Map(_multiLanguageWithOriginalInfo, "", _movieSearchCriteria).RemoteMovie.ParsedMovieInfo.Languages.Should().NotContain(Language.Original);
}
}
}

View File

@@ -452,18 +452,6 @@ namespace NzbDrone.Core.Test.ParserTests
result.ResolutionDetectionSource.Should().Be(QualityDetectionSource.Name);
}
[TestCase("Movie.Title.2016.1080p.KORSUB.WEBRip.x264.AAC2.0-RADARR", "KORSUB")]
[TestCase("Movie.Title.2016.1080p.KORSUBS.WEBRip.x264.AAC2.0-RADARR", "KORSUBS")]
[TestCase("Movie Title 2017 HC 720p HDRiP DD5 1 x264-LEGi0N", "Generic Hardcoded Subs")]
[TestCase("Movie.Title.2017.720p.SUBBED.HDRip.V2.XViD-26k.avi", "Generic Hardcoded Subs")]
[TestCase("Movie.Title.2000.1080p.BlueRay.x264.DTS.RoSubbed-playHD", null)]
[TestCase("Movie Title! 2018 [Web][MKV][h264][480p][AAC 2.0][Softsubs]", null)]
[TestCase("Movie Title! 2019 [HorribleSubs][Web][MKV][h264][848x480][AAC 2.0][Softsubs(HorribleSubs)]", null)]
public void should_parse_hardcoded_subs(string postTitle, string sub)
{
QualityParser.ParseQuality(postTitle).HardcodedSubs.Should().Be(sub);
}
[TestCase("Movie Title 2018 REPACK 720p x264 aAF", true)]
[TestCase("Movie.Title.2018.REPACK.720p.x264-aAF", true)]
[TestCase("Movie.Title.2018.PROPER.720p.x264-aAF", false)]

View File

@@ -22,7 +22,7 @@ namespace NzbDrone.Core.Test.Profiles
{
Items = Qualities.QualityFixture.GetDefaultQualities(Quality.Bluray1080p, Quality.DVD, Quality.HDTV720p),
MinFormatScore = 0,
FormatItems = CustomFormatsFixture.GetDefaultFormatItems(),
FormatItems = CustomFormatsTestHelpers.GetDefaultFormatItems(),
Cutoff = Quality.Bluray1080p.Id,
Name = "TestProfile"
};

View File

@@ -170,9 +170,9 @@ namespace NzbDrone.Core.Test.Profiles
var customFormat1 = new CustomFormat("My Format 1", new LanguageSpecification { Value = (int)Language.English }) { Id = 1 };
var customFormat2 = new CustomFormat("My Format 2", new LanguageSpecification { Value = (int)Language.French }) { Id = 2 };
CustomFormatsFixture.GivenCustomFormats(customFormat1, customFormat2);
CustomFormatsTestHelpers.GivenCustomFormats(customFormat1, customFormat2);
profile.FormatItems = CustomFormatsFixture.GetSampleFormatItems(customFormat2.Name);
profile.FormatItems = CustomFormatsTestHelpers.GetSampleFormatItems(customFormat2.Name);
Mocker.GetMock<IProfileRepository>()
.Setup(s => s.Get(It.IsAny<int>()))

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.Movies;
@@ -32,7 +33,14 @@ namespace NzbDrone.Core.Blocklisting
public List<Blocklist> BlocklistedByMovie(int movieId)
{
return Query(x => x.MovieId == movieId);
var builder = Builder().Join<Blocklist, Movie>((h, a) => h.MovieId == a.Id)
.Where<Blocklist>(h => h.MovieId == movieId);
return _database.QueryJoined<Blocklist, Movie>(builder, (blocklist, movie) =>
{
blocklist.Movie = movie;
return blocklist;
}).OrderByDescending(h => h.Date).ToList();
}
public void DeleteForMovies(List<int> movieIds)

View File

@@ -26,6 +26,7 @@ namespace NzbDrone.Core.Configuration
XDocument LoadConfigFile();
Dictionary<string, object> GetConfigDictionary();
void SaveConfigDictionary(Dictionary<string, object> configValues);
void EnsureDefaultConfigFile();
string BindAddress { get; }
int Port { get; }
@@ -253,7 +254,7 @@ namespace NzbDrone.Core.Configuration
public T GetValueEnum<T>(string key, T defaultValue, bool persist = true)
{
return (T)Enum.Parse(typeof(T), GetValue(key, defaultValue), persist);
return (T)Enum.Parse(typeof(T), GetValue(key, defaultValue, persist), true);
}
public string GetValue(string key, object defaultValue, bool persist = true)
@@ -312,7 +313,7 @@ namespace NzbDrone.Core.Configuration
SetValue(key, value.ToString().ToLower());
}
private void EnsureDefaultConfigFile()
public void EnsureDefaultConfigFile()
{
if (!File.Exists(_configFile))
{

View File

@@ -14,28 +14,134 @@ namespace NzbDrone.Core.CustomFormats
{
public interface ICustomFormatCalculationService
{
List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo, Movie movie);
List<CustomFormat> ParseCustomFormat(RemoteMovie remoteMovie, long size);
List<CustomFormat> ParseCustomFormat(MovieFile movieFile, Movie movie);
List<CustomFormat> ParseCustomFormat(MovieFile movieFile);
List<CustomFormat> ParseCustomFormat(Blocklist blocklist);
List<CustomFormat> ParseCustomFormat(MovieHistory history);
List<CustomFormat> ParseCustomFormat(Blocklist blocklist, Movie movie);
List<CustomFormat> ParseCustomFormat(MovieHistory history, Movie movie);
List<CustomFormat> ParseCustomFormat(LocalMovie localMovie);
}
public class CustomFormatCalculationService : ICustomFormatCalculationService
{
private readonly ICustomFormatService _formatService;
private readonly IParsingService _parsingService;
private readonly IMovieService _movieService;
public CustomFormatCalculationService(ICustomFormatService formatService,
IParsingService parsingService,
IMovieService movieService)
public CustomFormatCalculationService(ICustomFormatService formatService)
{
_formatService = formatService;
_parsingService = parsingService;
_movieService = movieService;
}
public static List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo, List<CustomFormat> allCustomFormats)
public List<CustomFormat> ParseCustomFormat(RemoteMovie remoteMovie, long size)
{
var input = new CustomFormatInput
{
MovieInfo = remoteMovie.ParsedMovieInfo,
Movie = remoteMovie.Movie,
Size = size,
Languages = remoteMovie.Languages,
IndexerFlags = remoteMovie.Release?.IndexerFlags ?? 0
};
return ParseCustomFormat(input);
}
public List<CustomFormat> ParseCustomFormat(MovieFile movieFile, Movie movie)
{
return ParseCustomFormat(movieFile, movie, _formatService.All());
}
public List<CustomFormat> ParseCustomFormat(MovieFile movieFile)
{
return ParseCustomFormat(movieFile, movieFile.Movie, _formatService.All());
}
public List<CustomFormat> ParseCustomFormat(Blocklist blocklist, Movie movie)
{
var parsed = Parser.Parser.ParseMovieTitle(blocklist.SourceTitle);
var movieInfo = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(),
ReleaseTitle = parsed?.ReleaseTitle ?? blocklist.SourceTitle,
Edition = parsed?.Edition,
Quality = blocklist.Quality,
Languages = blocklist.Languages,
ReleaseGroup = parsed?.ReleaseGroup
};
var input = new CustomFormatInput
{
MovieInfo = movieInfo,
Movie = movie,
Size = blocklist.Size ?? 0,
IndexerFlags = blocklist.IndexerFlags,
Languages = blocklist.Languages
};
return ParseCustomFormat(input);
}
public List<CustomFormat> ParseCustomFormat(MovieHistory history, Movie movie)
{
var parsed = Parser.Parser.ParseMovieTitle(history.SourceTitle);
long.TryParse(history.Data.GetValueOrDefault("size"), out var size);
Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags flags);
var movieInfo = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(),
ReleaseTitle = parsed?.ReleaseTitle ?? history.SourceTitle,
Edition = parsed?.Edition,
Quality = history.Quality,
Languages = history.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
};
var input = new CustomFormatInput
{
MovieInfo = movieInfo,
Movie = movie,
Size = size,
IndexerFlags = flags,
Languages = history.Languages
};
return ParseCustomFormat(input);
}
public List<CustomFormat> ParseCustomFormat(LocalMovie localMovie)
{
var episodeInfo = new ParsedMovieInfo
{
MovieTitles = new List<string>() { localMovie.Movie.Title },
SimpleReleaseTitle = localMovie.SceneName?.SimplifyReleaseTitle(),
ReleaseTitle = localMovie.SceneName,
Quality = localMovie.Quality,
Edition = localMovie.Edition,
Languages = localMovie.Languages,
ReleaseGroup = localMovie.ReleaseGroup
};
var input = new CustomFormatInput
{
MovieInfo = episodeInfo,
Movie = localMovie.Movie,
Size = localMovie.Size,
Languages = localMovie.Languages
};
return ParseCustomFormat(input);
}
private List<CustomFormat> ParseCustomFormat(CustomFormatInput input)
{
return ParseCustomFormat(input, _formatService.All());
}
private static List<CustomFormat> ParseCustomFormat(CustomFormatInput input, List<CustomFormat> allCustomFormats)
{
var matches = new List<CustomFormat>();
@@ -45,7 +151,7 @@ namespace NzbDrone.Core.CustomFormats
.GroupBy(t => t.GetType())
.Select(g => new SpecificationMatchesGroup
{
Matches = g.ToDictionary(t => t, t => t.IsSatisfiedBy(movieInfo))
Matches = g.ToDictionary(t => t, t => t.IsSatisfiedBy(input))
})
.ToList();
@@ -58,7 +164,7 @@ namespace NzbDrone.Core.CustomFormats
return matches;
}
public static List<CustomFormat> ParseCustomFormat(MovieFile movieFile, List<CustomFormat> allCustomFormats)
private static List<CustomFormat> ParseCustomFormat(MovieFile movieFile, Movie movie, List<CustomFormat> allCustomFormats)
{
var sceneName = string.Empty;
if (movieFile.SceneName.IsNotNullOrWhiteSpace())
@@ -74,90 +180,29 @@ namespace NzbDrone.Core.CustomFormats
sceneName = Path.GetFileName(movieFile.RelativePath);
}
var info = new ParsedMovieInfo
var movieInfo = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movieFile.Movie.MovieMetadata.Value.Title },
MovieTitles = new List<string>() { movie.Title },
SimpleReleaseTitle = sceneName.SimplifyReleaseTitle(),
Quality = movieFile.Quality,
Languages = movieFile.Languages,
ReleaseGroup = movieFile.ReleaseGroup,
Edition = movieFile.Edition,
Year = movieFile.Movie.MovieMetadata.Value.Year,
ImdbId = movieFile.Movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", movieFile.IndexerFlags },
{ "Size", movieFile.Size },
{ "Filename", Path.GetFileName(movieFile.RelativePath) },
{ "OriginalLanguage", movieFile.Movie.MovieMetadata.Value.OriginalLanguage }
}
ImdbId = movieFile.Movie.MovieMetadata.Value.ImdbId
};
return ParseCustomFormat(info, allCustomFormats);
}
public List<CustomFormat> ParseCustomFormat(ParsedMovieInfo movieInfo, Movie movie)
{
movieInfo = _parsingService.EnhanceMovieInfo(movieInfo, new List<object> { movie }) ?? movieInfo;
return ParseCustomFormat(movieInfo, _formatService.All());
}
public List<CustomFormat> ParseCustomFormat(MovieFile movieFile)
{
return ParseCustomFormat(movieFile, _formatService.All());
}
public List<CustomFormat> ParseCustomFormat(Blocklist blocklist)
{
var movie = _movieService.GetMovie(blocklist.MovieId);
var parsed = _parsingService.ParseMovieInfo(blocklist.SourceTitle, null);
var info = new ParsedMovieInfo
var input = new CustomFormatInput
{
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? blocklist.SourceTitle.SimplifyReleaseTitle(),
Quality = blocklist.Quality,
Languages = blocklist.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", blocklist.IndexerFlags },
{ "Size", blocklist.Size }
}
MovieInfo = movieInfo,
Movie = movie,
Size = movieFile.Size,
IndexerFlags = movieFile.IndexerFlags,
Languages = movieFile.Languages,
Filename = Path.GetFileName(movieFile.RelativePath)
};
return ParseCustomFormat(info, movie);
}
public List<CustomFormat> ParseCustomFormat(MovieHistory history)
{
var movie = _movieService.GetMovie(history.MovieId);
var parsed = _parsingService.ParseMovieInfo(history.SourceTitle, null);
Enum.TryParse(history.Data.GetValueOrDefault("indexerFlags"), true, out IndexerFlags flags);
long.TryParse(history.Data.GetValueOrDefault("size"), out var size);
var info = new ParsedMovieInfo
{
MovieTitles = new List<string>() { movie.MovieMetadata.Value.Title },
SimpleReleaseTitle = parsed?.SimpleReleaseTitle ?? history.SourceTitle.SimplifyReleaseTitle(),
Quality = history.Quality,
Languages = history.Languages,
ReleaseGroup = parsed?.ReleaseGroup,
Edition = parsed?.Edition,
Year = movie.MovieMetadata.Value.Year,
ImdbId = movie.MovieMetadata.Value.ImdbId,
ExtraInfo = new Dictionary<string, object>
{
{ "IndexerFlags", flags },
{ "Size", size }
}
};
return ParseCustomFormat(info, movie);
return ParseCustomFormat(input, allCustomFormats);
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Collections.Generic;
using NzbDrone.Core.Languages;
using NzbDrone.Core.Movies;
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.CustomFormats
{
public class CustomFormatInput
{
public ParsedMovieInfo MovieInfo { get; set; }
public Movie Movie { get; set; }
public long Size { get; set; }
public IndexerFlags IndexerFlags { get; set; }
public List<Language> Languages { get; set; }
public string Filename { get; set; }
public CustomFormatInput()
{
Languages = new List<Language>();
}
}
}

View File

@@ -21,9 +21,9 @@ namespace NzbDrone.Core.CustomFormats
public abstract NzbDroneValidationResult Validate();
public bool IsSatisfiedBy(ParsedMovieInfo movieInfo)
public bool IsSatisfiedBy(CustomFormatInput input)
{
var match = IsSatisfiedByWithoutNegate(movieInfo);
var match = IsSatisfiedByWithoutNegate(input);
if (Negate)
{
match = !match;
@@ -32,6 +32,6 @@ namespace NzbDrone.Core.CustomFormats
return match;
}
protected abstract bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo);
protected abstract bool IsSatisfiedByWithoutNegate(CustomFormatInput input);
}
}

View File

@@ -1,5 +1,3 @@
using NzbDrone.Core.Parser.Model;
namespace NzbDrone.Core.CustomFormats
{
public class EditionSpecification : RegexSpecificationBase
@@ -8,9 +6,9 @@ namespace NzbDrone.Core.CustomFormats
public override string ImplementationName => "Edition";
public override string InfoLink => "https://wiki.servarr.com/radarr/settings#custom-formats-2";
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return MatchString(movieInfo.Edition);
return MatchString(input.MovieInfo.Edition);
}
}
}

View File

@@ -15,6 +15,6 @@ namespace NzbDrone.Core.CustomFormats
NzbDroneValidationResult Validate();
ICustomFormatSpecification Clone();
bool IsSatisfiedBy(ParsedMovieInfo movieInfo);
bool IsSatisfiedBy(CustomFormatInput input);
}
}

View File

@@ -32,10 +32,9 @@ namespace NzbDrone.Core.CustomFormats
[FieldDefinition(1, Label = "Flag", Type = FieldType.Select, SelectOptions = typeof(IndexerFlags))]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
var flags = movieInfo?.ExtraInfo?.GetValueOrDefault("IndexerFlags") as IndexerFlags?;
return flags?.HasFlag((IndexerFlags)Value) == true;
return input.IndexerFlags.HasFlag((IndexerFlags)Value) == true;
}
public override NzbDroneValidationResult Validate()

View File

@@ -32,12 +32,13 @@ namespace NzbDrone.Core.CustomFormats
[FieldDefinition(1, Label = "Language", Type = FieldType.Select, SelectOptions = typeof(LanguageFieldConverter))]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
var comparedLanguage = movieInfo != null && Value == Language.Original.Id && movieInfo.ExtraInfo.ContainsKey("OriginalLanguage")
? (Language)movieInfo.ExtraInfo["OriginalLanguage"]
var comparedLanguage = input.MovieInfo != null && input.Movie != null && Value == Language.Original.Id && input.Movie.MovieMetadata.Value.OriginalLanguage != Language.Unknown
? input.Movie.MovieMetadata.Value.OriginalLanguage
: (Language)Value;
return movieInfo?.Languages?.Contains(comparedLanguage) ?? false;
return input?.Languages?.Contains(comparedLanguage) ?? false;
}
public override NzbDroneValidationResult Validate()

View File

@@ -32,9 +32,9 @@ namespace NzbDrone.Core.CustomFormats
[FieldDefinition(1, Label = "Quality Modifier", Type = FieldType.Select, SelectOptions = typeof(Modifier))]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return (movieInfo?.Quality?.Quality?.Modifier ?? (int)Modifier.NONE) == (Modifier)Value;
return (input.MovieInfo?.Quality?.Quality?.Modifier ?? (int)Modifier.NONE) == (Modifier)Value;
}
public override NzbDroneValidationResult Validate()

View File

@@ -8,9 +8,9 @@ namespace NzbDrone.Core.CustomFormats
public override string ImplementationName => "Release Group";
public override string InfoLink => "https://wiki.servarr.com/radarr/settings#custom-formats-2";
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return MatchString(movieInfo?.ReleaseGroup);
return MatchString(input.MovieInfo?.ReleaseGroup);
}
}
}

View File

@@ -9,11 +9,9 @@ namespace NzbDrone.Core.CustomFormats
public override string ImplementationName => "Release Title";
public override string InfoLink => "https://wiki.servarr.com/radarr/settings#custom-formats-2";
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
var filename = (string)movieInfo?.ExtraInfo?.GetValueOrDefault("Filename");
return MatchString(movieInfo?.SimpleReleaseTitle) || MatchString(filename);
return MatchString(input.MovieInfo?.SimpleReleaseTitle) || MatchString(input.Filename);
}
}
}

View File

@@ -24,9 +24,9 @@ namespace NzbDrone.Core.CustomFormats
[FieldDefinition(1, Label = "Resolution", Type = FieldType.Select, SelectOptions = typeof(Resolution))]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return (movieInfo?.Quality?.Quality?.Resolution ?? (int)Resolution.Unknown) == Value;
return (input.MovieInfo?.Quality?.Quality?.Resolution ?? (int)Resolution.Unknown) == Value;
}
public override NzbDroneValidationResult Validate()

View File

@@ -28,9 +28,9 @@ namespace NzbDrone.Core.CustomFormats
[FieldDefinition(1, Label = "Maximum Size", HelpText = "Release must be less than or equal to this size", Unit = "GB", Type = FieldType.Number)]
public double Max { get; set; }
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
var size = (movieInfo?.ExtraInfo?.GetValueOrDefault("Size", 0.0) as long?) ?? 0;
var size = input.Size;
return size > Min.Gigabytes() && size <= Max.Gigabytes();
}

View File

@@ -24,9 +24,9 @@ namespace NzbDrone.Core.CustomFormats
[FieldDefinition(1, Label = "Source", Type = FieldType.Select, SelectOptions = typeof(Source))]
public int Value { get; set; }
protected override bool IsSatisfiedByWithoutNegate(ParsedMovieInfo movieInfo)
protected override bool IsSatisfiedByWithoutNegate(CustomFormatInput input)
{
return (movieInfo?.Quality?.Quality?.Source ?? (int)Source.UNKNOWN) == (Source)Value;
return (input.MovieInfo?.Quality?.Quality?.Source ?? (int)Source.UNKNOWN) == (Source)Value;
}
public override NzbDroneValidationResult Validate()

View File

@@ -627,13 +627,13 @@ namespace NzbDrone.Core.Datastore.Migration
try
{
if (audioChannelPositions.Contains("+"))
if (audioChannelPositions.Contains('+'))
{
return audioChannelPositions.Split('+')
.Sum(s => decimal.Parse(s.Trim(), CultureInfo.InvariantCulture));
}
if (audioChannelPositions.Contains("/"))
if (audioChannelPositions.Contains('/'))
{
var channelStringList = Regex.Replace(audioChannelPositions,
@"^\d+\sobjects",

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Data;
using System.Text;
@@ -250,7 +250,7 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
}
Index = end + 1;
identifier.Append(Buffer.Substring(start, end - start));
identifier.Append(Buffer.AsSpan(start, end - start));
if (Buffer[Index] != escape)
{

View File

@@ -15,9 +15,9 @@ namespace NzbDrone.Core.Datastore
private const DbType EnumerableMultiParameter = (DbType)(-1);
private readonly string _paramNamePrefix;
private readonly bool _requireConcreteValue = false;
private int _paramCount = 0;
private bool _gotConcreteValue = false;
private readonly bool _requireConcreteValue;
private int _paramCount;
private bool _gotConcreteValue;
public WhereBuilderPostgres(Expression filter, bool requireConcreteValue, int seq)
{

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