1
0
mirror of https://github.com/Radarr/Radarr.git synced 2026-04-18 21:35:51 -04:00

Compare commits

..

184 Commits

Author SHA1 Message Date
Leonardo Galli fc805e5078 Fixed: Refresh movie failing. 2017-08-27 18:55:55 +02:00
Leonardo Galli ba531fff4d Added: Ability to force download movies that could not be mapped correctly. This also shares these mappings with other users, so everyone can profit :)
(This is just for the automatic changelog, hacky I know)
2017-08-27 18:12:09 +02:00
Leonardo Galli 1d7ce68431 Fixed: Refresh movie failing for most movies. (Fixes #2007)
Fixed: Invisible download button if no release name was found.
2017-08-27 18:05:28 +02:00
Leonardo Galli 09d51dca0f Fixed: A few issues with the new alternative titles feature. (#2008) (Fixes #1919, #1927 and #1917)
Added: Ability to force download movies that could not be mapped correctly. This also shares these mappings with other users, so everyone can profit :)
2017-08-27 16:42:11 +02:00
James White efe49ef3c4 @cosmetic Make file name match naming format (#1997) 2017-08-25 08:37:24 +02:00
Leonardo Galli a5823bb15f Fixed: A lot of small ui errors (e.g. More not showing) (Revert of #1959) 2017-08-24 07:57:31 +02:00
James White 38af8edd59 Fixed: Adjust Sonarr references to Radarr (#1977) 2017-08-21 21:48:45 +02:00
Leonardo Galli 685c5daf36 Fixed: Rename movie not working (#1970) (Fixes #1908) 2017-08-20 22:12:02 +02:00
Leonardo Galli 4d5a5ed2c1 Merge remote-tracking branch 'origin/develop' into develop 2017-08-20 20:13:48 +02:00
Leonardo Galli d44de777c1 Fixed: Error with CP Import when no info is present. Fixes #1792 2017-08-20 20:13:42 +02:00
James White dc2740aeb7 Added: Display breakpoint name in browser window in debug mode (#1968) 2017-08-20 20:00:37 +02:00
Leonardo Galli fb53fc68a9 Added: Ability to delete multiple movies at once via the movie editor. 2017-08-20 18:58:29 +02:00
Tom 8de87bb516 Fixed: Movie files & folders will actually get deleted now (#1966) (Fixes #694) 2017-08-20 14:40:02 +02:00
James White 0c8e264668 Fixed: Bulk UI cleanup, fixes and consistency improvements (#1959) 2017-08-20 14:38:24 +02:00
MangaValk 4d8a270170 Fixed: Parser error when using (year) name folder (#1956) (Fixes #1951) 2017-08-19 00:24:41 +02:00
hotio f184fc2827 @cosmetic Indicate proper release types for docker image (#1953) 2017-08-17 19:24:39 +02:00
hotio 4e48e6ea21 @cosmetic Update appveyor builds url to exclude pull requests (#1946) 2017-08-15 23:23:38 +02:00
Leonardo Galli b1e75ffc57 Merge remote-tracking branch 'origin/develop' into develop 2017-08-15 23:22:43 +02:00
Leonardo Galli 285ffb19d8 Fixed: Non-Freeleech torrents showing as freeleech for AHD. 2017-08-15 23:22:00 +02:00
hotio aea7a3f48f @cosmetic Update docker nightly image reference (#1945) 2017-08-15 23:07:34 +02:00
James White edbf1cb4e4 Fixed: Missing icon preventing detailed explanation validation errors explanations from appearing. (#1944) 2017-08-15 22:54:59 +02:00
Leonardo Galli 2154c48304 @cosmetic Removed Tests from AppVeyor 2017-08-15 20:23:02 +02:00
James White 7a95f040c9 Added: Deprecation warning about Drone Factory to front end (#1938) 2017-08-15 20:22:17 +02:00
James White cc1966230a Added: Package-lock.json for npm 5 (#1939) 2017-08-15 20:21:59 +02:00
James White e97fe7b3a7 Fixed: Mask-icon and other resources when UrlBase is in use (#1933) 2017-08-13 22:56:56 +02:00
James White 6500edbd14 Fixed: Slack/Mattermost notifications improvements from Sonarr (#1930) 2017-08-13 19:42:00 +02:00
James White e155585198 Fixed: fontawesome path (Icons disappearing) (#1929) 2017-08-13 14:18:54 +02:00
James White d9da32173f Fixed: Charset and meta in index.html and login.html (#1926) 2017-08-13 12:57:10 +02:00
Rotem 9db46ba154 Fixed: Removed hebrew ISO, since english movies are still in english. (#1922) 2017-08-13 12:55:25 +02:00
James White eff6e33a0b Fixed: Adjust column sizes relative to size of dropdown values (#1923) 2017-08-13 12:54:44 +02:00
James White 724097d276 Updated FontAwesome to 4.7.0 (#1928) 2017-08-13 12:54:16 +02:00
James White 7a06ead806 Fixed: Additional jshint warnings (#1921) 2017-08-12 17:11:34 +02:00
James White d773da60e8 Fixed: Minor issues on MoreInfoViewTemplate.hbs (#1916) 2017-08-12 15:16:31 +02:00
James White 1f7b03d321 Fixed: gulp jshint warnings (#1873) 2017-08-12 15:16:12 +02:00
James White a07ef20410 Fixed: Replace GitHub wiki references to Radarr's wiki URL (#1914) 2017-08-12 15:15:23 +02:00
Rotem 7c4c6ccd5c Added: Hebrew language (#1909) 2017-08-12 00:48:57 +02:00
James White c754edc4b8 Fixed: Hanging form-group div (#1911) 2017-08-12 00:29:31 +02:00
Mike 7f3ab36c4f New: Run tests through powershell. (#1903) 2017-08-10 20:11:12 +02:00
Leonardo Galli 17387c8b50 Fixed: Migration failing and thus making Radarr unable to start. 2017-08-10 18:51:05 +02:00
Leonardo Galli 0d40ed7ec0 Added: Alternative Titles are now also pulled from mappings.radarr.video.
Added: A secondary year will also be pulled from mappings.radarr.video.
Added: An option to force download a movie with wrong year / title. Radarr then adds the year / title to mappings.radarr.video.
2017-08-09 22:18:04 +02:00
Leonardo Galli cfcb66fba1 Changed: Alternative Titles were reworked greatly. This should speed up RSS Sync massively, especially for large libraries (up to 4x). 2017-08-09 22:14:01 +02:00
James White 8927e7c2c6 Fixed: Task name of PreDB Sync task (#1875) 2017-08-06 17:47:23 +02:00
Qstick 4e9a931537 Fixed: Check that Quality Profile is not in use before deleting it. 2017-08-06 12:10:17 +02:00
James White 17feedaf53 Fixed: Category not setting with qBitTorrent 3.3.14 and other api errors. (upstream from Sonarr) 2017-08-06 12:09:16 +02:00
Leonardo Galli b06108fb45 Fixed: Older movies (released more than 30 days ago) are now not refreshed as often anymore (every 30 days) 2017-07-28 16:59:06 +02:00
Leonardo Galli 67dd498576 Fixed: (Hopefully) Bug where movie file was not correctly linked to movie. 2017-07-28 16:57:26 +02:00
Leonardo Galli 3fb356ddb6 Fixed: No API Key required with SignalR connections. 2017-07-26 23:24:28 +02:00
Leonardo Galli 605b8f9645 Fixed: Guard agains null reference exception with newznab capabilities. 2017-07-26 23:23:36 +02:00
Marc Runkel 668ef336fb Fixed: Update Info.plist to avoid conflict with Sonarr (#1783) 2017-07-16 14:09:03 +01:00
Richard Schwab b82f2376a7 Fixed: Relax SingleInstancePolicy when using a custom data directory Fixes #1765 (#1782) 2017-07-16 14:08:16 +01:00
Leonardo Galli 964c18b236 Fixed: Lists are fetched much more efficiently. (Up to 40x loading time improvement with large lists!) 2017-07-08 16:13:28 +02:00
Taloth Saldono fb4f510909 Revert "Fixed: Support for Mono 5.x with the newer BoringTLS provider."
This reverts commit 5b722a3a48.
2017-07-06 21:45:37 +02:00
Taloth Saldono 5b722a3a48 Fixed: Support for Mono 5.x with the newer BoringTLS provider. 2017-07-06 21:43:34 +02:00
Sandro Stikić 0892f20298 Fixed: Old Plex ValidationFailure message (#1770) 2017-07-06 18:48:46 +02:00
Leonardo Galli ac5732536d Fixed: BDRemux not recognized as such and BDRips without resolution recognized as DVD. Fixes #1755 2017-07-01 14:01:38 +02:00
Leonardo Galli 1f4c2ad946 Fixed: A as part of an acronym being removed from clean title. Fixes #1747 2017-07-01 11:01:48 +02:00
Leonardo Galli 7712aa62da Fixed: Folder in List settings appearing blank in some browsers. Fixes #1711 2017-06-27 12:53:50 +02:00
Leonardo Galli 58b9c9d3d1 Fixed: Minimum Seeders not saving for Torznab indexer. Fixes #1736 2017-06-27 12:36:24 +02:00
Leonardo Galli b2115e2066 Removed most of changelog. Generate changelog using gitchangelog v0.2.0.18..HEAD. @cosmetic 2017-06-20 14:29:32 +02:00
Leonardo Galli 4e4873271b Added Changelog, just for fun :D @cosmetic 2017-06-20 14:21:19 +02:00
Leonardo Galli f2e5d9e996 Updated: Radarr API url now points to new v2 version. 2017-06-20 10:23:26 +02:00
Leonardo Galli bae3a48aa1 Changed Name of Radarr Lists 2017-06-19 15:22:03 +02:00
Leonardo Galli 6d033c57f4 Added: More detailed descriptions why a movie was not able to be mapped. (#1696)
Added: Option to make mapping more lenient. This should practically allow all movies to be correctly mapped. Though it also opens the path for movies being wrongly mapped! (So it is a toggable option)

Added: Improved edition parsing. Now almost all releases should have the correct edition, even ones with no year, etc.
2017-06-18 23:12:14 +02:00
Leonardo Galli d6cf53e12c Added: Options to make parsing more lenient. (Adds support for some german and french releasegroups) (#1692)
Fixes #1676. Fixes #1632.
2017-06-17 15:02:58 +02:00
Leonardo Galli 5238b78813 Merge remote-tracking branch 'origin/develop' into develop 2017-06-13 16:10:17 +02:00
Leonardo Galli 705b233819 Fix migration.
Fixes #1678
2017-06-13 16:09:12 +02:00
Mitchell Cash 295536ae30 Updated: Bootstrap Tags Input (#1674) 2017-06-13 13:15:43 +02:00
Leonardo Galli 42c980c905 Merge remote-tracking branch 'origin/develop' into develop 2017-06-13 13:09:09 +02:00
Leonardo Galli 0a71aac56c Fixed: Urls missing from multiple indexers after latest nightly update. 2017-06-13 13:09:02 +02:00
Mitchell Cash c312ffd7db Fixed: Redirect calls missing URL Base (#1668) 2017-06-13 08:42:49 +02:00
Mitchell Cash 5c5f06a92c Fixed: Twitter oAuth callback URL (#1669) 2017-06-13 08:42:07 +02:00
Mitchell Cash 3eab8248e6 Fixed: Error when processing manual import decisions (#1670) 2017-06-13 08:40:51 +02:00
Mitchell Cash c33d9727a0 Added: Include css files in minification (#1672) 2017-06-13 08:39:42 +02:00
Mitchell Cash ca6784f7b5 Added: Upgrade to Bootstrap 3.3.7 (#1673) 2017-06-13 08:38:39 +02:00
Leonardo Galli ca00d0d6cc Create README.md 2017-06-12 19:17:56 +02:00
Leonardo Galli 756fc7556c Add license 2017-06-12 19:11:11 +02:00
Leonardo Galli 9f4ce50dd6 Added: Allow minimum seeders to be set on a per indexer basis. Pulled from Sonarr Upstream (#1624) 2017-06-12 14:47:05 +02:00
Leonardo Galli a460e89a8d Merge remote-tracking branch 'origin/develop' into develop 2017-06-12 14:10:18 +02:00
Leonardo Galli edda8786ad Minimum availability is now working similarely to profile when adding a movie. 2017-06-12 14:10:07 +02:00
Mitchell Cash b1c5dd8167 Changed: Remove redundant IE meta tag as we use http header instead (#1655) 2017-06-11 09:32:12 +02:00
Mitchell Cash a620c4b5d8 Changed: Use cleancss for minification (#1654) 2017-06-11 09:31:27 +02:00
Mitchell Cash 28b523b504 Fixed: Follow 301 redirects when fetching torrents (#1653)
Closes #1564
2017-06-11 09:30:51 +02:00
Mitchell Cash 7af88037bb Fixed: Ensure an API Key is set when starting Radarr (#1652) 2017-06-11 09:30:00 +02:00
Leonardo Galli 43446ee3d0 Fixed: Forgot to include some js files in the last commit 2017-06-07 13:37:20 +02:00
Leonardo Galli accf8a9efa Added: Ability to see TMDB and lists going through the Radarr API on the discovery page.
Added: More lists (specifically presets for IMDB Top 250 and IMDB Popular)
Added: Ability to set Radarr API endpoint as list.
2017-06-06 22:40:44 +02:00
Leonardo Galli b70ed720c5 Fix error when we get invalid datetime from our api. 2017-06-06 20:03:52 +02:00
Leonardo Galli cff4578c66 Merge remote-tracking branch 'origin/develop' into develop 2017-06-06 19:51:00 +02:00
Leonardo Galli 7bbebe53a3 Added: Custom Class for Radarr API requests. Also implements new error handling present on staging server. 2017-06-06 19:50:53 +02:00
Leonardo Galli d81e3a79cf Added: Search 5 alternative titles as well. This should help with french as well as movies with very different titles. 2017-06-05 17:48:04 +02:00
Jason Costomiris 09c86013b0 Added: [Radarr] tag for Twitter Notifications (#1558) 2017-06-05 12:06:20 +02:00
Fish2 f1873a9684 lossless compression of images saved 92KB (#1620) 2017-06-04 13:11:52 +02:00
randellhodges 3d48da2111 Added HDBits Category, Codec, and Medium Filtering Capability (#1458)
* Added advanced configuration options to support filtering Categories, Codecs, and Medium to the HDBits indexer.

* Changes to use the existing tags with a controlled vocabulary.

* 1) Sorting select options by name
2) Moved the autocomplete tag code into taginput as requested

* removed commented out line

* require cleanups
2017-05-29 17:56:16 +02:00
Leonardo Galli 86634006e5 update radarr api url 2017-05-29 15:49:42 +02:00
Leonardo Galli 234827d5fd Mostly fixes UI glitches for list settings.
Fixes #679
2017-05-26 18:31:11 +02:00
Leonardo Galli 10bceaf370 Merge remote-tracking branch 'origin/develop' into develop 2017-05-26 11:12:14 +02:00
Leonardo Galli b7f6ff7b2e Fixed PTP indexer being disabled if no results are found for a movie.
Fixes #1573
2017-05-26 11:12:07 +02:00
Sentir101 6767f602fb Refresh IsDuplicate in bulk import when the tmdbId changes (#1570) 2017-05-25 15:44:43 +02:00
flightlevel e43e7d2b8d Encourage Torznab use with Jackett (#1559) 2017-05-23 17:30:59 +02:00
Leonardo Galli 811a4bf117 Fix basic naming settings.
Fixes #376
2017-05-21 18:10:46 +02:00
Leonardo Galli 9dee1d6fad Discovery of upcoming movies points to our server now.
Discovery results now show physical release date (if present).
All physical release dates now should show a note (if available) detailing what kind of release date it is (e.g. Netflix, DVD, Streaming, etc.)
2017-05-20 14:31:38 +02:00
Mike 390e4c3014 Most likely fixed #745 now 2017-05-18 01:08:13 +02:00
Mike aace29e1e1 Chmod osx file as executable. (#1539) 2017-05-17 11:20:32 +02:00
tsubus 8fb257d5b7 Add IMDB URL to notifications (#1531) 2017-05-15 14:47:22 +02:00
Levi Wilcox 28e0f85e88 Fixed design calendar css bug (#1527)
Fixes #983
2017-05-15 09:40:00 +02:00
Luke Anderson 41d3f6d7ea Correct Program Name (#1524) 2017-05-14 12:19:20 +02:00
Luke Anderson b19fbcbb71 Correct Program Name (#1523) 2017-05-14 12:19:10 +02:00
Leonardo Galli 5200758200 Osx updater now updates plist file to point to the correct executable binary. 2017-05-14 11:08:33 +02:00
Leonardo Galli 6210c5b8f8 Merge remote-tracking branch 'origin/develop' into develop 2017-05-14 11:03:28 +02:00
Leonardo Galli 6e31f7220c Fix osx updater failing. 2017-05-14 11:03:20 +02:00
Leonardo Galli 797a9acff5 Update TaskManager.cs 2017-05-13 21:22:55 +02:00
Leonardo Galli b36053e1f4 Update LogEntries token again :) 2017-05-13 20:32:55 +02:00
Leonardo Galli 212bcebdaf Fixed: Using our own logentries token now.
Fixes #1517
2017-05-13 13:11:54 +02:00
Leonardo Galli 3c8162f1d6 Fix test. 2017-05-12 16:52:38 +02:00
Leonardo Galli 096d24ed91 Merge branch 'feature/better-mapping-info' into develop 2017-05-12 16:09:35 +02:00
Leonardo Galli 63e3361fb5 Movies with same name but different year being downloaded regardlessly is now fixed! 2017-05-12 16:09:23 +02:00
Leonardo Galli 51854ef73b Update TaskManager.cs 2017-05-11 23:05:12 +02:00
Levi Wilcox a0486b54a6 Fixed design issue when deleting css bug (#1480) Fixes #1475 2017-05-11 22:05:34 +02:00
Leonardo Galli 7ed0db10cb 10 Movies are now shown on discover as well as search results.
Show more should also be more consistent now.
2017-05-09 22:28:15 +02:00
Leonardo Galli e94591a290 Hotfix for when ignored movies would appear again after clicking on show more. 2017-05-09 21:28:22 +02:00
Leonardo Galli fccd02a0ca Merge remote-tracking branch 'origin/develop' into develop 2017-05-09 20:44:43 +02:00
Leonardo Galli b49f0e70ed Merge branch 'feature/better-import-exclusions' into develop 2017-05-09 20:44:17 +02:00
Leonardo Galli fc1585e900 Completely overhauled how import exclusions work.
Currently new exclusions can only be added when adding new movies or deleting old ones. Not manually in the settings menu.
Movies can now be hidden in the new discover feature by using the new import exclusions!
2017-05-09 20:44:07 +02:00
Leonardo Galli b36ac091fc Fix appveyor build 2017-05-09 19:49:30 +02:00
Leonardo Galli ab28bfead2 Merge branch 'develop' into feature/better-import-exclusions 2017-05-09 16:55:19 +02:00
Leonardo Galli 3ab3fbfd57 Added ability to discover new movies based on upcoming blurays as well as popular movies (borrowed from steven lu :)) 2017-05-09 16:46:19 +02:00
Leonardo Galli d133ee3143 Hopefully more logging to catch errors better. 2017-05-08 18:46:03 +02:00
Leonardo Galli 98b6932ffe Merge remote-tracking branch 'origin/develop' into develop 2017-05-08 18:07:38 +02:00
Leonardo Galli 58e81a916c Fixed error when language is present in title, but has dots instead of spaces. For example The.Danish.Girl.2015 2017-05-06 15:26:35 +02:00
PatrickGHanna 817f48448c Fix: A small bug fix for items loading as undefined in organize modal. Movie titles should now show up correctly. (#1424) 2017-05-06 12:31:41 +02:00
hotio 1eca179b4e Update Kodi icon, fixes #1464 (#1492) 2017-05-06 12:30:36 +02:00
Leonardo Galli b05d505bce Fixed Final in titles parsing as an edition. 2017-05-02 22:15:03 +02:00
Leonardo Galli ace426e69f Added initial migration. 2017-04-30 14:05:41 +02:00
Mitchell Cash a57c9917cc Fixed: Radarr not importing torrents in Vuze if the torrent already finished seeding and was stopped (#1471) 2017-04-30 13:14:49 +02:00
Mitchell Cash 9e84b4a782 Fixed: Incorrect imports with Vuze when torrent contains a single file. (#1470) 2017-04-30 10:37:51 +02:00
Mitchell Cash 494ef16735 Fixed: Sonarr UI Authentication cookie should be placed on path (UrlBase) instead of domain alone. Fixes ##1451 2017-04-30 10:30:59 +02:00
Leonardo Galli 5a0f02007f Added trailer links to the discovery page. 2017-04-28 14:14:02 +02:00
Leonardo Galli b1025e7229 Use Post for tmdbids request, to avoid too long URIs. 2017-04-28 13:14:00 +02:00
Leonardo Galli 446d661345 Added discovery tab based on tmdb recommendations based on your existing movies. (#1450)
Keep scroll position on more in search result view.
Added TMDB score to search results.
2017-04-28 11:04:30 +02:00
David Pooley 3eb351823e Tidy up layout of buttons on the Add Movies page for mobile/tablet (#1454) 2017-04-28 10:59:55 +02:00
morberg 835a7cffa1 Rename Sonarr to Radarr for OSX App 2017-04-26 18:44:57 +02:00
Leonardo Galli e728330ce4 Minor text fixes. 2017-04-26 15:45:06 +02:00
Leonardo Galli 6f3118c142 Merge remote-tracking branch 'origin/develop' into develop 2017-04-26 15:17:49 +02:00
Leonardo Galli b568072140 Change default page size to 250. Should help with safari timeouts. 2017-04-26 15:17:42 +02:00
Leonardo Galli 7db92c6bcf Enable automatic renaming, according to naming scheme, of movie folder after creation of the movie. (#1349)
Please test everything you can about this and report back if everything still works correctly.
2017-04-26 13:31:55 +02:00
Leonardo Galli f1e8a9acfc Fix for error when clicking Rescan Drone Folder 2017-04-19 22:04:34 +02:00
Leonardo Galli dae389ce64 Fix for error when trying to manually import. 2017-04-19 22:03:52 +02:00
Leonardo Galli 7c3d8c8ff9 Added multiple new editions such as FanEdit, Anniversary and 2in1. 2017-04-19 21:02:01 +02:00
Donald Webster 8ca66fb61a Change smtp.google.com to smtp.gmail.com (#1410) 2017-04-18 19:28:15 +02:00
Leonardo Galli 064844ac0c Fix PTP_Approved turning into HDBits Internal. 2017-04-18 16:41:40 +02:00
Leonardo Galli 5540594ecf Fix ptp tests. 2017-04-17 22:30:51 +02:00
Leonardo Galli 433ae019de AHD, PTP and HDB support the new indexer flags too now! Indexer flags can be preferred over other releases. 2017-04-17 17:12:09 +02:00
Leonardo Galli 10091b9454 Movies with Umlauts are now correctly matched and have correct CleanTitles.
An update library is recommended. Fixes #1338
2017-04-17 13:08:47 +02:00
Leonardo Galli 475851775f Minor Text fixes. 2017-04-17 12:11:35 +02:00
Leonardo Galli 0fff862fd2 Updated debug movie title to include Year. 2017-04-17 12:09:24 +02:00
Leonardo Galli 23754c49dc Fix error when MinimumAvailability was Announced and Delay was negative. 2017-04-17 12:08:03 +02:00
Leonardo Galli fbf790e9fd Disable PreDB sync for now. 2017-04-17 12:04:54 +02:00
Leonardo Galli 6d00bd0f7a Stats are now sent to our server instead of Sonarr's :) 2017-04-17 12:01:56 +02:00
hotio 5bf95e0d9e Update Series reference to Movies, should fix #1399 (#1402) 2017-04-16 23:20:42 +02:00
Leonardo Galli 8bb4b02be7 Fix for sql error. Did not think everything through exactly.
Fixes #1390.
2017-04-16 00:48:39 +02:00
Leonardo Galli b26a036eed Fix when MovieTitle is the empty string (should not occur, but what evs)
Fixes #1389
2017-04-16 00:26:16 +02:00
Leonardo Galli ef57882291 Fixes Movie Size not showing correctly.
Fixes #1379
2017-04-15 15:47:40 +02:00
Leonardo Galli 32a2407ad1 Fixed an issue where movies which were labelled with an alternative title could not be found.
Fixes #557 Fixes #1387 Probably fixes #1372, probably fixes #555
2017-04-15 14:50:34 +02:00
Leonardo Galli 33b48eec95 Indexer flags implementation. (#1377) Will be further finalized over the next few weeks with Freelech, preferring of certain flags, etc 2017-04-14 22:27:48 +02:00
Leonardo Galli 3790dc9109 Added test for fix in last commit. 2017-04-13 14:18:48 +02:00
Leonardo Galli 343d849536 Add default runtime when runtime info of tmdb says 0.
Fixes #1371
2017-04-13 14:04:38 +02:00
Leonardo Galli c36b259fa9 Fixes an issue where the semicolon and space afterwards was replaced.
This caused issues with cleaning the title afterwards. Fixes #1185
2017-04-13 10:27:00 +02:00
Leonardo Galli 6463913f22 Final tweak for package.sh 2017-04-12 22:31:49 +02:00
Leonardo Galli e39deb4bdc Update branch. 2017-04-12 21:57:59 +02:00
Leonardo Galli 9ca2c21547 This should finally fix all packaging stuff. 2017-04-12 21:46:33 +02:00
Leonardo Galli f376360611 Update packages.sh some more. 2017-04-12 21:23:02 +02:00
Leonardo Galli 3e966d4d58 Update package.sh script 2017-04-12 21:20:33 +02:00
Leonardo Galli e036267c33 Test fixes. 2017-04-12 18:23:04 +02:00
Leonardo Galli 7d4378ca7a More test debugging. 2017-04-12 18:12:47 +02:00
Leonardo Galli ee1ebfd893 Remote Test debugging yey! 2017-04-12 17:58:52 +02:00
Leonardo Galli 403fd0f0c0 Remove unecessary test. 2017-04-12 17:17:22 +02:00
Leonardo Galli fc5ac8219f Using NUnit.Runners so that teamcity build works. 2017-04-12 17:03:53 +02:00
Leonardo Galli 600a433faa Merge remote-tracking branch 'origin/develop' into develop 2017-04-12 16:45:23 +02:00
Leonardo Galli 5609facd9d Fixed package script for Teamcity. 2017-04-12 16:45:13 +02:00
Leonardo Galli 36ea6c6b99 Turn installer back on. 2017-04-12 12:23:07 +02:00
Leonardo Galli 56ac87c760 Disabled installer being picked up, causes error with update api. 2017-04-11 21:19:31 +02:00
Leonardo Galli 47753c47a5 Now artifacts get pushed even if tests fail 2017-04-11 19:40:13 +02:00
Leonardo Galli 712c0eb84a Log if ParsedMovieInfo is NULL. 2017-04-11 19:31:33 +02:00
Leonardo Galli 8765155223 Merge remote-tracking branch 'origin/develop' into develop 2017-04-11 12:16:14 +02:00
Leonardo Galli 63d7596e98 Catching predb.me errors hopefully. 2017-04-11 12:15:52 +02:00
497 changed files with 15892 additions and 2101 deletions
+293
View File
@@ -0,0 +1,293 @@
# -*- coding: utf-8; mode: python -*-
##
## Format
##
## ACTION: [AUDIENCE:] COMMIT_MSG [!TAG ...]
##
## Description
##
## ACTION is one of 'chg', 'fix', 'new'
##
## Is WHAT the change is about.
##
## 'chg' is for refactor, small improvement, cosmetic changes...
## 'fix' is for bug fixes
## 'new' is for new features, big improvement
##
## AUDIENCE is optional and one of 'dev', 'usr', 'pkg', 'test', 'doc'
##
## Is WHO is concerned by the change.
##
## 'dev' is for developpers (API changes, refactors...)
## 'usr' is for final users (UI changes)
## 'pkg' is for packagers (packaging changes)
## 'test' is for testers (test only related changes)
## 'doc' is for doc guys (doc only changes)
##
## COMMIT_MSG is ... well ... the commit message itself.
##
## TAGs are additionnal adjective as 'refactor' 'minor' 'cosmetic'
##
## They are preceded with a '!' or a '@' (prefer the former, as the
## latter is wrongly interpreted in github.) Commonly used tags are:
##
## 'refactor' is obviously for refactoring code only
## 'minor' is for a very meaningless change (a typo, adding a comment)
## 'cosmetic' is for cosmetic driven change (re-indentation, 80-col...)
## 'wip' is for partial functionality but complete subfunctionality.
##
## Example:
##
## new: usr: support of bazaar implemented
## chg: re-indentend some lines !cosmetic
## new: dev: updated code to be compatible with last version of killer lib.
## fix: pkg: updated year of licence coverage.
## new: test: added a bunch of test around user usability of feature X.
## fix: typo in spelling my name in comment. !minor
##
## Please note that multi-line commit message are supported, and only the
## first line will be considered as the "summary" of the commit message. So
## tags, and other rules only applies to the summary. The body of the commit
## message will be displayed in the changelog without reformatting.
##
## ``ignore_regexps`` is a line of regexps
##
## Any commit having its full commit message matching any regexp listed here
## will be ignored and won't be reported in the changelog.
##
ignore_regexps = [
r'@minor', r'!minor',
r'@cosmetic', r'!cosmetic',
r'@refactor', r'!refactor',
r'@wip', r'!wip',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[p|P]kg:',
r'^([cC]hg|[fF]ix|[nN]ew)\s*:\s*[d|D]ev:',
r'^(.{3,3}\s*:)?\s*[fF]irst commit.?\s*$',
r'^$', ## ignore commits with empty messages
]
## ``section_regexps`` is a list of 2-tuples associating a string label and a
## list of regexp
##
## Commit messages will be classified in sections thanks to this. Section
## titles are the label, and a commit is classified under this section if any
## of the regexps associated is matching.
##
## Please note that ``section_regexps`` will only classify commits and won't
## make any changes to the contents. So you'll probably want to go check
## ``subject_process`` (or ``body_process``) to do some changes to the subject,
## whenever you are tweaking this variable.
##
section_regexps = [
('**New Features**', [
r'^[aA]dded?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
r'^[uU]pdated?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
r'^[cC]hanged?\s*:?\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n]*)$',
]),
('**Fixes**', [
r'^(?![mM]erge\s*)'
]
),
]
## ``body_process`` is a callable
##
## This callable will be given the original body and result will
## be used in the changelog.
##
## Available constructs are:
##
## - any python callable that take one txt argument and return txt argument.
##
## - ReSub(pattern, replacement): will apply regexp substitution.
##
## - Indent(chars=" "): will indent the text with the prefix
## Please remember that template engines gets also to modify the text and
## will usually indent themselves the text if needed.
##
## - Wrap(regexp=r"\n\n"): re-wrap text in separate paragraph to fill 80-Columns
##
## - noop: do nothing
##
## - ucfirst: ensure the first letter is uppercase.
## (usually used in the ``subject_process`` pipeline)
##
## - final_dot: ensure text finishes with a dot
## (usually used in the ``subject_process`` pipeline)
##
## - strip: remove any spaces before or after the content of the string
##
## - SetIfEmpty(msg="No commit message."): will set the text to
## whatever given ``msg`` if the current text is empty.
##
## Additionally, you can `pipe` the provided filters, for instance:
#body_process = Wrap(regexp=r'\n(?=\w+\s*:)') | Indent(chars=" ")
#body_process = Wrap(regexp=r'\n(?=\w+\s*:)')
#body_process = noop
body_process = ReSub(r'((^|\n)[A-Z]\w+(-\w+)*: .*(\n\s+.*)*)+$', r'') | strip
## ``subject_process`` is a callable
##
## This callable will be given the original subject and result will
## be used in the changelog.
##
## Available constructs are those listed in ``body_process`` doc.
subject_process = (strip |
ReSub(r'^([cC]hanged|[fF]ixed|[aA]dded|[uU]pdated)\s*:\s*((dev|use?r|pkg|test|doc)\s*:\s*)?([^\n@]*)(@[a-z]+\s+)*$', r'\4') |
SetIfEmpty("No commit message.") | ucfirst | final_dot)
## ``tag_filter_regexp`` is a regexp
##
## Tags that will be used for the changelog must match this regexp.
##
tag_filter_regexp = r'^v[0]+\.[2-9]+\.[0-9]+\.[0-9]+$'
## ``unreleased_version_label`` is a string or a callable that outputs a string
##
## This label will be used as the changelog Title of the last set of changes
## between last valid tag and HEAD if any.
unreleased_version_label = "(unreleased)"
## ``output_engine`` is a callable
##
## This will change the output format of the generated changelog file
##
## Available choices are:
##
## - rest_py
##
## Legacy pure python engine, outputs ReSTructured text.
## This is the default.
##
## - mustache(<template_name>)
##
## Template name could be any of the available templates in
## ``templates/mustache/*.tpl``.
## Requires python package ``pystache``.
## Examples:
## - mustache("markdown")
## - mustache("restructuredtext")
##
## - makotemplate(<template_name>)
##
## Template name could be any of the available templates in
## ``templates/mako/*.tpl``.
## Requires python package ``mako``.
## Examples:
## - makotemplate("restructuredtext")
##
#output_engine = rest_py
#output_engine = mustache("restructuredtext")
output_engine = mustache("changelog.tpl")
#output_engine = makotemplate("restructuredtext")
## ``include_merge`` is a boolean
##
## This option tells git-log whether to include merge commits in the log.
## The default is to include them.
include_merge = False
## ``log_encoding`` is a string identifier
##
## This option tells gitchangelog what encoding is outputed by ``git log``.
## The default is to be clever about it: it checks ``git config`` for
## ``i18n.logOutputEncoding``, and if not found will default to git's own
## default: ``utf-8``.
#log_encoding = 'utf-8'
## ``publish`` is a callable
##
## Sets what ``gitchangelog`` should do with the output generated by
## the output engine. ``publish`` is a callable taking one argument
## that is an interator on lines from the output engine.
##
## Some helper callable are provided:
##
## Available choices are:
##
## - stdout
##
## Outputs directly to standard output
## (This is the default)
##
## - FileInsertAtFirstRegexMatch(file, pattern, idx=lamda m: m.start())
##
## Creates a callable that will parse given file for the given
## regex pattern and will insert the output in the file.
## ``idx`` is a callable that receive the matching object and
## must return a integer index point where to insert the
## the output in the file. Default is to return the position of
## the start of the matched string.
##
## - FileRegexSubst(file, pattern, replace, flags)
##
## Apply a replace inplace in the given file. Your regex pattern must
## take care of everything and might be more complex. Check the README
## for a complete copy-pastable example.
##
# publish = FileInsertIntoFirstRegexMatch(
# "CHANGELOG.rst",
# r'/(?P<rev>[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n/',
# idx=lambda m: m.start(1)
# )
#publish = stdout
def write_to_file(content):
with open("CHANGELOG.md", "w+") as f:
for chunk in content:
f.write(chunk)
publish = write_to_file
## ``revs`` is a list of callable or a list of string
##
## callable will be called to resolve as strings and allow dynamical
## computation of these. The result will be used as revisions for
## gitchangelog (as if directly stated on the command line). This allows
## to filter exaclty which commits will be read by gitchangelog.
##
## To get a full documentation on the format of these strings, please
## refer to the ``git rev-list`` arguments. There are many examples.
##
## Using callables is especially useful, for instance, if you
## are using gitchangelog to generate incrementally your changelog.
##
## Some helpers are provided, you can use them::
##
## - FileFirstRegexMatch(file, pattern): will return a callable that will
## return the first string match for the given pattern in the given file.
## If you use named sub-patterns in your regex pattern, it'll output only
## the string matching the regex pattern named "rev".
##
## - Caret(rev): will return the rev prefixed by a "^", which is a
## way to remove the given revision and all its ancestor.
##
## Please note that if you provide a rev-list on the command line, it'll
## replace this value (which will then be ignored).
##
## If empty, then ``gitchangelog`` will act as it had to generate a full
## changelog.
##
## The default is to use all commits to make the changelog.
#revs = ["^1.0.3", ]
#revs = [
# Caret(
# FileFirstRegexMatch(
# "CHANGELOG.rst",
# r"(?P<rev>[0-9]+\.[0-9]+(\.[0-9]+)?)\s+\([0-9]+-[0-9]{2}-[0-9]{2}\)\n--+\n")),
# "HEAD"
#]
revs = []
-1
View File
@@ -20,6 +20,5 @@
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Sonarr node_modules" level="project" />
</component> </component>
</module> </module>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="JavaScriptLibraryMappings"> <component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="ECMAScript 6" /> <excludedPredefinedLibrary name="Radarr/node_modules" />
</component> </component>
</project> </project>
-14
View File
@@ -1,14 +0,0 @@
<component name="libraryTable">
<library name="Sonarr node_modules" type="javaScript">
<properties>
<option name="frameworkName" value="node_modules" />
<sourceFilesUrls>
<item url="file://$PROJECT_DIR$/node_modules" />
</sourceFilesUrls>
</properties>
<CLASSES>
<root url="file://$PROJECT_DIR$/node_modules" />
</CLASSES>
<SOURCES />
</library>
</component>
+1566
View File
File diff suppressed because it is too large Load Diff
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

After

Width:  |  Height:  |  Size: 44 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 701 B

After

Width:  |  Height:  |  Size: 605 B

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 16 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 21 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 34 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 28 KiB

+7 -10
View File
@@ -21,10 +21,10 @@ The project was inspired by other Usenet/BitTorrent movie downloaders such as Co
## Downloads ## Downloads
[![GitHub Releases](https://img.shields.io/badge/downloads-releases-brightgreen.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/releases) [![GitHub Releases](https://img.shields.io/badge/downloads-releases-brightgreen.svg?maxAge=60&style=flat-square)](https://github.com/Radarr/Radarr/releases)
[![AppVeyor Builds](https://img.shields.io/badge/downloads-continuous-green.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/radarr-usby1/build/artifacts) [![AppVeyor Builds](https://img.shields.io/badge/downloads-continuous-green.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/radarr-usby1/branch/develop/artifacts)
[![Docker release](https://img.shields.io/badge/docker-release-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/linuxserver/radarr) [![Docker release](https://img.shields.io/badge/docker-release-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/linuxserver/radarr)
[![Docker nightly](https://img.shields.io/badge/docker-nightly-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/hotio/radarr) [![Docker nightly](https://img.shields.io/badge/docker-release/nightly-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/hotio/suitarr)
[![Docker armhf](https://img.shields.io/badge/docker-armhf-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/lsioarmhf/radarr) [![Docker armhf](https://img.shields.io/badge/docker-armhf-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/lsioarmhf/radarr)
[![Docker aarch64](https://img.shields.io/badge/docker-aarch64-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64) [![Docker aarch64](https://img.shields.io/badge/docker-aarch64-blue.svg?colorB=1488C6&maxAge=60&style=flat-square)](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64)
@@ -50,8 +50,6 @@ The project was inspired by other Usenet/BitTorrent movie downloaders such as Co
| AppVeyor | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr/master.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr) | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr-usby1/develop.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) | | AppVeyor | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr/master.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr) | [![AppVeyor](https://img.shields.io/appveyor/ci/galli-leo/Radarr-usby1/develop.svg?maxAge=60&style=flat-square)](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
| Travis | [![Travis](https://img.shields.io/travis/Radarr/Radarr/master.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) | [![Travis](https://img.shields.io/travis/Radarr/Radarr/develop.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) | | Travis | [![Travis](https://img.shields.io/travis/Radarr/Radarr/master.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) | [![Travis](https://img.shields.io/travis/Radarr/Radarr/develop.svg?maxAge=60&style=flat-square)](https://travis-ci.org/Radarr/Radarr) |
**This project works independently of Sonarr and will not interfere with it.**
Radarr is currently undergoing rapid development and pull requests are actively added into the repository. Radarr is currently undergoing rapid development and pull requests are actively added into the repository.
## Features ## Features
@@ -71,7 +69,8 @@ Radarr is currently undergoing rapid development and pull requests are actively
* All indexers supported by Sonarr also supported * All indexers supported by Sonarr also supported
* New PassThePopcorn Indexer * New PassThePopcorn Indexer
* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming) * QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming)
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett)) * New TorrentPotato Indexer
* Torznab Indexer now supports Movies (Works well with [Jackett](https://github.com/Jackett/Jackett))
* Scanning PreDB to know when a new release is available * Scanning PreDB to know when a new release is available
* Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114)) * Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
* Full integration with Kodi, Plex (notification, library update) * Full integration with Kodi, Plex (notification, library update)
@@ -114,9 +113,7 @@ Radarr is currently undergoing rapid development and pull requests are actively
* Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed * Open `NzbDrone.sln` in Visual Studio or run the build.sh script, if Mono is installed
* Make sure `NzbDrone.Console` is set as the startup project * Make sure `NzbDrone.Console` is set as the startup project
## Sponsors ### License
Thanks to [JetBrains](http://www.jetbrains.com) for providing us with free licenses to their great tools: * [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
* [ReSharper](http://www.jetbrains.com/resharper) * Copyright 2010-2017
* [WebStorm](http://www.jetbrains.com/webstorm)
* [TeamCity](http://www.jetbrains.com/teamcity)
+13 -8
View File
@@ -16,14 +16,14 @@ install:
build_script: build_script:
- ps: ./build-appveyor.ps1 - ps: ./build-appveyor.ps1
# test: off test: off
test: #test:
assemblies: # assemblies:
- '_tests\*Test.dll' # - '_tests\*Test.dll'
categories: # categories:
except: # except:
- IntegrationTest # - IntegrationTest
- AutomationTest # - AutomationTest
artifacts: artifacts:
- path: '_artifacts\*.zip' - path: '_artifacts\*.zip'
@@ -37,6 +37,11 @@ cache:
pull_requests: pull_requests:
do_not_increment_build_number: true do_not_increment_build_number: true
on_failure:
- ps: Get-ChildItem .\_artifacts\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
- ps: Get-ChildItem .\_artifacts\*.exe | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
- ps: Get-ChildItem .\_artifacts\*.tar.gz | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
only_commits: only_commits:
files: files:
- src/ - src/
+16 -8
View File
@@ -104,11 +104,13 @@ Task("Compile").Does(() => {
}); });
Task("Gulp").Does(() => { Task("Gulp").Does(() => {
Npm NpmInstall(new NpmInstallSettings {
.WithLogLevel(NpmLogLevel.Silent) LogLevel = NpmLogLevel.Silent,
.FromPath(".") WorkingDirectory = "./",
.Install() Production = true
.RunScript("build"); });
NpmRunScript("build");
}); });
Task("PackageMono").Does(() => { Task("PackageMono").Does(() => {
@@ -166,8 +168,14 @@ Task("PackageOsx").Does(() => {
// Adding MediaInfo dylib // Adding MediaInfo dylib
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx); CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
// Chmod as executable
StartProcess(@"C:\cygwin64\bin\chmod.exe", new ProcessSettings()
.WithArguments(args => args
.Append("+x")
.Append(outputFolderOsx + "/Radarr")));
// Adding Startup script // Adding Startup script
CopyFile("./osx/Sonarr", outputFolderOsx + "/Sonarr"); CopyFile("./osx/Radarr", outputFolderOsx + "/Radarr");
}); });
Task("PackageOsxApp").Does(() => { Task("PackageOsxApp").Does(() => {
@@ -266,9 +274,9 @@ Task("ArtifactsWindows").Does(() => {
Task("ArtifactsWindowsInstaller").Does(() => { Task("ArtifactsWindowsInstaller").Does(() => {
InnoSetup("./setup/nzbdrone.iss", new InnoSetupSettings { InnoSetup("./setup/nzbdrone.iss", new InnoSetupSettings {
OutputDirectory = artifactsFolder, OutputDirectory = artifactsFolder,
ToolPath = "./setup/inno/ISCC.exe" ToolPath = "./setup/inno/ISCC.exe"
}); });
}); });
Task("ArtifactsLinux").Does(() => { Task("ArtifactsLinux").Does(() => {
+3 -3
View File
@@ -181,7 +181,7 @@ PackageOsx()
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderOsx cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderOsx
echo "Adding Startup script" echo "Adding Startup script"
cp ./osx/Sonarr $outputFolderOsx cp ./osx/Radarr $outputFolderOsx
echo "##teamcity[progressFinish 'Creating OS X Package']" echo "##teamcity[progressFinish 'Creating OS X Package']"
} }
@@ -208,9 +208,9 @@ PackageTests()
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \; find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
if [ $runtime = "dotnet" ] ; then if [ $runtime = "dotnet" ] ; then
$nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder $nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
else else
mono $nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder mono $nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
fi fi
cp $outputFolder/*.dll $testPackageFolder cp $outputFolder/*.dll $testPackageFolder
+15
View File
@@ -0,0 +1,15 @@
# Changelog
{{#versions}}
## {{{label}}}
{{#sections}}
### {{{label}}}
{{#commits}}
- {{{subject}}} [{{{author}}}]
{{/commits}}
{{/sections}}
{{/versions}}
+44
View File
@@ -0,0 +1,44 @@
input1 = """Prometheus.Special.Edition.Fan Edit.2012..BRRip.x264.AAC-m2g
Star Wars Episode IV - A New Hope (Despecialized) 1999.mkv
Prometheus.(Special.Edition.Remastered).2012.[Bluray-1080p].mkv
Prometheus Extended 2012
Prometheus Extended Directors Cut Fan Edit 2012
Prometheus Director's Cut 2012
Prometheus Directors Cut 2012
Prometheus.(Extended.Theatrical.Version.IMAX).BluRay.1080p.2012.asdf
2001 A Space Odyssey Director's Cut (1968).mkv
2001: A Space Odyssey (Extended Directors Cut FanEdit) Bluray 1080p 1968
A Fake Movie 2035 Directors 2012.mkv
Blade Runner Director's Cut 2049.mkv
Prometheus 50th Anniversary Edition 2012.mkv
Movie 2in1 2012.mkv
Movie IMAX 2012.mkv"""
output1 = """Special.Edition.Fan Edit BRRip.x264.AAC-m2g
Despecialized mkv
Special.Edition.Remastered Bluray-1080p].mkv
Extended mkv
Extended Directors Cut Fan Edit mkv
Director's Cut mkv
Directors Cut mkv
Extended.Theatrical.Version.IMAX asdf
Director's Cut mkv
Extended Directors Cut FanEdit mkv
Directors mkv
Director's Cut mkv
50th Anniversary Edition mkv
2in1 mkv
IMAX mkv"""
inputs = input1.split("\n")
outputs = output1.split("\n")
real_o = []
for output in outputs:
real_o.append(output.split(" ")[0].replace(".", " ").strip())
count = 0
for inp in inputs:
o = real_o[count]
print "[TestCase(\"{0}\", \"{1}\")]".format(inp, o)
count += 1
+1 -1
View File
@@ -25,7 +25,7 @@ gulp.task('copyHtml', function () {
}); });
gulp.task('copyContent', function () { gulp.task('copyContent', function () {
return gulp.src([paths.src.content + '**/*.*', '!**/*.less']) return gulp.src([paths.src.content + '**/*.*', '!**/*.less', '!**/*.css'])
.pipe(gulp.dest(paths.dest.content)) .pipe(gulp.dest(paths.dest.content))
.pipe(livereload()); .pipe(livereload());
}); });
+8 -3
View File
@@ -5,7 +5,7 @@ var postcss = require('gulp-postcss');
var sourcemaps = require('gulp-sourcemaps'); var sourcemaps = require('gulp-sourcemaps');
var autoprefixer = require('autoprefixer-core'); var autoprefixer = require('autoprefixer-core');
var livereload = require('gulp-livereload'); var livereload = require('gulp-livereload');
var cleancss = require('gulp-clean-css');
var print = require('gulp-print'); var print = require('gulp-print');
var paths = require('./paths'); var paths = require('./paths');
var errorHandler = require('./errorHandler'); var errorHandler = require('./errorHandler');
@@ -16,6 +16,10 @@ gulp.task('less', function() {
paths.src.content + 'bootstrap.less', paths.src.content + 'bootstrap.less',
paths.src.content + 'theme.less', paths.src.content + 'theme.less',
paths.src.content + 'overrides.less', paths.src.content + 'overrides.less',
paths.src.content + 'bootstrap.toggle-switch.css',
paths.src.content + 'fullcalendar.css',
paths.src.content + 'Messenger/messenger.css',
paths.src.content + 'Messenger/messenger.flat.css',
paths.src.root + 'Series/series.less', paths.src.root + 'Series/series.less',
paths.src.root + 'Activity/activity.less', paths.src.root + 'Activity/activity.less',
paths.src.root + 'AddSeries/addSeries.less', paths.src.root + 'AddSeries/addSeries.less',
@@ -36,12 +40,13 @@ gulp.task('less', function() {
.pipe(sourcemaps.init()) .pipe(sourcemaps.init())
.pipe(less({ .pipe(less({
dumpLineNumbers : 'false', dumpLineNumbers : 'false',
compress : true, compress : false,
yuicompress : true, yuicompress : false,
ieCompat : true, ieCompat : true,
strictImports : true strictImports : true
})) }))
.pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ])) .pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
.pipe(cleancss())
.on('error', errorHandler.onError) .on('error', errorHandler.onError)
.pipe(sourcemaps.write(paths.dest.content)) .pipe(sourcemaps.write(paths.dest.content))
.pipe(gulp.dest(paths.dest.content)) .pipe(gulp.dest(paths.dest.content))
+1 -1
View File
@@ -5,7 +5,7 @@ DIR=$(cd "$(dirname "$0")"; pwd)
#change these values to match your app #change these values to match your app
EXE_PATH="$DIR/Radarr.exe" EXE_PATH="$DIR/Radarr.exe"
APPNAME="Sonarr" APPNAME="Radarr"
#set up environment #set up environment
if [[ -x '/opt/local/bin/mono' ]]; then if [[ -x '/opt/local/bin/mono' ]]; then
+2 -2
View File
@@ -11,11 +11,11 @@
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>Sonarr</string> <string>Radarr</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>radarr.icns</string> <string>radarr.icns</string>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>com.osx.sonarr.tv</string> <string>com.osx.radarr.video</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleName</key> <key>CFBundleName</key>
+4190
View File
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -1,7 +1,7 @@
{ {
"name": "Sonarr", "name": "Radarr",
"version": "2.0.0", "version": "2.0.0",
"description": "Sonarr", "description": "Radarr",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
"build": "gulp build", "build": "gulp build",
@@ -9,7 +9,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/Sonarr/Sonarr.git" "url": "git://github.com/Radarr/Radarr.git"
}, },
"author": "", "author": "",
"license": "GPL-3.0", "license": "GPL-3.0",
@@ -20,6 +20,7 @@
"del": "1.2.0", "del": "1.2.0",
"gulp": "3.9.0", "gulp": "3.9.0",
"gulp-cached": "1.1.0", "gulp-cached": "1.1.0",
"gulp-clean-css": "^3.0.4",
"gulp-concat": "2.6.0", "gulp-concat": "2.6.0",
"gulp-declare": "0.3.0", "gulp-declare": "0.3.0",
"gulp-handlebars": "3.0.1", "gulp-handlebars": "3.0.1",
+38 -29
View File
@@ -23,20 +23,19 @@ if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
DAY="`date +%d`" DAY="`date +%d`"
else else
VERSION=$1 VERSION=$1
BRANCH=$2
BRANCH=${BRANCH#refs\/heads\/}
BRANCH=${BRANCH//\//-}
fi fi
outputFolder='./_output' outputFolder='./_output'
outputFolderMono='./_output_mono' outputFolderMono='./_output_mono'
outputFolderOsx='./_output_osx' outputFolderOsx='./_output_osx'
outputFolderOsxApp='./_output_osx_app' outputFolderOsxApp='./_output_osx_app'
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr >& error.log
cp -r $outputFolder/ Radarr_Windows_$VERSION
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
if [ $runtime = "dotnet" ] ; then if [ $runtime = "dotnet" ] ; then
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/* ./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
@@ -44,25 +43,35 @@ if [ $runtime = "dotnet" ] ; then
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz ./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz ./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
else else
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null cp -r $outputFolder/ Radarr
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz zip -r Radarr.$BRANCH.$VERSION.windows.zip Radarr
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null rm -rf Radarr
cp -r $outputFolderMono/ Radarr
tar -zcvf Radarr.$BRANCH.$VERSION.linux.tar.gz Radarr
rm -rf Radarr
cp -r $outputFolderOsx/ Radarr
tar -zcvf Radarr.$BRANCH.$VERSION.osx.tar.gz Radarr
rm -rf Radarr
#TODO update for tar.gz
cd _output_osx_app/
zip -r ../Radarr.$BRANCH.$VERSION.osx-app.zip *
fi fi
ftp -n ftp.leonardogalli.ch << END_SCRIPT # ftp -n ftp.leonardogalli.ch << END_SCRIPT
passive # passive
quote USER $FTP_USER # quote USER $FTP_USER
quote PASS $FTP_PASS # quote PASS $FTP_PASS
mkdir builds # mkdir builds
cd builds # cd builds
mkdir $YEAR # mkdir $YEAR
cd $YEAR # cd $YEAR
mkdir $MONTH # mkdir $MONTH
cd $MONTH # cd $MONTH
mkdir $DAY # mkdir $DAY
cd $DAY # cd $DAY
binary # binary
put Radarr_Windows_$VERSION.zip # put Radarr_Windows_$VERSION.zip
put Radarr_Mono_$VERSION.zip # put Radarr_Mono_$VERSION.zip
put Radarr_OSX_$VERSION.zip # put Radarr_OSX_$VERSION.zip
quit # quit
END_SCRIPT # END_SCRIPT
+1
View File
@@ -0,0 +1 @@
NzbDrone
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderRiderContentModelStore">
<excludedPaths />
</component>
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.NzbDrone/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.NzbDrone/riderModule.iml" />
</modules>
</component>
</project>
+103
View File
@@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../../../Logo/1024.png">
<sourceFolder url="file://$MODULE_DIR$/../../../Logo/1024.png" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$/../../../Logo/64.png">
<sourceFolder url="file://$MODULE_DIR$/../../../Logo/64.png" isTestSource="false" />
</content>
<content url="file://$MODULE_DIR$/../..">
<sourceFolder url="file://$MODULE_DIR$/../../.nuget/NuGet.exe" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Common/CommonAssemblyInfo.cs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Common/CommonVersionInfo.cs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Common/GlobalSuppressions.cs" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/MediaInfo/libmediainfo.0.dylib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/MediaInfo/MediaInfo.dll" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/Sqlite/libsqlite3.0.dylib" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/Sqlite/sqlite3.dll" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../LogentriesCore" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../LogentriesNLog" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Marr.Data" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../MonoTorrent" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Api" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Common" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Console" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Core" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Host" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.SignalR" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Update" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceInstall" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceUninstall" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesCore/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesCore/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesNLog/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesNLog/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../Marr.Data/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../MonoTorrent/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Console/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Host/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.SignalR/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test/bin" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceInstall/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceUninstall/obj" />
<excludeFolder url="file://$MODULE_DIR$/../../_ReSharper.Caches/ReSharperHost8.NzbDrone.00" />
<excludeFolder url="file://$MODULE_DIR$/../../packages" />
</content>
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
@@ -14,8 +14,10 @@ You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>. */ License along with this library. If not, see <http://www.gnu.org/licenses/>. */
using System; using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.Common; using System.Data.Common;
using System.Runtime.InteropServices.ComTypes;
using Marr.Data.Converters; using Marr.Data.Converters;
namespace Marr.Data.Parameters namespace Marr.Data.Parameters
@@ -42,15 +44,25 @@ namespace Marr.Data.Parameters
Type valueType = value.GetType(); Type valueType = value.GetType();
// Check for a registered IConverter // Check for a registered IConverter
IConverter converter = MapRepository.Instance.GetConverter(valueType); //If we have a list of ints, we ignore the converter since we want to do an in statement!
if (converter != null) var list = value as List<int>;
if (list != null)
{ {
Parameter.Value = converter.ToDB(value); Parameter.Value = $"{string.Join(",", list)}";
} }
else else
{ {
Parameter.Value = value; IConverter converter = MapRepository.Instance.GetConverter(valueType);
} if (converter != null)
{
Parameter.Value = converter.ToDB(value);
}
else
{
Parameter.Value = value;
}
}
//// Determine the correct DbType based on the passed in value type //// Determine the correct DbType based on the passed in value type
//IDbTypeBuilder typeBuilder = MapRepository.Instance.DbTypeBuilder; //IDbTypeBuilder typeBuilder = MapRepository.Instance.DbTypeBuilder;
+8
View File
@@ -68,5 +68,13 @@ namespace Marr.Data.QGen.Dialects
{ {
get { return "({0} LIKE '%' + {1} + '%')"; } get { return "({0} LIKE '%' + {1} + '%')"; }
} }
public virtual string InFormat
{
get
{
return "({0} in ({1}))";
}
}
} }
} }
+12 -2
View File
@@ -1,4 +1,5 @@
using System.Text; using System.Linq;
using System.Text;
using Marr.Data.Mapping; using Marr.Data.Mapping;
using Marr.Data.QGen.Dialects; using Marr.Data.QGen.Dialects;
@@ -129,7 +130,16 @@ namespace Marr.Data.QGen
public void BuildOrderClause(StringBuilder sql) public void BuildOrderClause(StringBuilder sql)
{ {
sql.Append(OrderBy.ToString()); sql.Append(OrderBy.ToString());
} }
public void BuildGroupBy(StringBuilder sql)
{
var baseTable = this.Tables.First();
var primaryKeyColumn = baseTable.Columns.Single(c => c.ColumnInfo.IsPrimaryKey);
string token = this.Dialect.CreateToken(string.Concat(baseTable.Alias, ".", primaryKeyColumn.ColumnInfo.Name));
sql.AppendFormat(" GROUP BY {0}", token);
}
private string TranslateJoin(JoinType join) private string TranslateJoin(JoinType join)
{ {
@@ -14,8 +14,22 @@ namespace Marr.Data.QGen
public string Generate() public string Generate()
{ {
StringBuilder sql = new StringBuilder(); StringBuilder sql = new StringBuilder();
BuildSelectCountClause(sql); BuildSelectCountClause(sql);
if (_innerQuery.IsJoin)
{
sql.Append(" FROM (");
_innerQuery.BuildSelectClause(sql);
_innerQuery.BuildFromClause(sql);
_innerQuery.BuildJoinClauses(sql);
_innerQuery.BuildWhereClause(sql);
_innerQuery.BuildGroupBy(sql);
sql.Append(") ");
return sql.ToString();
}
_innerQuery.BuildFromClause(sql); _innerQuery.BuildFromClause(sql);
_innerQuery.BuildJoinClauses(sql); _innerQuery.BuildJoinClauses(sql);
_innerQuery.BuildWhereClause(sql); _innerQuery.BuildWhereClause(sql);
+47 -15
View File
@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
using System.Text; using System.Text;
using System.Linq.Expressions; using System.Linq.Expressions;
using System.Data.Common; using System.Data.Common;
@@ -92,6 +93,10 @@ namespace Marr.Data.QGen
case "EndsWith": case "EndsWith":
Write_EndsWith(expression); Write_EndsWith(expression);
break; break;
case "In":
Write_In(expression);
break;
default: default:
string msg = string.Format("'{0}' expressions are not yet implemented in the where clause expression tree parser.", method); string msg = string.Format("'{0}' expressions are not yet implemented in the where clause expression tree parser.", method);
@@ -140,31 +145,47 @@ namespace Marr.Data.QGen
return expression; return expression;
} }
private object GetRightValue(Expression rightExpression) private object GetRightValue(Expression expression)
{ {
object rightValue = null; object rightValue = null;
var right = rightExpression as ConstantExpression; var simpleConstExp = expression as ConstantExpression;
if (right == null) // Value is not directly passed in as a constant if (simpleConstExp == null) // Value is not directly passed in as a constant
{ {
var rightMemberExp = (rightExpression as MemberExpression); MemberExpression memberExp = expression as MemberExpression;
var parentMemberExpression = rightMemberExp.Expression as MemberExpression; ConstantExpression constExp = null;
if (parentMemberExpression != null) // Value is passed in as a property on a parent entity
// Value may be nested in multiple levels of objects/properties, so traverse the MemberExpressions
// until a ConstantExpression property value is found, and then unwind the stack to get the value.
var memberNames = new Stack<string>();
while (memberExp != null)
{ {
string entityName = (rightMemberExp.Expression as MemberExpression).Member.Name; memberNames.Push(memberExp.Member.Name);
var container = ((rightMemberExp.Expression as MemberExpression).Expression as ConstantExpression).Value;
var entity = _repos.ReflectionStrategy.GetFieldValue(container, entityName); // Function calls are not supported - user needs to simplify their Where expression.
rightValue = _repos.ReflectionStrategy.GetFieldValue(entity, rightMemberExp.Member.Name); var methodExp = memberExp.Expression as MethodCallExpression;
if (methodExp != null)
{
var errMsg = string.Format("Function calls are not supported by the Where clause expression parser. Please evaluate your function call, '{0}', manually and then use the resulting paremeter value in your Where expression.", methodExp.Method.Name);
throw new NotSupportedException(errMsg);
}
constExp = memberExp.Expression as ConstantExpression;
memberExp = memberExp.Expression as MemberExpression;
} }
else // Value is passed in as a variable
object entity = constExp.Value;
while (memberNames.Count > 0)
{ {
var parent = (rightMemberExp.Expression as ConstantExpression).Value; string entityName = memberNames.Pop();
rightValue = _repos.ReflectionStrategy.GetFieldValue(parent, rightMemberExp.Member.Name); entity = _repos.ReflectionStrategy.GetFieldValue(entity, entityName);
} }
rightValue = entity;
} }
else // Value is passed in directly as a constant else // Value is passed in directly as a constant
{ {
rightValue = right.Value; rightValue = simpleConstExp.Value;
} }
return rightValue; return rightValue;
@@ -238,6 +259,17 @@ namespace Marr.Data.QGen
_sb.AppendFormat(_dialect.ContainsFormat, fqColumn, paramName); _sb.AppendFormat(_dialect.ContainsFormat, fqColumn, paramName);
} }
private void Write_In(MethodCallExpression body)
{
object value = GetRightValue(body.Arguments[1]);
//string paramName = string.Concat(_paramPrefix, "P", _command.Parameters.Count.ToString());
//var parameter = new ParameterChainMethods(_command, paramName, value).Parameter;
MemberExpression memberExp = (body.Arguments[0] as MemberExpression);
string fqColumn = GetFullyQualifiedColumnName(memberExp.Member, memberExp.Expression.Type);
_sb.AppendFormat(_dialect.InFormat, fqColumn, string.Join(",", value as List<int>));
}
private void Write_StartsWith(MethodCallExpression body) private void Write_StartsWith(MethodCallExpression body)
{ {
// Add parameter to Command.Parameters // Add parameter to Command.Parameters
@@ -70,6 +70,7 @@ namespace NzbDrone.Api.Authentication
{ {
RedirectUrl = _configFileProvider.UrlBase + "/login", RedirectUrl = _configFileProvider.UrlBase + "/login",
UserMapper = _authenticationService, UserMapper = _authenticationService,
Path = _configFileProvider.UrlBase,
CryptographyConfiguration = cryptographyConfiguration CryptographyConfiguration = cryptographyConfiguration
}); });
} }
@@ -46,7 +46,7 @@ namespace NzbDrone.Api.ClientSchema
field.Value = value; field.Value = value;
} }
if (fieldAttribute.Type == FieldType.Select) if (fieldAttribute.Type == FieldType.Select || fieldAttribute.Type == FieldType.Tag)
{ {
field.SelectOptions = GetSelectOptions(fieldAttribute.SelectOptions); field.SelectOptions = GetSelectOptions(fieldAttribute.SelectOptions);
} }
@@ -150,7 +150,7 @@ namespace NzbDrone.Api.ClientSchema
private static List<SelectOption> GetSelectOptions(Type selectOptions) private static List<SelectOption> GetSelectOptions(Type selectOptions)
{ {
if (selectOptions == typeof(Profile)) if (selectOptions == null || selectOptions == typeof(Profile))
{ {
return new List<SelectOption>(); return new List<SelectOption>();
} }
@@ -165,7 +165,7 @@ namespace NzbDrone.Api.ClientSchema
var options = from Enum e in Enum.GetValues(selectOptions) var options = from Enum e in Enum.GetValues(selectOptions)
select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() }; select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() };
return options.OrderBy(o => o.Value).ToList(); return options.OrderBy(o => o.Name).ToList();
} }
} }
} }
+12 -2
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NLog;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Api.Validation; using NzbDrone.Api.Validation;
using NzbDrone.Common; using NzbDrone.Common;
@@ -17,14 +18,17 @@ namespace NzbDrone.Api.Commands
{ {
private readonly IManageCommandQueue _commandQueueManager; private readonly IManageCommandQueue _commandQueueManager;
private readonly IServiceFactory _serviceFactory; private readonly IServiceFactory _serviceFactory;
private readonly Logger _logger;
public CommandModule(IManageCommandQueue commandQueueManager, public CommandModule(IManageCommandQueue commandQueueManager,
IBroadcastSignalRMessage signalRBroadcaster, IBroadcastSignalRMessage signalRBroadcaster,
IServiceFactory serviceFactory) IServiceFactory serviceFactory,
Logger logger)
: base(signalRBroadcaster) : base(signalRBroadcaster)
{ {
_commandQueueManager = commandQueueManager; _commandQueueManager = commandQueueManager;
_serviceFactory = serviceFactory; _serviceFactory = serviceFactory;
_logger = logger;
GetResourceById = GetCommand; GetResourceById = GetCommand;
CreateResource = StartCommand; CreateResource = StartCommand;
@@ -41,7 +45,13 @@ namespace NzbDrone.Api.Commands
private int StartCommand(CommandResource commandResource) private int StartCommand(CommandResource commandResource)
{ {
var commandType = _serviceFactory.GetImplementations(typeof(Command)) var commandType = _serviceFactory.GetImplementations(typeof(Command))
.Single(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase)); .SingleOrDefault(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
if (commandType == null)
{
_logger.Error("Found no matching command for {0}", commandResource.Name);
return 0;
}
dynamic command = Request.Body.FromJson(commandType); dynamic command = Request.Body.FromJson(commandType);
command.Trigger = CommandTrigger.Manual; command.Trigger = CommandTrigger.Manual;
@@ -1,5 +1,6 @@
using NzbDrone.Api.REST; using NzbDrone.Api.REST;
using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration;
using NzbDrone.Core.Parser;
namespace NzbDrone.Api.Config namespace NzbDrone.Api.Config
{ {
@@ -8,9 +9,11 @@ namespace NzbDrone.Api.Config
public int MinimumAge { get; set; } public int MinimumAge { get; set; }
public int Retention { get; set; } public int Retention { get; set; }
public int RssSyncInterval { get; set; } public int RssSyncInterval { get; set; }
public int AvailabilityDelay { get; set; } public bool PreferIndexerFlags { get; set; }
public bool AllowHardcodedSubs { get; set; } public int AvailabilityDelay { get; set; }
public string WhitelistedHardcodedSubs { get; set; } public bool AllowHardcodedSubs { get; set; }
public string WhitelistedHardcodedSubs { get; set; }
public ParsingLeniencyType ParsingLeniency { get; set; }
} }
public static class IndexerConfigResourceMapper public static class IndexerConfigResourceMapper
@@ -22,10 +25,11 @@ namespace NzbDrone.Api.Config
MinimumAge = model.MinimumAge, MinimumAge = model.MinimumAge,
Retention = model.Retention, Retention = model.Retention,
RssSyncInterval = model.RssSyncInterval, RssSyncInterval = model.RssSyncInterval,
AvailabilityDelay = model.AvailabilityDelay, PreferIndexerFlags = model.PreferIndexerFlags,
AllowHardcodedSubs = model.AllowHardcodedSubs, AvailabilityDelay = model.AvailabilityDelay,
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs, AllowHardcodedSubs = model.AllowHardcodedSubs,
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs,
ParsingLeniency = model.ParsingLeniency,
}; };
} }
} }
@@ -11,6 +11,8 @@ namespace NzbDrone.Api.Config
public bool AutoDownloadPropers { get; set; } public bool AutoDownloadPropers { get; set; }
public bool CreateEmptySeriesFolders { get; set; } public bool CreateEmptySeriesFolders { get; set; }
public FileDateType FileDate { get; set; } public FileDateType FileDate { get; set; }
public bool AutoRenameFolders { get; set; }
public bool PathsDefaultStatic { get; set; }
public bool SetPermissionsLinux { get; set; } public bool SetPermissionsLinux { get; set; }
public string FileChmod { get; set; } public string FileChmod { get; set; }
@@ -35,6 +37,8 @@ namespace NzbDrone.Api.Config
AutoDownloadPropers = model.AutoDownloadPropers, AutoDownloadPropers = model.AutoDownloadPropers,
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders, CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
FileDate = model.FileDate, FileDate = model.FileDate,
AutoRenameFolders = model.AutoRenameFolders,
PathsDefaultStatic = model.PathsDefaultStatic,
SetPermissionsLinux = model.SetPermissionsLinux, SetPermissionsLinux = model.SetPermissionsLinux,
FileChmod = model.FileChmod, FileChmod = model.FileChmod,
@@ -0,0 +1,46 @@
using System;
using Nancy;
using Nancy.Bootstrapper;
using Nancy.Responses;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
namespace NzbDrone.Api.Extensions.Pipelines
{
public class UrlBasePipeline : IRegisterNancyPipeline
{
private readonly string _urlBase;
public UrlBasePipeline(IConfigFileProvider configFileProvider)
{
_urlBase = configFileProvider.UrlBase;
}
public int Order => 99;
public void Register(IPipelines pipelines)
{
if (_urlBase.IsNotNullOrWhiteSpace())
{
pipelines.BeforeRequest.AddItemToStartOfPipeline((Func<NancyContext, Response>) Handle);
}
}
private Response Handle(NancyContext context)
{
var basePath = context.Request.Url.BasePath;
if (basePath.IsNullOrWhiteSpace())
{
return new RedirectResponse($"{_urlBase}{context.Request.Path}{context.Request.Url.Query}");
}
if (_urlBase != basePath)
{
return new NotFoundResponse();
}
return null;
}
}
}
@@ -1,4 +1,4 @@
using System; using System;
using System.IO; using System.IO;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Nancy; using Nancy;
@@ -17,7 +17,7 @@ namespace NzbDrone.Api.Frontend.Mappers
private readonly IAnalyticsService _analyticsService; private readonly IAnalyticsService _analyticsService;
private readonly Func<ICacheBreakerProvider> _cacheBreakProviderFactory; private readonly Func<ICacheBreakerProvider> _cacheBreakProviderFactory;
private readonly string _indexPath; private readonly string _indexPath;
private static readonly Regex ReplaceRegex = new Regex(@"(?:(?<attribute>href|src)=\"")(?<path>.*?(?<extension>css|js|png|ico|ics))(?:\"")(?:\s(?<nohash>data-no-hash))?", RegexOptions.Compiled | RegexOptions.IgnoreCase); private static readonly Regex ReplaceRegex = new Regex(@"(?:(?<attribute>href|src|content)=\"")(?<path>.*?(?<extension>css|js|png|ico|ics|svg|json|xml))(?:\"")(?:\s(?<nohash>data-no-hash))?", RegexOptions.Compiled | RegexOptions.IgnoreCase);
private static string API_KEY; private static string API_KEY;
private static string URL_BASE; private static string URL_BASE;
@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Nancy.Responses; using Nancy.Responses;
@@ -38,20 +38,6 @@ namespace NzbDrone.Api.Frontend
return new NotFoundResponse(); return new NotFoundResponse();
} }
//Redirect to the subfolder if the request went to the base URL
if (path.Equals("/"))
{
var urlBase = _configFileProvider.UrlBase;
if (!string.IsNullOrEmpty(urlBase))
{
if (Request.Url.BasePath != urlBase)
{
return new RedirectResponse(urlBase + "/");
}
}
}
var mapper = _requestMappers.SingleOrDefault(m => m.CanHandle(path)); var mapper = _requestMappers.SingleOrDefault(m => m.CanHandle(path));
if (mapper != null) if (mapper != null)
+2 -2
View File
@@ -46,7 +46,7 @@ namespace NzbDrone.Api.Indexers
GetResourceAll = GetReleases; GetResourceAll = GetReleases;
Post["/"] = x => DownloadRelease(this.Bind<ReleaseResource>()); Post["/"] = x => DownloadRelease(this.Bind<ReleaseResource>());
PostValidator.RuleFor(s => s.DownloadAllowed).Equal(true); //PostValidator.RuleFor(s => s.DownloadAllowed).Equal(true);
PostValidator.RuleFor(s => s.Guid).NotEmpty(); PostValidator.RuleFor(s => s.Guid).NotEmpty();
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes"); _remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
@@ -70,7 +70,7 @@ namespace NzbDrone.Api.Indexers
try try
{ {
_downloadService.DownloadReport(remoteMovie); _downloadService.DownloadReport(remoteMovie, false);
} }
catch (ReleaseDownloadException ex) catch (ReleaseDownloadException ex)
{ {
+18 -12
View File
@@ -8,6 +8,7 @@ using NzbDrone.Core.Indexers;
using NzbDrone.Core.Parser.Model; using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.DecisionEngine;
using System.Linq; using System.Linq;
using NzbDrone.Core.Datastore.Migration;
namespace NzbDrone.Api.Indexers namespace NzbDrone.Api.Indexers
{ {
@@ -29,8 +30,8 @@ namespace NzbDrone.Api.Indexers
public bool FullSeason { get; set; } public bool FullSeason { get; set; }
public int SeasonNumber { get; set; } public int SeasonNumber { get; set; }
public Language Language { get; set; } public Language Language { get; set; }
public string AirDate { get; set; } public int Year { get; set; }
public string SeriesTitle { get; set; } public string MovieTitle { get; set; }
public int[] EpisodeNumbers { get; set; } public int[] EpisodeNumbers { get; set; }
public int[] AbsoluteEpisodeNumbers { get; set; } public int[] AbsoluteEpisodeNumbers { get; set; }
public bool Approved { get; set; } public bool Approved { get; set; }
@@ -43,9 +44,11 @@ namespace NzbDrone.Api.Indexers
public string CommentUrl { get; set; } public string CommentUrl { get; set; }
public string DownloadUrl { get; set; } public string DownloadUrl { get; set; }
public string InfoUrl { get; set; } public string InfoUrl { get; set; }
public bool DownloadAllowed { get; set; } public MappingResultType MappingResult { get; set; }
public int ReleaseWeight { get; set; } public int ReleaseWeight { get; set; }
public int SuspectedMovieId { get; set; }
public IEnumerable<string> IndexerFlags { get; set; }
public string MagnetUrl { get; set; } public string MagnetUrl { get; set; }
public string InfoHash { get; set; } public string InfoHash { get; set; }
@@ -87,11 +90,12 @@ namespace NzbDrone.Api.Indexers
var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo; var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo;
var remoteEpisode = model.RemoteEpisode; var remoteEpisode = model.RemoteEpisode;
var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo(); var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo();
var downloadAllowed = model.RemoteEpisode.DownloadAllowed; var mappingResult = MappingResultType.Success;
if (model.IsForMovie) if (model.IsForMovie)
{ {
downloadAllowed = model.RemoteMovie.DownloadAllowed; mappingResult = model.RemoteMovie.MappingResult;
var parsedMovieInfo = model.RemoteMovie.ParsedMovieInfo; var parsedMovieInfo = model.RemoteMovie.ParsedMovieInfo;
var movieId = model.RemoteMovie.Movie?.Id ?? 0;
return new ReleaseResource return new ReleaseResource
{ {
@@ -110,8 +114,8 @@ namespace NzbDrone.Api.Indexers
//FullSeason = parsedMovieInfo.FullSeason, //FullSeason = parsedMovieInfo.FullSeason,
//SeasonNumber = parsedMovieInfo.SeasonNumber, //SeasonNumber = parsedMovieInfo.SeasonNumber,
Language = parsedMovieInfo.Language, Language = parsedMovieInfo.Language,
AirDate = "", Year = parsedMovieInfo.Year,
SeriesTitle = parsedMovieInfo.MovieTitle, MovieTitle = parsedMovieInfo.MovieTitle,
EpisodeNumbers = new int[0], EpisodeNumbers = new int[0],
AbsoluteEpisodeNumbers = new int[0], AbsoluteEpisodeNumbers = new int[0],
Approved = model.Approved, Approved = model.Approved,
@@ -124,15 +128,17 @@ namespace NzbDrone.Api.Indexers
CommentUrl = releaseInfo.CommentUrl, CommentUrl = releaseInfo.CommentUrl,
DownloadUrl = releaseInfo.DownloadUrl, DownloadUrl = releaseInfo.DownloadUrl,
InfoUrl = releaseInfo.InfoUrl, InfoUrl = releaseInfo.InfoUrl,
DownloadAllowed = downloadAllowed, MappingResult = mappingResult,
//ReleaseWeight //ReleaseWeight
SuspectedMovieId = movieId,
MagnetUrl = torrentInfo.MagnetUrl, MagnetUrl = torrentInfo.MagnetUrl,
InfoHash = torrentInfo.InfoHash, InfoHash = torrentInfo.InfoHash,
Seeders = torrentInfo.Seeders, Seeders = torrentInfo.Seeders,
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null, Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
Protocol = releaseInfo.DownloadProtocol, Protocol = releaseInfo.DownloadProtocol,
IndexerFlags = torrentInfo.IndexerFlags.ToString().Split(new string[] { ", " }, StringSplitOptions.None),
Edition = parsedMovieInfo.Edition, Edition = parsedMovieInfo.Edition,
IsDaily = false, IsDaily = false,
@@ -160,8 +166,8 @@ namespace NzbDrone.Api.Indexers
FullSeason = parsedEpisodeInfo.FullSeason, FullSeason = parsedEpisodeInfo.FullSeason,
SeasonNumber = parsedEpisodeInfo.SeasonNumber, SeasonNumber = parsedEpisodeInfo.SeasonNumber,
Language = parsedEpisodeInfo.Language, Language = parsedEpisodeInfo.Language,
AirDate = parsedEpisodeInfo.AirDate, //AirDate = parsedEpisodeInfo.AirDate,
SeriesTitle = parsedEpisodeInfo.SeriesTitle, //SeriesTitle = parsedEpisodeInfo.SeriesTitle,
EpisodeNumbers = parsedEpisodeInfo.EpisodeNumbers, EpisodeNumbers = parsedEpisodeInfo.EpisodeNumbers,
AbsoluteEpisodeNumbers = parsedEpisodeInfo.AbsoluteEpisodeNumbers, AbsoluteEpisodeNumbers = parsedEpisodeInfo.AbsoluteEpisodeNumbers,
Approved = model.Approved, Approved = model.Approved,
@@ -174,7 +180,7 @@ namespace NzbDrone.Api.Indexers
CommentUrl = releaseInfo.CommentUrl, CommentUrl = releaseInfo.CommentUrl,
DownloadUrl = releaseInfo.DownloadUrl, DownloadUrl = releaseInfo.DownloadUrl,
InfoUrl = releaseInfo.InfoUrl, InfoUrl = releaseInfo.InfoUrl,
DownloadAllowed = downloadAllowed, //DownloadAllowed = downloadAllowed,
//ReleaseWeight //ReleaseWeight
MagnetUrl = torrentInfo.MagnetUrl, MagnetUrl = torrentInfo.MagnetUrl,
@@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Marr.Data;
using Nancy;
using NzbDrone.Api;
using NzbDrone.Api.Movie;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.EpisodeImport;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.RadarrAPI;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Api.Movie
{
public class AlternativeTitleModule : NzbDroneRestModule<AlternativeTitleResource>
{
private readonly IAlternativeTitleService _altTitleService;
private readonly IMovieService _movieService;
private readonly IRadarrAPIClient _radarrApi;
private readonly IEventAggregator _eventAggregator;
public AlternativeTitleModule(IAlternativeTitleService altTitleService, IMovieService movieService, IRadarrAPIClient radarrApi, IEventAggregator eventAggregator)
: base("/alttitle")
{
_altTitleService = altTitleService;
_movieService = movieService;
_radarrApi = radarrApi;
CreateResource = AddTitle;
GetResourceById = GetTitle;
_eventAggregator = eventAggregator;
}
private int AddTitle(AlternativeTitleResource altTitle)
{
var title = altTitle.ToModel();
var movie = _movieService.GetMovie(altTitle.MovieId);
var newTitle = _radarrApi.AddNewAlternativeTitle(title, movie.TmdbId);
var addedTitle = _altTitleService.AddAltTitle(newTitle, movie);
_eventAggregator.PublishEvent(new MovieUpdatedEvent(movie));
return addedTitle.Id;
}
private AlternativeTitleResource GetTitle(int id)
{
return _altTitleService.GetById(id).ToResource();
}
}
}
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Marr.Data;
using Nancy;
using NzbDrone.Api;
using NzbDrone.Api.Movie;
using NzbDrone.Common.Cache;
using NzbDrone.Common.Extensions;
using NzbDrone.Common.Messaging;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.MediaFiles.EpisodeImport;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.Core.MetadataSource;
using NzbDrone.Core.MetadataSource.RadarrAPI;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.RootFolders;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Tv.Events;
namespace NzbDrone.Api.Movie
{
public class AlternativeYearModule : NzbDroneRestModule<AlternativeYearResource>
{
private readonly IMovieService _movieService;
private readonly IRadarrAPIClient _radarrApi;
private readonly ICached<int> _yearCache;
private readonly IEventAggregator _eventAggregator;
public AlternativeYearModule(IMovieService movieService, IRadarrAPIClient radarrApi, ICacheManager cacheManager, IEventAggregator eventAggregator)
: base("/altyear")
{
_movieService = movieService;
_radarrApi = radarrApi;
CreateResource = AddYear;
GetResourceById = GetYear;
_yearCache = cacheManager.GetCache<int>(GetType(), "altYears");
_eventAggregator = eventAggregator;
}
private int AddYear(AlternativeYearResource altYear)
{
var id = new Random().Next();
_yearCache.Set(id.ToString(), altYear.Year, TimeSpan.FromMinutes(1));
var movie = _movieService.GetMovie(altYear.MovieId);
var newYear = _radarrApi.AddNewAlternativeYear(altYear.Year, movie.TmdbId);
movie.SecondaryYear = newYear.Year;
movie.SecondaryYearSourceId = newYear.SourceId;
_movieService.UpdateMovie(movie);
_eventAggregator.PublishEvent(new MovieUpdatedEvent(movie));
return id;
}
private AlternativeYearResource GetYear(int id)
{
return new AlternativeYearResource
{
Year = _yearCache.Find(id.ToString())
};
}
}
}
@@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Api.REST;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Api.Series;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.Parser;
namespace NzbDrone.Api.Movie
{
public class AlternativeYearResource : RestResource
{
public AlternativeYearResource()
{
}
//Todo: Sorters should be done completely on the client
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
//Todo: We should get the entire Profile instead of ID and Name separately
public int MovieId { get; set; }
public int Year { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties)
}
/*public static class AlternativeYearResourceMapper
{
/*public static AlternativeYearResource ToResource(this AlternativeTitle model)
{
if (model == null) return null;
AlternativeTitleResource resource = null;
return new AlternativeTitleResource
{
Id = model.Id,
SourceType = model.SourceType,
MovieId = model.MovieId,
Title = model.Title,
SourceId = model.SourceId,
Votes = model.Votes,
VoteCount = model.VoteCount,
Language = model.Language
};
}
public static AlternativeTitle ToModel(this AlternativeTitleResource resource)
{
if (resource == null) return null;
return new AlternativeTitle
{
Id = resource.Id,
SourceType = resource.SourceType,
MovieId = resource.MovieId,
Title = resource.Title,
SourceId = resource.SourceId,
Votes = resource.Votes,
VoteCount = resource.VoteCount,
Language = resource.Language
};
}
public static List<AlternativeTitleResource> ToResource(this IEnumerable<AlternativeTitle> movies)
{
return movies.Select(ToResource).ToList();
}
}*/
}
@@ -90,7 +90,7 @@ namespace NzbDrone.Api.Movie
return mappedMovie; return mappedMovie;
} }
var parsedTitle = Parser.ParseMoviePath(f.Name); var parsedTitle = Parser.ParseMoviePath(f.Name, false);
if (parsedTitle == null) if (parsedTitle == null)
{ {
m = new Core.Tv.Movie m = new Core.Tv.Movie
+33 -1
View File
@@ -1,7 +1,10 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using Nancy; using Nancy;
using Nancy.Responses;
using NzbDrone.Api.Extensions; using NzbDrone.Api.Extensions;
using NzbDrone.Api.REST;
using NzbDrone.Core.Tv; using NzbDrone.Core.Tv;
namespace NzbDrone.Api.Movie namespace NzbDrone.Api.Movie
@@ -15,6 +18,7 @@ namespace NzbDrone.Api.Movie
{ {
_movieService = movieService; _movieService = movieService;
Put["/"] = Movie => SaveAll(); Put["/"] = Movie => SaveAll();
Put["/delete"] = Movie => DeleteSelected();
} }
private Response SaveAll() private Response SaveAll()
@@ -27,5 +31,33 @@ namespace NzbDrone.Api.Movie
.ToResource() .ToResource()
.AsResponse(HttpStatusCode.Accepted); .AsResponse(HttpStatusCode.Accepted);
} }
private Response DeleteSelected()
{
var deleteFiles = false;
var addExclusion = false;
var deleteFilesQuery = Request.Query.deleteFiles;
var addExclusionQuery = Request.Query.addExclusion;
if (deleteFilesQuery.HasValue)
{
deleteFiles = Convert.ToBoolean(deleteFilesQuery.Value);
}
if (addExclusionQuery.HasValue)
{
addExclusion = Convert.ToBoolean(addExclusionQuery.Value);
}
var ids = Request.Body.FromJson<List<int>>();
foreach (var id in ids)
{
_movieService.DeleteMovie(id, deleteFiles, addExclusion);
}
return new Response
{
StatusCode = HttpStatusCode.Accepted
};
}
} }
} }
+4 -1
View File
@@ -46,11 +46,14 @@ namespace NzbDrone.Api.EpisodeFiles
return movie.ToResource(); return movie.ToResource();
} }
private void SetQuality(MovieFileResource movieFileResource) private void SetQuality(MovieFileResource movieFileResource)
{ {
var movieFile = _mediaFileService.GetMovie(movieFileResource.Id); var movieFile = _mediaFileService.GetMovie(movieFileResource.Id);
movieFile.Quality = movieFileResource.Quality; movieFile.Quality = movieFileResource.Quality;
_mediaFileService.Update(movieFile); _mediaFileService.Update(movieFile);
BroadcastResourceChange(ModelAction.Updated, movieFile.Id);
} }
private void DeleteMovieFile(int id) private void DeleteMovieFile(int id)
@@ -0,0 +1,45 @@
using System.Collections.Generic;
using FluentValidation;
using NzbDrone.Api.ClientSchema;
using NzbDrone.Core.NetImport;
using NzbDrone.Core.NetImport.ImportExclusions;
using NzbDrone.Core.Validation.Paths;
namespace NzbDrone.Api.NetImport
{
public class ImportExclusionsModule : NzbDroneRestModule<ImportExclusionsResource>
{
private readonly IImportExclusionsService _exclusionService;
public ImportExclusionsModule(NetImportFactory netImportFactory, IImportExclusionsService exclusionService) : base("exclusions")
{
_exclusionService = exclusionService;
GetResourceAll = GetAll;
CreateResource = AddExclusion;
DeleteResource = RemoveExclusion;
GetResourceById = GetById;
}
public List<ImportExclusionsResource> GetAll()
{
return _exclusionService.GetAllExclusions().ToResource();
}
public ImportExclusionsResource GetById(int id)
{
return _exclusionService.GetById(id).ToResource();
}
public int AddExclusion(ImportExclusionsResource exclusionResource)
{
var model = exclusionResource.ToModel();
return _exclusionService.AddExclusion(model).Id;
}
public void RemoveExclusion (int id)
{
_exclusionService.RemoveExclusion(new ImportExclusion { Id = id });
}
}
}
@@ -0,0 +1,46 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Core.NetImport;
using NzbDrone.Core.Tv;
namespace NzbDrone.Api.NetImport
{
public class ImportExclusionsResource : ProviderResource
{
//public int Id { get; set; }
public int TmdbId { get; set; }
public string MovieTitle { get; set; }
public int MovieYear { get; set; }
}
public static class ImportExclusionsResourceMapper
{
public static ImportExclusionsResource ToResource(this Core.NetImport.ImportExclusions.ImportExclusion model)
{
if (model == null) return null;
return new ImportExclusionsResource
{
Id = model.Id,
TmdbId = model.TmdbId,
MovieTitle = model.MovieTitle,
MovieYear = model.MovieYear
};
}
public static List<ImportExclusionsResource> ToResource(this IEnumerable<Core.NetImport.ImportExclusions.ImportExclusion> exclusions)
{
return exclusions.Select(ToResource).ToList();
}
public static Core.NetImport.ImportExclusions.ImportExclusion ToModel(this ImportExclusionsResource resource)
{
return new Core.NetImport.ImportExclusions.ImportExclusion
{
TmdbId = resource.TmdbId,
MovieTitle = resource.MovieTitle,
MovieYear = resource.MovieYear
};
}
}
}
@@ -9,7 +9,7 @@ namespace NzbDrone.Api.NetImport
{ {
public NetImportModule(NetImportFactory netImportFactory) : base(netImportFactory, "netimport") public NetImportModule(NetImportFactory netImportFactory) : base(netImportFactory, "netimport")
{ {
PostValidator.RuleFor(c => c.RootFolderPath).NotNull(); PostValidator.RuleFor(c => c.RootFolderPath).IsValidPath();
PostValidator.RuleFor(c => c.MinimumAvailability).NotNull(); PostValidator.RuleFor(c => c.MinimumAvailability).NotNull();
PostValidator.RuleFor(c => c.ProfileId).NotNull(); PostValidator.RuleFor(c => c.ProfileId).NotNull();
} }
+8 -1
View File
@@ -113,11 +113,15 @@
<Compile Include="Config\NetImportConfigResource.cs" /> <Compile Include="Config\NetImportConfigResource.cs" />
<Compile Include="Extensions\AccessControlHeaders.cs" /> <Compile Include="Extensions\AccessControlHeaders.cs" />
<Compile Include="Extensions\Pipelines\CorsPipeline.cs" /> <Compile Include="Extensions\Pipelines\CorsPipeline.cs" />
<Compile Include="Extensions\Pipelines\UrlBasePipeline.cs" />
<Compile Include="Extensions\Pipelines\RequestLoggingPipeline.cs" /> <Compile Include="Extensions\Pipelines\RequestLoggingPipeline.cs" />
<Compile Include="Frontend\Mappers\LoginHtmlMapper.cs" /> <Compile Include="Frontend\Mappers\LoginHtmlMapper.cs" />
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" /> <Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
<Compile Include="Indexers\ReleaseModuleBase.cs" /> <Compile Include="Indexers\ReleaseModuleBase.cs" />
<Compile Include="Indexers\ReleasePushModule.cs" /> <Compile Include="Indexers\ReleasePushModule.cs" />
<Compile Include="Movies\AlternativeTitleModule.cs" />
<Compile Include="Movies\AlternativeYearResource.cs" />
<Compile Include="Movies\AlternativeYearModule.cs" />
<Compile Include="Movies\MovieModuleWithSignalR.cs" /> <Compile Include="Movies\MovieModuleWithSignalR.cs" />
<Compile Include="Movies\MovieBulkImportModule.cs" /> <Compile Include="Movies\MovieBulkImportModule.cs" />
<Compile Include="Movies\MovieFileModule.cs" /> <Compile Include="Movies\MovieFileModule.cs" />
@@ -239,7 +243,7 @@
<Compile Include="RootFolders\RootFolderModule.cs" /> <Compile Include="RootFolders\RootFolderModule.cs" />
<Compile Include="RootFolders\RootFolderResource.cs" /> <Compile Include="RootFolders\RootFolderResource.cs" />
<Compile Include="SeasonPass\SeasonPassResource.cs" /> <Compile Include="SeasonPass\SeasonPassResource.cs" />
<Compile Include="Series\AlternateTitleResource.cs" /> <Compile Include="Series\AlternativeTitleResource.cs" />
<Compile Include="Series\MovieFileResource.cs" /> <Compile Include="Series\MovieFileResource.cs" />
<Compile Include="Series\FetchMovieListModule.cs" /> <Compile Include="Series\FetchMovieListModule.cs" />
<Compile Include="Series\SeasonResource.cs" /> <Compile Include="Series\SeasonResource.cs" />
@@ -270,6 +274,9 @@
<Compile Include="Wanted\MissingModule.cs" /> <Compile Include="Wanted\MissingModule.cs" />
<Compile Include="Wanted\MovieCutoffModule.cs" /> <Compile Include="Wanted\MovieCutoffModule.cs" />
<Compile Include="Wanted\MovieMissingModule.cs" /> <Compile Include="Wanted\MovieMissingModule.cs" />
<Compile Include="Series\MovieDiscoverModule.cs" />
<Compile Include="NetImport\ImportExclusionsModule.cs" />
<Compile Include="NetImport\ImportExclusionsResource.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />
+1 -1
View File
@@ -105,7 +105,7 @@ namespace NzbDrone.Api.Queue
throw new NotFoundException(); throw new NotFoundException();
} }
_downloadService.DownloadReport(pendingRelease.RemoteMovie); _downloadService.DownloadReport(pendingRelease.RemoteMovie, false);
return resource.AsResponse(); return resource.AsResponse();
} }
@@ -1,9 +0,0 @@
namespace NzbDrone.Api.Series
{
public class AlternateTitleResource
{
public string Title { get; set; }
public int? SeasonNumber { get; set; }
public int? SceneSeasonNumber { get; set; }
}
}
@@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Api.REST;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Qualities;
using NzbDrone.Api.Series;
using NzbDrone.Core.MediaFiles;
using NzbDrone.Core.Movies.AlternativeTitles;
using NzbDrone.Core.Parser;
namespace NzbDrone.Api.Movie
{
public class AlternativeTitleResource : RestResource
{
public AlternativeTitleResource()
{
}
//Todo: Sorters should be done completely on the client
//Todo: Is there an easy way to keep IgnoreArticlesWhenSorting in sync between, Series, History, Missing?
//Todo: We should get the entire Profile instead of ID and Name separately
public SourceType SourceType { get; set; }
public int MovieId { get; set; }
public string Title { get; set; }
public string CleanTitle { get; set; }
public int SourceId { get; set; }
public int Votes { get; set; }
public int VoteCount { get; set; }
public Language Language { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties)
}
public static class AlternativeTitleResourceMapper
{
public static AlternativeTitleResource ToResource(this AlternativeTitle model)
{
if (model == null) return null;
AlternativeTitleResource resource = null;
return new AlternativeTitleResource
{
Id = model.Id,
SourceType = model.SourceType,
MovieId = model.MovieId,
Title = model.Title,
SourceId = model.SourceId,
Votes = model.Votes,
VoteCount = model.VoteCount,
Language = model.Language
};
}
public static AlternativeTitle ToModel(this AlternativeTitleResource resource)
{
if (resource == null) return null;
return new AlternativeTitle
{
Id = resource.Id,
SourceType = resource.SourceType,
MovieId = resource.MovieId,
Title = resource.Title,
SourceId = resource.SourceId,
Votes = resource.Votes,
VoteCount = resource.VoteCount,
Language = resource.Language
};
}
public static List<AlternativeTitleResource> ToResource(this IEnumerable<AlternativeTitle> movies)
{
return movies.Select(ToResource).ToList();
}
}
}
@@ -0,0 +1,63 @@
using System.Collections.Generic;
using Nancy;
using NzbDrone.Api.Extensions;
using NzbDrone.Core.MediaCover;
using NzbDrone.Core.MetadataSource;
using System.Linq;
using System;
using NzbDrone.Api.REST;
using NzbDrone.Core.NetImport;
using NzbDrone.Api.NetImport;
namespace NzbDrone.Api.Movie
{
public class MovieDiscoverModule : NzbDroneRestModule<MovieResource>
{
private readonly IDiscoverNewMovies _searchProxy;
private readonly INetImportFactory _netImportFactory;
public MovieDiscoverModule(IDiscoverNewMovies searchProxy, INetImportFactory netImportFactory)
: base("/movies/discover")
{
_searchProxy = searchProxy;
_netImportFactory = netImportFactory;
Get["/lists"] = x => GetLists();
Get["/{action?recommendations}"] = x => Search(x.action);
}
private Response Search(string action)
{
var imdbResults = _searchProxy.DiscoverNewMovies(action);
return MapToResource(imdbResults).AsResponse();
}
private Response GetLists()
{
var lists = _netImportFactory.Discoverable();
return lists.Select(definition => {
var resource = new NetImportResource();
resource.Id = definition.Definition.Id;
resource.Name = definition.Definition.Name;
return resource;
}).AsResponse();
}
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
{
foreach (var currentSeries in movies)
{
var resource = currentSeries.ToResource();
var poster = currentSeries.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
if (poster != null)
{
resource.RemotePoster = poster.Url;
}
yield return resource;
}
}
}
}
+29 -6
View File
@@ -17,6 +17,8 @@ using NzbDrone.Core.DataAugmentation.Scene;
using NzbDrone.Core.Validation; using NzbDrone.Core.Validation;
using NzbDrone.SignalR; using NzbDrone.SignalR;
using NzbDrone.Core.Datastore; using NzbDrone.Core.Datastore;
using Microsoft.CSharp.RuntimeBinder;
using Nancy;
namespace NzbDrone.Api.Movie namespace NzbDrone.Api.Movie
{ {
@@ -58,9 +60,12 @@ namespace NzbDrone.Api.Movie
GetResourceAll = AllMovie; GetResourceAll = AllMovie;
GetResourcePaged = GetMoviePaged; GetResourcePaged = GetMoviePaged;
GetResourceById = GetMovie; GetResourceById = GetMovie;
Get[TITLE_SLUG_ROUTE] = (options) => { Get[TITLE_SLUG_ROUTE] = GetByTitleSlug; /*(options) => {
return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug)); return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug), Nancy.HttpStatusCode.OK);
}; };*/
CreateResource = AddMovie; CreateResource = AddMovie;
UpdateResource = UpdateMovie; UpdateResource = UpdateMovie;
DeleteResource = DeleteMovie; DeleteResource = DeleteMovie;
@@ -145,9 +150,27 @@ namespace NzbDrone.Api.Movie
return moviesResources; return moviesResources;
} }
private MovieResource GetByTitleSlug(string slug) private Response GetByTitleSlug(dynamic options)
{ {
return MapToResource(_moviesService.FindByTitleSlug(slug)); var slug = "";
try
{
slug = options.slug;
// do stuff with x
}
catch (RuntimeBinderException)
{
return new NotFoundResponse();
}
try
{
return MapToResource(_moviesService.FindByTitleSlug(slug)).AsResponse(Nancy.HttpStatusCode.OK);
}
catch (ModelNotFoundException)
{
return new NotFoundResponse();
}
} }
private int AddMovie(MovieResource moviesResource) private int AddMovie(MovieResource moviesResource)
@@ -213,7 +236,7 @@ namespace NzbDrone.Api.Movie
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics) private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
{ {
resource.SizeOnDisk = moviesStatistics.SizeOnDisk; //resource.SizeOnDisk = 0;//TODO: incorporate movie statistics moviesStatistics.SizeOnDisk;
} }
private void PopulateAlternateTitles(List<MovieResource> resources) private void PopulateAlternateTitles(List<MovieResource> resources)
+21 -6
View File
@@ -21,13 +21,16 @@ namespace NzbDrone.Api.Movie
//View Only //View Only
public string Title { get; set; } public string Title { get; set; }
public List<AlternateTitleResource> AlternateTitles { get; set; } public List<AlternativeTitleResource> AlternativeTitles { get; set; }
public int? SecondaryYear { get; set; }
public int SecondaryYearSourceId { get; set; }
public string SortTitle { get; set; } public string SortTitle { get; set; }
public long? SizeOnDisk { get; set; } public long? SizeOnDisk { get; set; }
public MovieStatusType Status { get; set; } public MovieStatusType Status { get; set; }
public string Overview { get; set; } public string Overview { get; set; }
public DateTime? InCinemas { get; set; } public DateTime? InCinemas { get; set; }
public DateTime? PhysicalRelease { get; set; } public DateTime? PhysicalRelease { get; set; }
public string PhysicalReleaseNote { get; set; }
public List<MediaCover> Images { get; set; } public List<MediaCover> Images { get; set; }
public string Website { get; set; } public string Website { get; set; }
public bool Downloaded { get; set; } public bool Downloaded { get; set; }
@@ -40,6 +43,7 @@ namespace NzbDrone.Api.Movie
//View & Edit //View & Edit
public string Path { get; set; } public string Path { get; set; }
public int ProfileId { get; set; } public int ProfileId { get; set; }
public MoviePathState PathState { get; set; }
//Editing Only //Editing Only
public bool Monitored { get; set; } public bool Monitored { get; set; }
@@ -60,7 +64,7 @@ namespace NzbDrone.Api.Movie
public DateTime Added { get; set; } public DateTime Added { get; set; }
public AddMovieOptions AddOptions { get; set; } public AddMovieOptions AddOptions { get; set; }
public Ratings Ratings { get; set; } public Ratings Ratings { get; set; }
public List<string> AlternativeTitles { get; set; } //public List<string> AlternativeTitles { get; set; }
public MovieFileResource MovieFile { get; set; } public MovieFileResource MovieFile { get; set; }
//TODO: Add series statistics as a property of the series (instead of individual properties) //TODO: Add series statistics as a property of the series (instead of individual properties)
@@ -105,6 +109,8 @@ namespace NzbDrone.Api.Movie
downloaded = true; downloaded = true;
movieFile = model.MovieFile.Value.ToResource(); movieFile = model.MovieFile.Value.ToResource();
} }
//model.AlternativeTitles.LazyLoad();
return new MovieResource return new MovieResource
{ {
@@ -115,12 +121,13 @@ namespace NzbDrone.Api.Movie
SortTitle = model.SortTitle, SortTitle = model.SortTitle,
InCinemas = model.InCinemas, InCinemas = model.InCinemas,
PhysicalRelease = model.PhysicalRelease, PhysicalRelease = model.PhysicalRelease,
PhysicalReleaseNote = model.PhysicalReleaseNote,
HasFile = model.HasFile, HasFile = model.HasFile,
Downloaded = downloaded, Downloaded = downloaded,
//TotalEpisodeCount //TotalEpisodeCount
//EpisodeCount //EpisodeCount
//EpisodeFileCount //EpisodeFileCount
//SizeOnDisk SizeOnDisk = size,
Status = model.Status, Status = model.Status,
Overview = model.Overview, Overview = model.Overview,
//NextAiring //NextAiring
@@ -128,9 +135,12 @@ namespace NzbDrone.Api.Movie
Images = model.Images, Images = model.Images,
Year = model.Year, Year = model.Year,
SecondaryYear = model.SecondaryYear,
SecondaryYearSourceId = model.SecondaryYearSourceId,
Path = model.Path, Path = model.Path,
ProfileId = model.ProfileId, ProfileId = model.ProfileId,
PathState = model.PathState,
Monitored = model.Monitored, Monitored = model.Monitored,
MinimumAvailability = model.MinimumAvailability, MinimumAvailability = model.MinimumAvailability,
@@ -138,7 +148,7 @@ namespace NzbDrone.Api.Movie
IsAvailable = model.IsAvailable(), IsAvailable = model.IsAvailable(),
FolderName = model.FolderName(), FolderName = model.FolderName(),
SizeOnDisk = size, //SizeOnDisk = size,
Runtime = model.Runtime, Runtime = model.Runtime,
LastInfoSync = model.LastInfoSync, LastInfoSync = model.LastInfoSync,
@@ -152,7 +162,7 @@ namespace NzbDrone.Api.Movie
Tags = model.Tags, Tags = model.Tags,
Added = model.Added, Added = model.Added,
AddOptions = model.AddOptions, AddOptions = model.AddOptions,
AlternativeTitles = model.AlternativeTitles, AlternativeTitles = model.AlternativeTitles.ToResource(),
Ratings = model.Ratings, Ratings = model.Ratings,
MovieFile = movieFile, MovieFile = movieFile,
YouTubeTrailerId = model.YouTubeTrailerId, YouTubeTrailerId = model.YouTubeTrailerId,
@@ -174,6 +184,7 @@ namespace NzbDrone.Api.Movie
SortTitle = resource.SortTitle, SortTitle = resource.SortTitle,
InCinemas = resource.InCinemas, InCinemas = resource.InCinemas,
PhysicalRelease = resource.PhysicalRelease, PhysicalRelease = resource.PhysicalRelease,
PhysicalReleaseNote = resource.PhysicalReleaseNote,
//TotalEpisodeCount //TotalEpisodeCount
//EpisodeCount //EpisodeCount
//EpisodeFileCount //EpisodeFileCount
@@ -184,9 +195,12 @@ namespace NzbDrone.Api.Movie
Images = resource.Images, Images = resource.Images,
Year = resource.Year, Year = resource.Year,
SecondaryYear = resource.SecondaryYear,
SecondaryYearSourceId = resource.SecondaryYearSourceId,
Path = resource.Path, Path = resource.Path,
ProfileId = resource.ProfileId, ProfileId = resource.ProfileId,
PathState = resource.PathState,
Monitored = resource.Monitored, Monitored = resource.Monitored,
MinimumAvailability = resource.MinimumAvailability, MinimumAvailability = resource.MinimumAvailability,
@@ -203,7 +217,7 @@ namespace NzbDrone.Api.Movie
Tags = resource.Tags, Tags = resource.Tags,
Added = resource.Added, Added = resource.Added,
AddOptions = resource.AddOptions, AddOptions = resource.AddOptions,
AlternativeTitles = resource.AlternativeTitles, //AlternativeTitles = resource.AlternativeTitles,
Ratings = resource.Ratings, Ratings = resource.Ratings,
YouTubeTrailerId = resource.YouTubeTrailerId, YouTubeTrailerId = resource.YouTubeTrailerId,
Studio = resource.Studio Studio = resource.Studio
@@ -217,6 +231,7 @@ namespace NzbDrone.Api.Movie
movie.Path = resource.Path; movie.Path = resource.Path;
movie.ProfileId = resource.ProfileId; movie.ProfileId = resource.ProfileId;
movie.PathState = resource.PathState;
movie.Monitored = resource.Monitored; movie.Monitored = resource.Monitored;
movie.MinimumAvailability = resource.MinimumAvailability; movie.MinimumAvailability = resource.MinimumAvailability;
+1 -1
View File
@@ -199,7 +199,7 @@ namespace NzbDrone.Api.Series
if (mappings == null) return; if (mappings == null) return;
resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList(); //resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
} }
public void Handle(EpisodeImportedEvent message) public void Handle(EpisodeImportedEvent message)
+1 -1
View File
@@ -20,7 +20,7 @@ namespace NzbDrone.Api.Series
//View Only //View Only
public string Title { get; set; } public string Title { get; set; }
public List<AlternateTitleResource> AlternateTitles { get; set; } //public List<AlternativeTitleResource> AlternateTitles { get; set; }
public string SortTitle { get; set; } public string SortTitle { get; set; }
public int SeasonCount public int SeasonCount
+2 -2
View File
@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using NzbDrone.Core.Datastore.Events; using NzbDrone.Core.Datastore.Events;
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.System.Tasks
{ {
private readonly ITaskManager _taskManager; private readonly ITaskManager _taskManager;
private static readonly Regex NameRegex = new Regex("(?<!^)[A-Z]", RegexOptions.Compiled); private static readonly Regex NameRegex = new Regex("(?<!^)[A-Z][a-z]", RegexOptions.Compiled);
public TaskModule(ITaskManager taskManager, IBroadcastSignalRMessage broadcastSignalRMessage) public TaskModule(ITaskManager taskManager, IBroadcastSignalRMessage broadcastSignalRMessage)
: base(broadcastSignalRMessage, "system/task") : base(broadcastSignalRMessage, "system/task")
@@ -29,7 +29,7 @@ namespace NzbDrone.Common.Test.DiskTests
public void should_be_able_to_check_space_on_ramdrive() public void should_be_able_to_check_space_on_ramdrive()
{ {
MonoOnly(); MonoOnly();
Subject.GetAvailableSpace("/run/").Should().NotBe(0); Subject.GetAvailableSpace("/").Should().NotBe(0);
} }
[Test] [Test]
@@ -20,7 +20,6 @@ namespace NzbDrone.Common.Test
} }
[TestCase("")] [TestCase("")]
[TestCase("http://")]
public void DownloadString_should_throw_on_error(string url) public void DownloadString_should_throw_on_error(string url)
{ {
Assert.Throws<ArgumentException>(() => Subject.DownloadString(url)); Assert.Throws<ArgumentException>(() => Subject.DownloadString(url));
+4 -4
View File
@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@@ -108,7 +108,7 @@ namespace NzbDrone.Common.Disk
} }
} }
} }
public bool CanUseGDIPlus() public bool CanUseGDIPlus()
{ {
try try
@@ -129,7 +129,7 @@ namespace NzbDrone.Common.Disk
{ {
return true; return true;
} }
try try
{ {
using (var bmp = new Bitmap(filename)) using (var bmp = new Bitmap(filename))
@@ -150,7 +150,7 @@ namespace NzbDrone.Common.Disk
try try
{ {
var testPath = Path.Combine(path, "sonarr_write_test.txt"); var testPath = Path.Combine(path, "radarr_write_test.txt");
var testContent = string.Format("This file was created to verify if '{0}' is writable. It should've been automatically deleted. Feel free to delete it.", path); var testContent = string.Format("This file was created to verify if '{0}' is writable. It should've been automatically deleted. Feel free to delete it.", path);
File.WriteAllText(testPath, testContent); File.WriteAllText(testPath, testContent);
File.Delete(testPath); File.Delete(testPath);
@@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -80,5 +80,34 @@ namespace NzbDrone.Common.Extensions
{ {
return source.Select(predicate).ToList(); return source.Select(predicate).ToList();
} }
public static IEnumerable<T> DropLast<T>(this IEnumerable<T> source, int n)
{
if (source == null)
throw new ArgumentNullException("source");
if (n < 0)
throw new ArgumentOutOfRangeException("n",
"Argument n should be non-negative.");
return InternalDropLast(source, n);
}
private static IEnumerable<T> InternalDropLast<T>(IEnumerable<T> source, int n)
{
Queue<T> buffer = new Queue<T>(n + 1);
foreach (T x in source)
{
buffer.Enqueue(x);
if (buffer.Count == n + 1)
yield return buffer.Dequeue();
}
}
public static bool In<T>(this T source, List<T> list)
{
return list.Contains(source);
}
} }
} }
@@ -136,7 +136,7 @@ namespace NzbDrone.Common.Http.Dispatchers
webRequest.TransferEncoding = header.Value; webRequest.TransferEncoding = header.Value;
break; break;
case "User-Agent": case "User-Agent":
throw new NotSupportedException("User-Agent other than Sonarr not allowed."); throw new NotSupportedException("User-Agent other than Radarr not allowed.");
case "Proxy-Connection": case "Proxy-Connection":
throw new NotImplementedException(); throw new NotImplementedException();
default: default:
+4 -4
View File
@@ -1,4 +1,4 @@
using System; using System;
using System.Net; using System.Net;
using NLog; using NLog;
using NzbDrone.Common.EnvironmentInfo; using NzbDrone.Common.EnvironmentInfo;
@@ -24,7 +24,7 @@ namespace NzbDrone.Common.Http
public HttpProvider(Logger logger) public HttpProvider(Logger logger)
{ {
_logger = logger; _logger = logger;
_userAgent = string.Format("Sonarr {0}", BuildInfo.Version); _userAgent = string.Format("Radarr {0}", BuildInfo.Version);
ServicePointManager.Expect100Continue = false; ServicePointManager.Expect100Continue = false;
} }
@@ -58,6 +58,6 @@ namespace NzbDrone.Common.Http
} }
} }
} }
} }
@@ -63,7 +63,7 @@ namespace NzbDrone.Common.Instrumentation
{ {
var target = new LogentriesTarget(); var target = new LogentriesTarget();
target.Name = "logentriesTarget"; target.Name = "logentriesTarget";
target.Token = "d3a83ee9-74fb-4045-ad25-a84c1d4d7c81"; target.Token = "7688c9ac-015f-45c7-bfee-73f370f5f380";
target.LogHostname = true; target.LogHostname = true;
target.Debug = false; target.Debug = false;
@@ -20,6 +20,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
private RemoteEpisode parseResultMulti; private RemoteEpisode parseResultMulti;
private RemoteEpisode parseResultSingle; private RemoteEpisode parseResultSingle;
private Series series; private Series series;
private Movie movie;
private RemoteMovie remoteMovie;
private QualityDefinition qualityType; private QualityDefinition qualityType;
[SetUp] [SetUp]
@@ -28,6 +30,16 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
series = Builder<Series>.CreateNew() series = Builder<Series>.CreateNew()
.Build(); .Build();
movie = Builder<Movie>.CreateNew().Build();
remoteMovie = new RemoteMovie
{
Movie = movie,
Release = new ReleaseInfo(),
ParsedMovieInfo = new ParsedMovieInfo { Quality = new QualityModel(Quality.SDTV, new Revision(version: 2)) },
};
parseResultMultiSet = new RemoteEpisode parseResultMultiSet = new RemoteEpisode
{ {
Series = series, Series = series,
@@ -216,5 +228,17 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue(); Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
} }
[Test]
public void should_use_110_minutes_if_runtime_is_0()
{
movie.Runtime = 0;
remoteMovie.Movie = movie;
remoteMovie.Release.Size = 1095.Megabytes();
Subject.IsSatisfiedBy(remoteMovie, null).Accepted.Should().Be(true);
remoteMovie.Release.Size = 1105.Megabytes();
Subject.IsSatisfiedBy(remoteMovie, null).Accepted.Should().Be(false);
}
} }
} }
@@ -19,6 +19,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{ {
private List<ReleaseInfo> _reports; private List<ReleaseInfo> _reports;
private RemoteMovie _remoteEpisode; private RemoteMovie _remoteEpisode;
private MappingResult _mappingResult;
private Mock<IDecisionEngineSpecification> _pass1; private Mock<IDecisionEngineSpecification> _pass1;
private Mock<IDecisionEngineSpecification> _pass2; private Mock<IDecisionEngineSpecification> _pass2;
@@ -50,11 +51,15 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "Trolls.2016.720p.WEB-DL.DD5.1.H264-FGT" } }; _reports = new List<ReleaseInfo> { new ReleaseInfo { Title = "Trolls.2016.720p.WEB-DL.DD5.1.H264-FGT" } };
_remoteEpisode = new RemoteMovie { _remoteEpisode = new RemoteMovie {
Movie = new Movie(), Movie = new Movie(),
ParsedMovieInfo = new ParsedMovieInfo()
}; };
_mappingResult = new MappingResult {Movie = new Movie(), MappingResultType = MappingResultType.Success};
_mappingResult.RemoteMovie = _remoteEpisode;
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()
.Setup(c => c.Map(It.IsAny<ParsedMovieInfo>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>())) .Setup(c => c.Map(It.IsAny<ParsedMovieInfo>(), It.IsAny<string>(), It.IsAny<SearchCriteriaBase>())).Returns(_mappingResult);
.Returns(_remoteEpisode);
} }
private void GivenSpecifications(params Mock<IDecisionEngineSpecification>[] mocks) private void GivenSpecifications(params Mock<IDecisionEngineSpecification>[] mocks)
@@ -121,6 +126,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{ {
GivenSpecifications(_pass1, _pass2, _pass3); GivenSpecifications(_pass1, _pass2, _pass3);
_reports[0].Title = "Not parsable"; _reports[0].Title = "Not parsable";
_mappingResult.MappingResultType = MappingResultType.NotParsable;
var results = Subject.GetRssDecision(_reports).ToList(); var results = Subject.GetRssDecision(_reports).ToList();
@@ -130,7 +136,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never()); _pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never()); _pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never());
results.Should().BeEmpty(); results.Should().NotBeEmpty();
} }
[Test] [Test]
@@ -138,6 +144,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
{ {
GivenSpecifications(_pass1, _pass2, _pass3); GivenSpecifications(_pass1, _pass2, _pass3);
_reports[0].Title = "1937 - Snow White and the Seven Dwarves"; _reports[0].Title = "1937 - Snow White and the Seven Dwarves";
_mappingResult.MappingResultType = MappingResultType.NotParsable;
var results = Subject.GetRssDecision(_reports).ToList(); var results = Subject.GetRssDecision(_reports).ToList();
@@ -147,7 +154,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
_pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never()); _pass2.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never());
_pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never()); _pass3.Verify(c => c.IsSatisfiedBy(It.IsAny<RemoteMovie>(), null), Times.Never());
results.Should().BeEmpty(); results.Should().NotBeEmpty();
} }
[Test] [Test]
@@ -156,6 +163,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenSpecifications(_pass1, _pass2, _pass3); GivenSpecifications(_pass1, _pass2, _pass3);
_remoteEpisode.Movie = null; _remoteEpisode.Movie = null;
_mappingResult.MappingResultType = MappingResultType.TitleNotFound;
Subject.GetRssDecision(_reports); Subject.GetRssDecision(_reports);
@@ -249,12 +257,13 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
GivenSpecifications(_pass1, _pass2, _pass3); GivenSpecifications(_pass1, _pass2, _pass3);
_remoteEpisode.Movie = null; _remoteEpisode.Movie = null;
_mappingResult.MappingResultType = MappingResultType.TitleNotFound;
var result = Subject.GetRssDecision(_reports); var result = Subject.GetRssDecision(_reports);
result.Should().HaveCount(1); result.Should().HaveCount(1);
result.First().RemoteMovie.DownloadAllowed.Should().BeFalse(); //result.First().RemoteMovie.DownloadAllowed.Should().BeFalse();
} }
[Test] [Test]
@@ -269,7 +278,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
result.Should().HaveCount(1); result.Should().HaveCount(1);
result.First().RemoteMovie.DownloadAllowed.Should().BeFalse(); //result.First().RemoteMovie.DownloadAllowed.Should().BeFalse();
} }
[Test] [Test]
@@ -0,0 +1,111 @@
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.DecisionEngine.Specifications.Search;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.TorrentRss;
using NzbDrone.Core.IndexerSearch.Definitions;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Tv;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.DecisionEngineTests.Search
{
[TestFixture]
public class TorrentSeedingSpecificationFixture : TestBase<TorrentSeedingSpecification>
{
private Series _series;
private RemoteEpisode _remoteEpisode;
private IndexerDefinition _indexerDefinition;
[SetUp]
public void Setup()
{
_series = Builder<Series>.CreateNew().With(s => s.Id = 1).Build();
_remoteEpisode = new RemoteEpisode
{
Series = _series,
Release = new TorrentInfo
{
IndexerId = 1,
Title = "Series.Title.S01.720p.BluRay.X264-RlsGrp",
Seeders = 0
}
};
_indexerDefinition = new IndexerDefinition
{
Settings = new TorrentRssIndexerSettings { MinimumSeeders = 5 }
};
Mocker.GetMock<IIndexerFactory>()
.Setup(v => v.Get(1))
.Returns(_indexerDefinition);
}
private void GivenReleaseSeeders(int? seeders)
{
(_remoteEpisode.Release as TorrentInfo).Seeders = seeders;
}
[Test]
public void should_return_true_if_not_torrent()
{
_remoteEpisode.Release = new ReleaseInfo
{
IndexerId = 1,
Title = "Series.Title.S01.720p.BluRay.X264-RlsGrp"
};
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_indexer_not_specified()
{
_remoteEpisode.Release.IndexerId = 0;
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_indexer_no_longer_exists()
{
Mocker.GetMock<IIndexerFactory>()
.Setup(v => v.Get(It.IsAny<int>()))
.Callback<int>(i => { throw new ModelNotFoundException(typeof(IndexerDefinition), i); });
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[Test]
public void should_return_true_if_seeds_unknown()
{
GivenReleaseSeeders(null);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[TestCase(5)]
[TestCase(6)]
public void should_return_true_if_seeds_above_or_equal_to_limit(int seeders)
{
GivenReleaseSeeders(seeders);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeTrue();
}
[TestCase(0)]
[TestCase(4)]
public void should_return_false_if_seeds_belove_limit(int seeders)
{
GivenReleaseSeeders(seeders);
Subject.IsSatisfiedBy(_remoteEpisode, null).Accepted.Should().BeFalse();
}
}
}
@@ -76,7 +76,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteMovie)); decisions.Add(new DownloadDecision(remoteMovie));
Subject.ProcessDecisions(decisions); Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>(), false), Times.Once());
} }
[Test] [Test]
@@ -89,7 +89,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteMovie)); decisions.Add(new DownloadDecision(remoteMovie));
Subject.ProcessDecisions(decisions); Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Once()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>(), false), Times.Once());
} }
[Test] [Test]
@@ -157,7 +157,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
var decisions = new List<DownloadDecision>(); var decisions = new List<DownloadDecision>();
decisions.Add(new DownloadDecision(remoteMovie)); decisions.Add(new DownloadDecision(remoteMovie));
Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteMovie>())).Throws(new Exception()); Mocker.GetMock<IDownloadService>().Setup(s => s.DownloadReport(It.IsAny<RemoteMovie>(), false)).Throws(new Exception());
Subject.ProcessDecisions(decisions).Grabbed.Should().BeEmpty(); Subject.ProcessDecisions(decisions).Grabbed.Should().BeEmpty();
ExceptionVerification.ExpectedWarns(1); ExceptionVerification.ExpectedWarns(1);
} }
@@ -183,7 +183,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
decisions.Add(new DownloadDecision(remoteMovie)); decisions.Add(new DownloadDecision(remoteMovie));
Subject.ProcessDecisions(decisions); Subject.ProcessDecisions(decisions);
Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>()), Times.Never()); Mocker.GetMock<IDownloadService>().Verify(v => v.DownloadReport(It.IsAny<RemoteMovie>(), false), Times.Never());
} }
[Test] [Test]
@@ -31,7 +31,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()
.Setup(s => s.Map(It.IsAny<ParsedMovieInfo>(), It.IsAny<string>(), (SearchCriteriaBase)null)) .Setup(s => s.Map(It.IsAny<ParsedMovieInfo>(), It.IsAny<string>(), (SearchCriteriaBase)null))
.Returns(() => CreateRemoteMovie()); .Returns(() => new MappingResult{RemoteMovie = CreateRemoteMovie(), MappingResultType = MappingResultType.Success});
Mocker.GetMock<IHttpClient>() Mocker.GetMock<IHttpClient>()
.Setup(s => s.Get(It.IsAny<HttpRequest>())) .Setup(s => s.Get(It.IsAny<HttpRequest>()))
@@ -54,7 +54,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
protected void GivenRedirectToTorrent() protected void GivenRedirectToTorrent()
{ {
var httpHeader = new HttpHeader(); var httpHeader = new HttpHeader();
httpHeader["Location"] = "http://test.sonarr.tv/not-a-real-torrent.torrent"; httpHeader["Location"] = "http://test.radarr.video/not-a-real-torrent.torrent";
Mocker.GetMock<IHttpClient>() Mocker.GetMock<IHttpClient>()
.Setup(s => s.Get(It.Is<HttpRequest>(h => h.Url.FullUri == _downloadUrl))) .Setup(s => s.Get(It.Is<HttpRequest>(h => h.Url.FullUri == _downloadUrl)))
@@ -405,7 +405,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
[Test] [Test]
public void should_get_category_from_the_category_if_set() public void should_get_category_from_the_category_if_set()
{ {
const string category = "tv-sonarr"; const string category = "movies-radarr";
GivenMaxRatio(1.0f); GivenMaxRatio(1.0f);
var torrent = new QBittorrentTorrent var torrent = new QBittorrentTorrent
@@ -430,7 +430,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
[Test] [Test]
public void should_get_category_from_the_label_if_the_category_is_not_available() public void should_get_category_from_the_label_if_the_category_is_not_available()
{ {
const string category = "tv-sonarr"; const string category = "movies-radarr";
GivenMaxRatio(1.0f); GivenMaxRatio(1.0f);
var torrent = new QBittorrentTorrent var torrent = new QBittorrentTorrent
@@ -145,8 +145,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)] [TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)] [TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed)] [TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus) public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
{ {
_queued.Status = apiStatus; _queued.Status = apiStatus;
@@ -160,7 +160,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)] [TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus) public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
{ {
_downloading.Status = apiStatus; _downloading.Status = apiStatus;
@@ -107,7 +107,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.UTorrentTests
protected void GivenRedirectToTorrent() protected void GivenRedirectToTorrent()
{ {
var httpHeader = new HttpHeader(); var httpHeader = new HttpHeader();
httpHeader["Location"] = "http://test.sonarr.tv/not-a-real-torrent.torrent"; httpHeader["Location"] = "http://test.radarr.video/not-a-real-torrent.torrent";
Mocker.GetMock<IHttpClient>() Mocker.GetMock<IHttpClient>()
.Setup(s => s.Get(It.Is<HttpRequest>(h => h.Url.ToString() == _downloadUrl))) .Setup(s => s.Get(It.Is<HttpRequest>(h => h.Url.ToString() == _downloadUrl)))
@@ -13,6 +13,13 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[TestFixture] [TestFixture]
public class VuzeFixture : TransmissionFixtureBase<Vuze> public class VuzeFixture : TransmissionFixtureBase<Vuze>
{ {
[SetUp]
public void Setup_Vuze()
{
// Vuze never sets isFinished.
_completed.IsFinished = false;
}
[Test] [Test]
public void queued_item_should_have_required_properties() public void queued_item_should_have_required_properties()
{ {
@@ -147,8 +154,8 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)] [TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)] [TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed)] [TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus) public void GetItems_should_return_queued_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
{ {
_queued.Status = apiStatus; _queued.Status = apiStatus;
@@ -162,7 +169,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued)]
[TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)] [TestCase(TransmissionTorrentStatus.Downloading, DownloadItemStatus.Downloading)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Downloading)]
public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus) public void GetItems_should_return_downloading_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus)
{ {
_downloading.Status = apiStatus; _downloading.Status = apiStatus;
@@ -177,7 +184,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
[TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)] [TestCase(TransmissionTorrentStatus.Stopped, DownloadItemStatus.Completed, false)]
[TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)] [TestCase(TransmissionTorrentStatus.CheckWait, DownloadItemStatus.Downloading, true)]
[TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)] [TestCase(TransmissionTorrentStatus.Check, DownloadItemStatus.Downloading, true)]
[TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.Queued, DownloadItemStatus.Queued, true)]
[TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.SeedingWait, DownloadItemStatus.Completed, true)]
[TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)] [TestCase(TransmissionTorrentStatus.Seeding, DownloadItemStatus.Completed, true)]
public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly) public void GetItems_should_return_completed_item_as_downloadItemStatus(TransmissionTorrentStatus apiStatus, DownloadItemStatus expectedItemStatus, bool expectedReadOnly)
@@ -294,7 +301,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
} }
[Test] [Test]
public void should_have_correct_output_directory() public void should_have_correct_output_directory_for_multifile_torrents()
{ {
WindowsOnly(); WindowsOnly();
@@ -311,5 +318,25 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.VuzeTests
items.First().OutputPath.Should().Be(@"C:\Downloads\" + _title); items.First().OutputPath.Should().Be(@"C:\Downloads\" + _title);
} }
[Test]
public void should_have_correct_output_directory_for_singlefile_torrents()
{
WindowsOnly();
var fileName = _title + ".mkv";
_downloading.Name = fileName;
_downloading.DownloadDir = @"C:/Downloads";
GivenTorrents(new List<TransmissionTorrent>
{
_downloading
});
var items = Subject.GetItems().ToList();
items.Should().HaveCount(1);
items.First().OutputPath.Should().Be(@"C:\Downloads\" + fileName);
}
} }
} }
@@ -50,7 +50,7 @@ namespace NzbDrone.Core.Test.Download.TrackedDownloads
Mocker.GetMock<IParsingService>() Mocker.GetMock<IParsingService>()
.Setup(s => s.Map(It.Is<ParsedMovieInfo>(i => i.MovieTitle == "A Movie"), It.IsAny<string>(), null)) .Setup(s => s.Map(It.Is<ParsedMovieInfo>(i => i.MovieTitle == "A Movie"), It.IsAny<string>(), null))
.Returns(remoteEpisode); .Returns(new MappingResult{RemoteMovie = remoteEpisode});
var client = new DownloadClientDefinition() var client = new DownloadClientDefinition()
{ {
File diff suppressed because one or more lines are too long
@@ -8,7 +8,7 @@ namespace NzbDrone.Core.Test.HealthCheck
[TestFixture] [TestFixture]
public class HealthCheckFixture : CoreTest public class HealthCheckFixture : CoreTest
{ {
private const string WikiRoot = "https://github.com/Sonarr/Sonarr/wiki/"; private const string WikiRoot = "https://github.com/Radarr/Radarr/wiki/";
[TestCase("I blew up because of some weird user mistake", null, WikiRoot + "Health-checks#i-blew-up-because-of-some-weird-user-mistake")] [TestCase("I blew up because of some weird user mistake", null, WikiRoot + "Health-checks#i-blew-up-because-of-some-weird-user-mistake")]
[TestCase("I blew up because of some weird user mistake", "#my-health-check", WikiRoot + "Health-checks#my-health-check")] [TestCase("I blew up because of some weird user mistake", "#my-health-check", WikiRoot + "Health-checks#my-health-check")]
@@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test.IndexerTests.IPTorrentsTests
Subject.Definition = new IndexerDefinition() Subject.Definition = new IndexerDefinition()
{ {
Name = "IPTorrents", Name = "IPTorrents",
Settings = new IPTorrentsSettings() { Url = "http://fake.com/" } Settings = new IPTorrentsSettings() { BaseUrl = "http://fake.com/" }
}; };
} }
@@ -14,6 +14,7 @@ using NzbDrone.Test.Common.Categories;
namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests namespace NzbDrone.Core.Test.IndexerTests.IntegrationTests
{ {
[IntegrationTest] [IntegrationTest]
[Ignore("Nyaa is down!")]
public class IndexerIntegrationTests : CoreTest public class IndexerIntegrationTests : CoreTest
{ {
private SingleEpisodeSearchCriteria _singleSearchCriteria; private SingleEpisodeSearchCriteria _singleSearchCriteria;
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
{ {
_settings = new NewznabSettings() _settings = new NewznabSettings()
{ {
Url = "http://indxer.local" BaseUrl = "http://indxer.local"
}; };
_caps = ReadAllText("Files/Indexers/Newznab/newznab_caps.xml"); _caps = ReadAllText("Files/Indexers/Newznab/newznab_caps.xml");
@@ -24,7 +24,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
Name = "Newznab", Name = "Newznab",
Settings = new NewznabSettings() Settings = new NewznabSettings()
{ {
Url = "http://indexer.local/", BaseUrl = "http://indexer.local/",
Categories = new int[] { 1 } Categories = new int[] { 1 }
} }
}; };
@@ -19,7 +19,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
{ {
Subject.Settings = new NewznabSettings() Subject.Settings = new NewznabSettings()
{ {
Url = "http://127.0.0.1:1234/", BaseUrl = "http://127.0.0.1:1234/",
Categories = new [] { 1, 2 }, Categories = new [] { 1, 2 },
AnimeCategories = new [] { 3, 4 }, AnimeCategories = new [] { 3, 4 },
ApiKey = "abcd", ApiKey = "abcd",
@@ -15,7 +15,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
var setting = new NewznabSettings() var setting = new NewznabSettings()
{ {
ApiKey = "", ApiKey = "",
Url = url BaseUrl = url
}; };
@@ -32,13 +32,13 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
var setting = new NewznabSettings var setting = new NewznabSettings
{ {
ApiKey = "", ApiKey = "",
Url = url BaseUrl = url
}; };
setting.Validate().IsValid.Should().BeFalse(); setting.Validate().IsValid.Should().BeFalse();
setting.Validate().Errors.Should().NotContain(c => c.PropertyName == "ApiKey"); setting.Validate().Errors.Should().NotContain(c => c.PropertyName == "ApiKey");
setting.Validate().Errors.Should().Contain(c => c.PropertyName == "Url"); setting.Validate().Errors.Should().Contain(c => c.PropertyName == "BaseUrl");
} }
@@ -49,7 +49,7 @@ namespace NzbDrone.Core.Test.IndexerTests.NewznabTests
var setting = new NewznabSettings() var setting = new NewznabSettings()
{ {
ApiKey = "", ApiKey = "",
Url = url BaseUrl = url
}; };
@@ -0,0 +1,69 @@
using System;
using System.Linq;
using System.Text;
using FluentAssertions;
using Moq;
using NUnit.Framework;
using NzbDrone.Common.Http;
using NzbDrone.Common.Serializer;
using NzbDrone.Core.Indexers;
using NzbDrone.Core.Indexers.PassThePopcorn;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Test.Common;
namespace NzbDrone.Core.Test.IndexerTests.PTPTests
{
[TestFixture]
public class PTPFixture : CoreTest<PassThePopcorn>
{
[SetUp]
public void Setup()
{
Subject.Definition = new IndexerDefinition()
{
Name = "PTP",
Settings = new PassThePopcornSettings() { Passkey = "fakekey", Username = "asdf", Password = "sad" }
};
}
[TestCase("Files/Indexers/PTP/imdbsearch.json")]
public void should_parse_feed_from_PTP(string fileName)
{
var authResponse = new PassThePopcornAuthResponse { Result = "Ok" };
System.IO.StringWriter authStream = new System.IO.StringWriter();
Json.Serialize(authResponse, authStream);
var responseJson = ReadAllText(fileName);
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
.Returns<HttpRequest>(r => new HttpResponse(r,new HttpHeader(), authStream.ToString()));
Mocker.GetMock<IHttpClient>()
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader {ContentType = HttpAccept.Json.Value}, responseJson));
var torrents = Subject.FetchRecent();
torrents.Should().HaveCount(293);
torrents.First().Should().BeOfType<PassThePopcornInfo>();
var first = torrents.First() as TorrentInfo;
first.Guid.Should().Be("PassThePopcorn-483521");
first.Title.Should().Be("The.Night.Of.S01.720p.HDTV.x264-BTN");
first.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
first.DownloadUrl.Should().Be("https://passthepopcorn.me/torrents.php?action=download&id=483521&authkey=00000000000000000000000000000000&torrent_pass=00000000000000000000000000000000");
first.InfoUrl.Should().Be("https://passthepopcorn.me/torrents.php?id=148131&torrentid=483521");
//first.PublishDate.Should().Be(DateTime.Parse("2017-04-17T12:13:42+0000").ToUniversalTime()); stupid timezones
first.Size.Should().Be(9370933376);
first.InfoHash.Should().BeNullOrEmpty();
first.MagnetUrl.Should().BeNullOrEmpty();
first.Peers.Should().Be(3);
first.Seeders.Should().Be(1);
torrents.Any(t => t.IndexerFlags.HasFlag(IndexerFlags.G_Freeleech)).Should().Be(true);
}
}
}
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.IndexerTests.TorznabTests
Name = "Torznab", Name = "Torznab",
Settings = new TorznabSettings() Settings = new TorznabSettings()
{ {
Url = "http://indexer.local/", BaseUrl = "http://indexer.local/",
Categories = new int[] { 1 } Categories = new int[] { 1 }
} }
}; };
@@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test.NetImport
[SetUp] [SetUp]
public void Setup() public void Setup()
{ {
Subject.Definition = Subject.DefaultDefinitions.First(); Subject.Definition = Subject.GetDefaultDefinitions().First();
} }
private void GivenRecentFeedResponse(string rssXmlFile) private void GivenRecentFeedResponse(string rssXmlFile)
{ {
@@ -159,6 +159,7 @@
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\RssSync\DelaySpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\Search\TorrentSeedingSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\SameEpisodesSpecificationFixture.cs" />
<Compile Include="DecisionEngineTests\RawDiskSpecificationFixture.cs" /> <Compile Include="DecisionEngineTests\RawDiskSpecificationFixture.cs" />
@@ -296,6 +297,7 @@
<Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" /> <Compile Include="OrganizerTests\FileNameBuilderTests\CleanTitleFixture.cs" />
<Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" /> <Compile Include="OrganizerTests\FileNameBuilderTests\EpisodeTitleCollapseFixture.cs" />
<Compile Include="OrganizerTests\FileNameBuilderTests\MultiEpisodeFixture.cs" /> <Compile Include="OrganizerTests\FileNameBuilderTests\MultiEpisodeFixture.cs" />
<Compile Include="OrganizerTests\GetMovieFolderFixture.cs" />
<Compile Include="ParserTests\MiniSeriesEpisodeParserFixture.cs" /> <Compile Include="ParserTests\MiniSeriesEpisodeParserFixture.cs" />
<Compile Include="ParserTests\RomanNumeralTests\RomanNumeralConversionFixture.cs" /> <Compile Include="ParserTests\RomanNumeralTests\RomanNumeralConversionFixture.cs" />
<Compile Include="Qualities\RevisionComparableFixture.cs" /> <Compile Include="Qualities\RevisionComparableFixture.cs" />
@@ -389,6 +391,10 @@
<Content Include="Files\ArabicRomanNumeralDictionary.JSON"> <Content Include="Files\ArabicRomanNumeralDictionary.JSON">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Compile Include="IndexerTests\PTPTests\PTPFixture.cs" />
<None Include="Files\Indexers\PTP\imdbsearch.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Marr.Data\Marr.Data.csproj"> <ProjectReference Include="..\Marr.Data\Marr.Data.csproj">
@@ -574,6 +580,8 @@
<Folder Include="DataAugmentation\SceneNumbering\" /> <Folder Include="DataAugmentation\SceneNumbering\" />
<Folder Include="Providers\" /> <Folder Include="Providers\" />
<Folder Include="ProviderTests\UpdateProviderTests\" /> <Folder Include="ProviderTests\UpdateProviderTests\" />
<Folder Include="IndexerTests\PTPTests\" />
<Folder Include="Files\Indexers\PTP\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
@@ -1,4 +1,4 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using FizzWare.NBuilder; using FizzWare.NBuilder;
@@ -734,5 +734,7 @@ namespace NzbDrone.Core.Test.OrganizerTests.FileNameBuilderTests
Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile) Subject.BuildFileName(new List<Episode> { _episode1 }, _series, _episodeFile)
.Should().Be(releaseGroup); .Should().Be(releaseGroup);
} }
} }
} }
@@ -0,0 +1,40 @@
using NUnit.Framework;
using NzbDrone.Core.Organizer;
using NzbDrone.Core.Test.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Core.Tv;
using FluentAssertions;
namespace NzbDrone.Core.Test.OrganizerTests
{
[TestFixture]
public class GetMovieFolderFixture : CoreTest<FileNameBuilder>
{
private NamingConfig namingConfig;
[SetUp]
public void Setup()
{
namingConfig = NamingConfig.Default;
Mocker.GetMock<INamingConfigService>()
.Setup(c => c.GetConfig()).Returns(namingConfig);
}
[TestCase("Arrival", 2016, "{Movie Title} ({Release Year})", "Arrival (2016)")]
[TestCase("The Big Short", 2015, "{Movie TitleThe} ({Release Year})", "Big Short, The (2015)")]
[TestCase("The Big Short", 2015, "{Movie Title} ({Release Year})", "The Big Short (2015)")]
public void should_use_movieFolderFormat_to_build_folder_name(string movieTitle, int year, string format, string expected)
{
namingConfig.MovieFolderFormat = format;
var movie = new Movie { Title = movieTitle, Year = year };
Subject.GetMovieFolder(movie).Should().Be(expected);
}
}
}
@@ -51,9 +51,13 @@ namespace NzbDrone.Core.Test.ParserTests
[TestCase("Castle.2009.S01E14.HDTV.XviD.HUN-LOL", Language.Hungarian)] [TestCase("Castle.2009.S01E14.HDTV.XviD.HUN-LOL", Language.Hungarian)]
[TestCase("The Danish Girl 2015", Language.English)] [TestCase("The Danish Girl 2015", Language.English)]
[TestCase("Passengers.2016.German.DL.AC3.Dubbed.1080p.WebHD.h264.iNTERNAL-PsO", Language.German)] [TestCase("Passengers.2016.German.DL.AC3.Dubbed.1080p.WebHD.h264.iNTERNAL-PsO", Language.German)]
[TestCase("Der.Soldat.James.German.Bluray.FuckYou.Pso.Why.cant.you.follow.scene.rules.1998", Language.German)]
[TestCase("Passengers.German.DL.AC3.Dubbed..BluRay.x264-PsO", Language.German)]
[TestCase("Valana la Legende FRENCH BluRay 720p 2016 kjhlj", Language.French)]
[TestCase("Smurfs.The.Lost.Village.2017.1080p.BluRay.HebDub.x264-iSrael",Language.Hebrew)]
public void should_parse_language(string postTitle, Language language) public void should_parse_language(string postTitle, Language language)
{ {
var result = Parser.Parser.ParseMovieTitle(postTitle); var result = Parser.Parser.ParseMovieTitle(postTitle, true);
if (result == null) if (result == null)
{ {
Parser.Parser.ParseTitle(postTitle).Language.Should().Be(language); Parser.Parser.ParseTitle(postTitle).Language.Should().Be(language);
@@ -72,6 +72,40 @@ namespace NzbDrone.Core.Test.ParserTests
} }
} }
[Test]
public void should_not_remove_a_when_at_start_of_acronym()
{
var dirtyFormat = new[]
{
"word.{0}.N.K.L.E.word",
"word {0} N K L E word",
"word-{0}-N-K-L-E-word",
};
foreach (var s in dirtyFormat)
{
var dirty = string.Format(s, "a");
dirty.CleanSeriesTitle().Should().Be("wordankleword");
}
}
[Test]
public void should_not_remove_a_when_at_end_of_acronym()
{
var dirtyFormat = new[]
{
"word.N.K.L.E.{0}.word",
"word N K L E {0} word",
"word-N-K-L-E-{0}-word",
};
foreach (var s in dirtyFormat)
{
var dirty = string.Format(s, "a");
dirty.CleanSeriesTitle().Should().Be("wordnkleaword");
}
}
[TestCase("the")] [TestCase("the")]
[TestCase("and")] [TestCase("and")]
[TestCase("or")] [TestCase("or")]

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