Compare commits
417 Commits
0.05
...
v0.2.0.210
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0bcb27beb | ||
|
|
ec6b389d75 | ||
|
|
f38430d632 | ||
|
|
266f28883a | ||
|
|
309877bf76 | ||
|
|
a50b20a397 | ||
|
|
de5489ae9a | ||
|
|
12e74aa38b | ||
|
|
80ec66b47c | ||
|
|
585fd87ad6 | ||
|
|
ec5161e848 | ||
|
|
0ec54daaff | ||
|
|
3ed1bebb7d | ||
|
|
29ae088a3d | ||
|
|
eb299ce847 | ||
|
|
a7e071318b | ||
|
|
3d67f6237e | ||
|
|
a691ffa7b7 | ||
|
|
aa9537c201 | ||
|
|
a3d9fb1c20 | ||
|
|
62a1e70c86 | ||
|
|
93d0d21846 | ||
|
|
b1c5a3ac14 | ||
|
|
55a525ba2f | ||
|
|
a53768463b | ||
|
|
24cbd6bcef | ||
|
|
3ab3e66853 | ||
|
|
40ca469339 | ||
|
|
2cbd2f719f | ||
|
|
53cbfa803b | ||
|
|
c0b0310bbd | ||
|
|
30e50062a8 | ||
|
|
85fd8f2c65 | ||
|
|
f72b042d5d | ||
|
|
2d3a3a0677 | ||
|
|
2bb21fedab | ||
|
|
91c820f98b | ||
|
|
7d3118aece | ||
|
|
4f4ad77ad1 | ||
|
|
42f205a731 | ||
|
|
cbb2b778a6 | ||
|
|
b3e03a648d | ||
|
|
acf45a79e8 | ||
|
|
b5d8ac852e | ||
|
|
4aec0e8fc6 | ||
|
|
ecea417fd8 | ||
|
|
6a41f6a435 | ||
|
|
da2d075aa8 | ||
|
|
10dc3993df | ||
|
|
7e5020db9a | ||
|
|
c48fe9de12 | ||
|
|
421e827a95 | ||
|
|
34d8045cf4 | ||
|
|
c6de163748 | ||
|
|
d9e2b22e74 | ||
|
|
65c0137964 | ||
|
|
ae19424ce7 | ||
|
|
7527ec52b7 | ||
|
|
640fcf3eaf | ||
|
|
3ce8232777 | ||
|
|
864b441d8e | ||
|
|
bc2ff149b4 | ||
|
|
dea305e921 | ||
|
|
e2eab31548 | ||
|
|
fe62e18f0d | ||
|
|
f1fa1553cf | ||
|
|
b576ae813d | ||
|
|
99123be936 | ||
|
|
dd0a033b0f | ||
|
|
c64597c9f1 | ||
|
|
6d2f81e3ed | ||
|
|
4263808360 | ||
|
|
c5ca2babf7 | ||
|
|
08db74d6e6 | ||
|
|
b309a9b01f | ||
|
|
2730745607 | ||
|
|
ae0df2aef0 | ||
|
|
6d665aeb21 | ||
|
|
967d3fd5c0 | ||
|
|
199d9c93ed | ||
|
|
30d2b41fbb | ||
|
|
75bb2533a3 | ||
|
|
9b3b4eb55b | ||
|
|
42f84b830c | ||
|
|
eb0f825cfc | ||
|
|
56a5b6ec89 | ||
|
|
af478d3799 | ||
|
|
c2d40051d4 | ||
|
|
281e516495 | ||
|
|
f63c3091f4 | ||
|
|
50f49863b7 | ||
|
|
941b3bd701 | ||
|
|
f60b8cefca | ||
|
|
7c5f2ca54e | ||
|
|
401a650273 | ||
|
|
105af5cf11 | ||
|
|
637c2e43eb | ||
|
|
53373e6f4a | ||
|
|
ad147ed425 | ||
|
|
ed35e2f194 | ||
|
|
674919dbf5 | ||
|
|
15b77e303f | ||
|
|
757ca1d72c | ||
|
|
8c8c7a99e3 | ||
|
|
b3dfb960b5 | ||
|
|
98856e6747 | ||
|
|
8fb5049899 | ||
|
|
3f62911a4f | ||
|
|
170349c950 | ||
|
|
6c413d83eb | ||
|
|
3afd27cad3 | ||
|
|
149faf467d | ||
|
|
ce52bb8f68 | ||
|
|
4bb5857444 | ||
|
|
620f09ef8b | ||
|
|
16c1a2ee50 | ||
|
|
4b559cf29c | ||
|
|
ca03f21b03 | ||
|
|
f481fe9ea9 | ||
|
|
3a0278d0a1 | ||
|
|
d18b15d504 | ||
|
|
dc7e75187c | ||
|
|
68a0ef65df | ||
|
|
fe11928487 | ||
|
|
41dda3af48 | ||
|
|
8c3260c545 | ||
|
|
bd0ec5dfce | ||
|
|
ad38437b70 | ||
|
|
4447b7cd62 | ||
|
|
d33de0d158 | ||
|
|
dd5049b483 | ||
|
|
29586667cb | ||
|
|
5daece0ed4 | ||
|
|
5dc63e5607 | ||
|
|
7df283e57f | ||
|
|
e9b6c250f7 | ||
|
|
10515156d1 | ||
|
|
4260b58535 | ||
|
|
3a386f2e18 | ||
|
|
d3bd0c9b69 | ||
|
|
3180e648b4 | ||
|
|
d0c93759c6 | ||
|
|
f7471940c4 | ||
|
|
3a6873cc4d | ||
|
|
330ae38ec2 | ||
|
|
a0ecb19e32 | ||
|
|
38c966c07b | ||
|
|
ad824d4da5 | ||
|
|
e76c160afe | ||
|
|
6a62546a4d | ||
|
|
0efdc78f8d | ||
|
|
fdd06127fc | ||
|
|
317f8917b9 | ||
|
|
4038ce18c3 | ||
|
|
7f3ca85953 | ||
|
|
b93a9719fe | ||
|
|
2ef18edf08 | ||
|
|
d61b9ab207 | ||
|
|
abf4b137f1 | ||
|
|
774c85f06b | ||
|
|
a060335bbc | ||
|
|
5a8d944397 | ||
|
|
0b70a5c315 | ||
|
|
91cded3b71 | ||
|
|
84112dc85b | ||
|
|
b1b947ae7f | ||
|
|
1b035f8657 | ||
|
|
9d50f4d651 | ||
|
|
c06a6dc988 | ||
|
|
f198ca2b77 | ||
|
|
9cfc766889 | ||
|
|
5ef1e40403 | ||
|
|
c9e6835d7b | ||
|
|
604cea00f6 | ||
|
|
b4782da1d1 | ||
|
|
d5504043c5 | ||
|
|
81ebbcad70 | ||
|
|
92e9dc6ee1 | ||
|
|
5e8b617625 | ||
|
|
2cbe17151d | ||
|
|
95bd615718 | ||
|
|
8e8c4ff497 | ||
|
|
5eddcc1660 | ||
|
|
d42165a93a | ||
|
|
99012d8a40 | ||
|
|
8bc42c76e4 | ||
|
|
b7f72c6259 | ||
|
|
64ef8db037 | ||
|
|
3b5887bf09 | ||
|
|
40a75949ba | ||
|
|
6747267d19 | ||
|
|
13db03f97c | ||
|
|
cd68eea790 | ||
|
|
cfe55d00ae | ||
|
|
1d88313424 | ||
|
|
9513068467 | ||
|
|
9206258370 | ||
|
|
0fa1509ca6 | ||
|
|
c5eb772f7a | ||
|
|
04fec6d4d8 | ||
|
|
d0b5e380d7 | ||
|
|
df69c58d2b | ||
|
|
27114c9399 | ||
|
|
cfca07996b | ||
|
|
e97b80f630 | ||
|
|
792679fd81 | ||
|
|
ecf47d4b17 | ||
|
|
3b1d49a78f | ||
|
|
753f3eb863 | ||
|
|
9fc2d22d19 | ||
|
|
3cb42f06c2 | ||
|
|
a6c396a595 | ||
|
|
bac9076b1e | ||
|
|
b228273be0 | ||
|
|
e7fa4cba19 | ||
|
|
0506cc4185 | ||
|
|
cde8b4dd97 | ||
|
|
0a0a44162c | ||
|
|
125f46fbec | ||
|
|
f3222ca7c7 | ||
|
|
d252a8b232 | ||
|
|
48559cf964 | ||
|
|
c734e8bc7e | ||
|
|
3c7d7756e6 | ||
|
|
683bda49d8 | ||
|
|
52fb29ee18 | ||
|
|
236e16c9a5 | ||
|
|
0584038273 | ||
|
|
6685aea144 | ||
|
|
e4f7aa52df | ||
|
|
f61c4feb00 | ||
|
|
04e8c635e0 | ||
|
|
93ea5cfdee | ||
|
|
1b7288e7cb | ||
|
|
f1914082b8 | ||
|
|
6016948329 | ||
|
|
708db1a75c | ||
|
|
994e881ba6 | ||
|
|
893e20c27b | ||
|
|
23aace6149 | ||
|
|
e774e6a038 | ||
|
|
f19a1a5960 | ||
|
|
03156d62f6 | ||
|
|
04d01dc781 | ||
|
|
cfae8807aa | ||
|
|
f90e77987e | ||
|
|
2ed0738b30 | ||
|
|
74c5664a7f | ||
|
|
4c9abe3d84 | ||
|
|
7a45394820 | ||
|
|
588a48e65d | ||
|
|
83453e2464 | ||
|
|
e6809585c9 | ||
|
|
14bf63e21d | ||
|
|
b5d932866a | ||
|
|
0b8a84a57c | ||
|
|
3555b4ce20 | ||
|
|
8cad976e7f | ||
|
|
ad7b6a8ec2 | ||
|
|
906ecfb6a1 | ||
|
|
03cc3a1ad2 | ||
|
|
d62dbd48ae | ||
|
|
cb12945270 | ||
|
|
af74854b8e | ||
|
|
f35fae109b | ||
|
|
804b2130a8 | ||
|
|
49537a2efe | ||
|
|
1dfb4ddcd8 | ||
|
|
fb7969e046 | ||
|
|
cd4863b974 | ||
|
|
55f4a81dee | ||
|
|
d006df8d7c | ||
|
|
97095733dd | ||
|
|
d08b0ce47a | ||
|
|
caa5a7e6b7 | ||
|
|
9376c02158 | ||
|
|
1ebd639e36 | ||
|
|
eff34725af | ||
|
|
00d4bfd712 | ||
|
|
5f9e285c70 | ||
|
|
902824cdbd | ||
|
|
d3cbf9a8ff | ||
|
|
c63704ba0d | ||
|
|
da404d6435 | ||
|
|
d9a6c4f211 | ||
|
|
7436997f9b | ||
|
|
4c2be68549 | ||
|
|
6d1766d81a | ||
|
|
3e676d2073 | ||
|
|
6da73d73a5 | ||
|
|
b9c98205e0 | ||
|
|
07d2f5b6a0 | ||
|
|
bfa479507c | ||
|
|
4182728901 | ||
|
|
5be5709043 | ||
|
|
ee5a2ec289 | ||
|
|
cdfb95f425 | ||
|
|
451060cb65 | ||
|
|
4d795e13cd | ||
|
|
ff6bf235aa | ||
|
|
a272127a00 | ||
|
|
e3bc6de734 | ||
|
|
23249de728 | ||
|
|
05e4af9ae7 | ||
|
|
1864a79f99 | ||
|
|
5843a881e6 | ||
|
|
d898fbb4b0 | ||
|
|
721767331b | ||
|
|
abd4c1a1ad | ||
|
|
df971b1289 | ||
|
|
e5c81eefd2 | ||
|
|
49c7c033d9 | ||
|
|
f7fb238fb4 | ||
|
|
52dbd8d708 | ||
|
|
427babf34e | ||
|
|
1022879103 | ||
|
|
dbf34e6740 | ||
|
|
4fd062b4e3 | ||
|
|
9aa8050627 | ||
|
|
cd310626e9 | ||
|
|
145c2ca4a4 | ||
|
|
1f5dcef29d | ||
|
|
899c1d98e3 | ||
|
|
3f8ea405bf | ||
|
|
f3c9a91da8 | ||
|
|
a6c79cd5d8 | ||
|
|
ed1174affb | ||
|
|
451f101350 | ||
|
|
a29fe1681d | ||
|
|
48e142c47d | ||
|
|
f1bc0164f6 | ||
|
|
aceb282f8d | ||
|
|
7871c118e7 | ||
|
|
5e7b379a45 | ||
|
|
be95311471 | ||
|
|
17d7083412 | ||
|
|
51e5c55d5f | ||
|
|
88dacc00f7 | ||
|
|
c314c9f6ec | ||
|
|
2b54f0a7f3 | ||
|
|
7a5fe59dbf | ||
|
|
a63587bb19 | ||
|
|
eb46343ce8 | ||
|
|
8fa43fb9f7 | ||
|
|
6d5e9ad4a1 | ||
|
|
70c8228605 | ||
|
|
82470bd995 | ||
|
|
a263558383 | ||
|
|
7d82e35650 | ||
|
|
8616bcedd4 | ||
|
|
2c66322121 | ||
|
|
1402bc883e | ||
|
|
1325822798 | ||
|
|
7a786d4c0e | ||
|
|
87c7afac16 | ||
|
|
06d39579a5 | ||
|
|
c8ea0a73e2 | ||
|
|
eeb3c88131 | ||
|
|
fd718b61ac | ||
|
|
4a3b2a0014 | ||
|
|
cbd87dcc38 | ||
|
|
956de03a62 | ||
|
|
2b74098040 | ||
|
|
402a9e1ee0 | ||
|
|
e68653463d | ||
|
|
0715962ec5 | ||
|
|
5668a3bcfd | ||
|
|
bd241dcbe0 | ||
|
|
69786b3968 | ||
|
|
6e2ded5d33 | ||
|
|
b47d5f7fa1 | ||
|
|
90ff73d45f | ||
|
|
c2c7015f39 | ||
|
|
579602419e | ||
|
|
28857e7fac | ||
|
|
6d23fb1b61 | ||
|
|
96332978a0 | ||
|
|
ad95fbfd4a | ||
|
|
1488c0a0fc | ||
|
|
d9d8cbacec | ||
|
|
80f2adad50 | ||
|
|
7a72f4a05b | ||
|
|
6d7ff628d8 | ||
|
|
e9f9f66b2f | ||
|
|
6ca88f98af | ||
|
|
631cf776f6 | ||
|
|
6ea9b4b94a | ||
|
|
d835c168d3 | ||
|
|
329786365d | ||
|
|
4f6380a73c | ||
|
|
cde1217356 | ||
|
|
2eedfca78a | ||
|
|
0d65984991 | ||
|
|
2a932fe7e8 | ||
|
|
0e02171938 | ||
|
|
a3dfa05f25 | ||
|
|
2a3b0304cb | ||
|
|
16e35f68bb | ||
|
|
74b1c846a5 | ||
|
|
1f930c18e4 | ||
|
|
d9e60eff6b | ||
|
|
097982334c | ||
|
|
be6e6b910e | ||
|
|
31b9ec1116 | ||
|
|
ff6c3b70d3 | ||
|
|
0fd0b31a60 | ||
|
|
76e6ebc63c | ||
|
|
2ea35adb98 | ||
|
|
782f63f510 | ||
|
|
c874122fc0 | ||
|
|
2efda4933d | ||
|
|
b7c70d750a | ||
|
|
5ebfac6cc8 | ||
|
|
74ca6149e3 | ||
|
|
40d7590f80 | ||
|
|
2cb27240dc | ||
|
|
837c2683df |
6
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,5 +1,9 @@
|
||||
|
||||
|
||||
|
||||
Please use the search bar and make sure you are not submitting an already submitted issue.
|
||||
|
||||
Provide a description of the feature request or bug, the more details the better.
|
||||
Please use https://forums.sonarr.tv/ for support or other questions. (When in doubt, use the forums)
|
||||
When possible include a log!
|
||||
|
||||
Please use our [Discord server](https://discord.gg/NWYch8M) for support or longer discussions.
|
||||
|
||||
29
.gitignore
vendored
@@ -101,16 +101,21 @@ App_Data/*.ldf
|
||||
_NCrunch_*
|
||||
_TeamCity*
|
||||
|
||||
# Sonarr
|
||||
config.xml
|
||||
nzbdrone.log*txt
|
||||
# Radarr
|
||||
Backups/
|
||||
logs/
|
||||
MediaCover/
|
||||
UpdateLogs/
|
||||
xdg/
|
||||
config.xml
|
||||
logs.db*
|
||||
nzbdrone.db*
|
||||
nzbdrone.pid
|
||||
*workspace.xml
|
||||
*.test-cache
|
||||
*.userprefs
|
||||
*/test-results/*
|
||||
src/UI/.idea/*
|
||||
*log.txt
|
||||
node_modules/
|
||||
_output*
|
||||
_rawPackage/
|
||||
@@ -122,14 +127,26 @@ setup/Output/
|
||||
|
||||
UI.Phantom/
|
||||
|
||||
#VS outout folders
|
||||
# VS outout folders
|
||||
bin
|
||||
obj
|
||||
output/*
|
||||
|
||||
# Packages
|
||||
Radarr_*/
|
||||
Radarr_*.zip
|
||||
Radarr_*.gz
|
||||
|
||||
#OS X metadata files
|
||||
# macOS metadata files
|
||||
._*
|
||||
.DS_Store
|
||||
|
||||
_start
|
||||
_temp_*/**/*
|
||||
|
||||
# Windows thumbnail cache files
|
||||
Thumbs.db
|
||||
|
||||
# AppVeyor
|
||||
/tools-cake/
|
||||
/_artifacts/
|
||||
|
||||
16
.travis.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
language: csharp
|
||||
solution: src/NzbDrone.sln
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- nodejs
|
||||
- npm
|
||||
script:
|
||||
- ./build.sh
|
||||
- chmod +x test.sh
|
||||
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
||||
after_success:
|
||||
- chmod +x package.sh
|
||||
- ./package.sh
|
||||
notifications:
|
||||
- webhooks: https://discordapp.com/api/webhooks/266910310219251712/V-QvCcnYkg3O8PMevcAJOJyCgrYkZQoF2pupLDGbaISNUECmYPd6LRwl3avKHsPyfgWP
|
||||
4
CLA.md
@@ -1,6 +1,6 @@
|
||||
# Sonarr Individual Contributor License Agreement #
|
||||
# Radarr Individual Contributor License Agreement #
|
||||
|
||||
Thank you for your interest in contributing to Sonarr ("We" or "Us").
|
||||
Thank you for your interest in contributing to Radarr ("We" or "Us").
|
||||
This contributor agreement ("Agreement") documents the rights granted by contributors to Us. To make this document effective, please complete the form below. This is a legally binding document, so please read it carefully before agreeing to it. The Agreement may cover more than one software project managed by Us.
|
||||
|
||||
## 1. Definitions ##
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# How to Contribute #
|
||||
|
||||
We're always looking for people to help make Sonarr even better, there are a number of ways to contribute.
|
||||
We're always looking for people to help make Radarr even better, there are a number of ways to contribute.
|
||||
|
||||
## Documentation ##
|
||||
Setup guides, FAQ, the more information we have on the wiki the better.
|
||||
@@ -15,7 +15,7 @@ Setup guides, FAQ, the more information we have on the wiki the better.
|
||||
|
||||
### Getting started ###
|
||||
|
||||
1. Fork Sonarr
|
||||
1. Fork Radarr
|
||||
2. Clone (develop branch) *you may need pull in submodules separately if you client doesn't clone them automatically (CurlSharp)*
|
||||
3. Run `npm install`
|
||||
4. Run `npm start` - Used to compile the UI components and copy them.
|
||||
@@ -24,8 +24,8 @@ Setup guides, FAQ, the more information we have on the wiki the better.
|
||||
5. Compile in Visual Studio
|
||||
|
||||
### Contributing Code ###
|
||||
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Sonarr/Sonarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
|
||||
- Rebase from Sonarr's develop branch, don't merge
|
||||
- If you're adding a new, already requested feature, please comment on [Github Issues](https://github.com/Radarr/Radarr/issues "Github Issues") so work is not duplicated (If you want to add something not already on there, please talk to us first)
|
||||
- Rebase from Radarr's develop branch, don't merge
|
||||
- Make meaningful commits, or squash them
|
||||
- Feel free to make a pull request before work is complete, this will let us see where its at and make comments/suggest improvements
|
||||
- Reach out to us on the forums or on IRC if you have any questions
|
||||
|
||||
BIN
Logo/1024.png
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 48 KiB |
BIN
Logo/128.png
|
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 5.1 KiB |
BIN
Logo/16.png
|
Before Width: | Height: | Size: 707 B After Width: | Height: | Size: 701 B |
BIN
Logo/256.png
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 11 KiB |
BIN
Logo/32.png
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
BIN
Logo/400.png
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 17 KiB |
BIN
Logo/48.png
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
Logo/512.png
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 22 KiB |
BIN
Logo/64.png
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
Logo/800.png
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 37 KiB |
25
Logo/Radarr.svg
Normal file
|
After Width: | Height: | Size: 31 KiB |
240
Logo/Sonarr.svg
@@ -1,240 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="218px"
|
||||
height="218px" viewBox="0 0 218 218" enable-background="new 0 0 218 218" xml:space="preserve">
|
||||
<symbol id="hex_grid" viewBox="-114.25 -98.617 228.55 197.233">
|
||||
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="none" stroke="#989898" stroke-width="0.5" stroke-linecap="square" stroke-miterlimit="1" d="
|
||||
M72.15,90.3l4.7-2.7l4.65,2.7v5.4l-4.65,2.7l-4.7-2.7V90.3z M62.85,95.7l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7V95.7l4.65,2.7
|
||||
l4.65-2.7 M62.85,90.3l4.65-2.7l4.65,2.7 M62.85,79.55v-5.4l4.65-2.7l4.65,2.7v5.4L67.5,82.2L62.85,79.55L58.2,82.2l-4.65-2.65
|
||||
M72.15,74.15l4.7-2.7l4.65,2.7v5.4l-4.65,2.65l-4.7-2.65 M76.85,87.6v-5.4 M67.5,87.6v-5.4 M81.5,95.7l4.65,2.7l4.65-2.7l4.65,2.7
|
||||
l4.65-2.7l4.65,2.7l4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4
|
||||
l4.65-2.7v-5.4L109.4,31v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7
|
||||
V-31l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4l-4.65-2.7v-5.4l4.65-2.7v-5.4l-4.65-2.65v-5.4l4.65-2.7v-5.4
|
||||
l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7
|
||||
l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7L7-98.4l-4.65,2.7l-4.65-2.7
|
||||
l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7
|
||||
l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.7-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7l-4.65-2.7l-4.65,2.7v5.4l-4.65,2.7
|
||||
v5.4l4.65,2.65v5.4l-4.65,2.7v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65
|
||||
v5.4l-4.65,2.7v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7V31l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7
|
||||
v5.4l4.65,2.7v5.4l-4.65,2.7v5.4l4.65,2.65v5.4l-4.65,2.7v5.4l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.7,2.7
|
||||
l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.7,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7
|
||||
l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7L7,95.7l4.65,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.7,2.7l4.65-2.7l4.65,2.7l4.65-2.7l4.65,2.7
|
||||
l4.65-2.7 M44.25,95.7v-5.4l4.65-2.7l4.65,2.7 M44.25,79.55v-5.4l4.65-2.7l4.65,2.7v5.4L48.9,82.2L44.25,79.55L39.6,82.2
|
||||
l-4.65-2.65 M58.2,87.6v-5.4 M48.9,87.6v-5.4 M53.55,63.35v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L53.55,63.35l-4.65,2.7l-4.65-2.7
|
||||
v-5.4l4.65-2.7l4.65,2.7 M62.85,74.15l-4.65-2.7v-5.4 M53.55,74.15l4.65-2.7 M48.9,71.45v-5.4 M48.9,55.25v-5.4l4.65-2.65
|
||||
l4.65,2.65v5.4 M67.5,71.45v-5.4l4.65-2.7l4.7,2.7v5.4 M67.5,66.05l-4.65-2.7 M58.2,49.85l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
||||
M72.15,63.35v-5.4l4.7-2.7l4.65,2.7v5.4l-4.65,2.7 M76.85,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M67.5,55.25l4.65,2.7
|
||||
M34.95,95.7v-5.4l4.65-2.7l4.65,2.7 M16.3,95.7v-5.4l4.65-2.7l4.65,2.7v5.4 M25.6,90.3l4.7-2.7l4.65,2.7 M25.6,79.55v-5.4l4.7-2.7
|
||||
l4.65,2.7v5.4L30.3,82.2L25.6,79.55l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M20.95,87.6v-5.4 M39.6,87.6v-5.4 M30.3,87.6
|
||||
v-5.4 M7,95.7v-5.4l4.65-2.7l4.65,2.7 M-2.3,95.7v-5.4l4.65-2.7L7,90.3 M2.35,82.2l-4.65-2.65v-5.4l4.65-2.7L7,74.15v5.4L2.35,82.2
|
||||
z M16.3,79.55l-4.65,2.65L7,79.55 M2.35,87.6v-5.4 M11.65,87.6v-5.4 M16.3,74.15l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M2.35,71.45
|
||||
v-5.4L7,63.35l4.65,2.7 M2.35,49.85L7,47.2l4.65,2.65v5.4L7,57.95l-4.65-2.7V49.85L-2.3,47.2v-5.4l4.65-2.7L7,41.8v5.4
|
||||
M11.65,55.25l4.65,2.7v5.4 M7,74.15l4.65-2.7 M7,57.95v5.4 M30.3,71.45v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M16.3,57.95
|
||||
l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M30.3,66.05l-4.7-2.7 M30.3,49.85l4.65-2.65l4.65,2.65v5.4l-4.65,2.7l-4.65-2.7V49.85l-4.7-2.65
|
||||
v-5.4l-4.65-2.7v-5.4L25.6,31l4.7,2.7v5.4l-4.7,2.7 M11.65,49.85l4.65-2.65l4.65,2.65v5.4 M25.6,57.95l4.7-2.7 M34.95,57.95v5.4
|
||||
M34.95,47.2v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M25.6,31v-5.4l4.7-2.7l4.65,2.7V31l-4.65,2.7 M34.95,25.6l4.65-2.7l4.65,2.7
|
||||
V31l-4.65,2.7L34.95,31 M30.3,39.1l4.65,2.7 M39.6,39.1v-5.4 M20.95,39.1l-4.65,2.7l-4.65-2.7v-5.4L16.3,31l4.65,2.7 M16.3,41.8
|
||||
v5.4 M2.35,33.7L-2.3,31v-5.4l4.65-2.7L7,25.6V31L2.35,33.7z M7,25.6l4.65-2.7l4.65,2.7V31 M2.35,39.1v-5.4 M11.65,33.7L7,31
|
||||
M7,41.8l4.65-2.7 M11.65,17.5L7,14.85v-5.4l4.65-2.7l4.65,2.7v5.4L11.65,17.5z M11.65,22.9v-5.4 M2.35,22.9v-5.4L7,14.85 M7,9.45
|
||||
l-4.65-2.7v-5.4L7-1.35l4.65,2.7v5.4 M34.95,14.85v-5.4l4.65-2.7l4.65,2.7v5.4L39.6,17.5L34.95,14.85z M39.6,22.9v-5.4 M25.6,25.6
|
||||
l-4.65-2.7v-5.4l4.65-2.65l4.7,2.65v5.4 M16.3,9.45l4.65-2.7l4.65,2.7v5.4 M34.95,9.45l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
||||
M11.65,1.35l4.65-2.7l4.65,2.7v5.4 M25.6,9.45l4.7-2.7 M30.3,17.5l4.65-2.65 M16.3,25.6l4.65-2.7 M20.95,17.5l-4.65-2.65
|
||||
M76.85,49.85l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7v5.4 M62.85,47.2v-5.4l4.65-2.7l4.65,2.7 M62.85,25.6l4.65-2.7l4.65,2.7V31
|
||||
l-4.65,2.7L62.85,31V25.6l-4.65-2.7v-5.4 M72.15,25.6l4.7-2.7l4.65,2.7V31l-4.65,2.7l-4.7-2.7 M76.85,39.1v-5.4 M67.5,39.1v-5.4
|
||||
M53.55,47.2v-5.4l4.65-2.7l4.65,2.7 M44.25,41.8l4.65-2.7l4.65,2.7 M44.25,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7L44.25,31
|
||||
M62.85,31l-4.65,2.7L53.55,31 M58.2,39.1v-5.4 M48.9,39.1v-5.4 M53.55,14.85v-5.4l4.65-2.7l4.65,2.7v5.4L58.2,17.5L53.55,14.85
|
||||
L48.9,17.5l-4.65-2.65 M48.9,22.9v-5.4 M53.55,9.45l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M44.25,9.45l4.65-2.7 M76.85,22.9v-5.4
|
||||
l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M76.85,17.5l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7v5.4 M67.5,22.9v-5.4l4.65-2.65 M67.5,17.5
|
||||
l-4.65-2.65 M72.15,9.45l-4.65-2.7v-5.4l4.65-2.7l4.7,2.7v5.4 M62.85,9.45l4.65-2.7 M53.55,25.6l4.65-2.7 M44.25,63.35l-4.65,2.7
|
||||
M39.6,55.25l4.65,2.7 M39.6,71.45l4.65,2.7 M67.5,49.85l4.65-2.65 M48.9,49.85l-4.65-2.65 M25.6,47.2l-4.65,2.65 M104.75,87.6
|
||||
l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65V87.6l4.65,2.7 M109.4,79.55l-4.65,2.65 M100.1,95.7v-5.4 M81.5,90.3l4.65-2.7
|
||||
l4.65,2.7v5.4 M81.5,74.15l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65 M90.8,79.55l4.65,2.65 M86.15,87.6v-5.4 M90.8,90.3
|
||||
l4.65-2.7 M95.45,71.45v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L95.45,71.45l-4.65,2.7 M86.15,55.25l4.65,2.7v5.4l-4.65,2.7
|
||||
l-4.65-2.7 M86.15,71.45v-5.4 M95.45,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7L95.45,55.25l-4.65,2.7 M100.1,63.35v-5.4
|
||||
M90.8,63.35l4.65,2.7 M109.4,63.35l-4.65,2.7 M104.75,71.45l4.65,2.7 M104.75,55.25l4.65,2.7 M100.1,79.55v-5.4 M100.1,47.2v-5.4
|
||||
l4.65-2.7l4.65,2.7 M100.1,41.8l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M109.4,31l-4.65,2.7 M81.5,41.8l4.65-2.7l4.65,2.7v5.4
|
||||
l-4.65,2.65 M86.15,22.9l4.65,2.7V31l-4.65,2.7L81.5,31 M100.1,31v-5.4l4.65-2.7l4.65,2.7 M90.8,31l4.65,2.7 M86.15,39.1v-5.4
|
||||
M90.8,41.8l4.65-2.7 M86.15,17.5l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M90.8,14.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65
|
||||
M81.5,9.45l4.65-2.7l4.65,2.7 M86.15,6.75v-5.4l4.65-2.7l4.65,2.7v5.4 M100.1,14.85l4.65,2.65v5.4 M109.4,14.85l-4.65,2.65
|
||||
M100.1,9.45l4.65-2.7l4.65,2.7 M95.45,1.35l4.65-2.7l4.65,2.7v5.4 M95.45,22.9l4.65,2.7 M109.4,47.2l-4.65,2.65 M90.8,47.2
|
||||
l4.65,2.65 M104.75-9.45l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65V-9.45l4.65,2.7 M109.4-17.5l-4.65,2.65 M100.1-1.35v-5.4
|
||||
M90.8-1.35v-5.4l4.65-2.7 M81.5-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4L81.5-6.75v5.4l-4.65,2.7 M90.8-6.75l-4.65-2.7
|
||||
M95.45-14.85L90.8-17.5v-5.4l4.65-2.7l4.65,2.7v5.4 M76.85-14.85l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7v5.4 M86.15-14.85l4.65-2.65
|
||||
M95.45-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L95.45-31z M95.45-25.6V-31 M90.8-22.9l-4.65-2.7V-31l4.65-2.7 M86.15-31
|
||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M86.15-41.8v-5.4l4.65-2.65l4.65,2.65v5.4 M100.1-33.7l4.65,2.7v5.4l-4.65,2.7 M109.4-33.7
|
||||
l-4.65,2.7 M95.45-47.2l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M104.75-41.8l4.65,2.7 M81.5-22.9l4.65-2.7 M104.75-25.6l4.65,2.7
|
||||
M100.1-49.85v-5.4l4.65-2.7l4.65,2.7 M109.4-66.05l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M104.75-63.35v5.4 M100.1-55.25
|
||||
l-4.65-2.7v-5.4l4.65-2.7 M86.15-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M86.15-74.15l4.65,2.7v5.4l-4.65,2.7l-4.65-2.7v-5.4
|
||||
L86.15-74.15v-5.4l4.65-2.65l4.65,2.65 M90.8-71.45l4.65-2.7l4.65,2.7 M95.45-63.35l-4.65-2.7 M90.8-55.25l4.65-2.7 M86.15-57.95
|
||||
v-5.4 M95.45-74.15v-5.4l4.65-2.65l4.65,2.65v5.4 M81.5-71.45l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65 M81.5-82.2v-5.4l4.65-2.7
|
||||
l4.65,2.7v5.4 M86.15-90.3v-5.4 M104.75-95.7v5.4l-4.65,2.7l-4.65-2.7v-5.4 M100.1-82.2v-5.4 M95.45-90.3l-4.65,2.7 M109.4-82.2
|
||||
l-4.65,2.65 M104.75-90.3l4.65,2.7 M109.4-49.85l-4.65,2.65 M72.15-1.35v-5.4l4.7-2.7 M67.5,1.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7
|
||||
M72.15-17.5l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M67.5-14.85v5.4 M53.55-1.35v-5.4l4.65-2.7l4.65,2.7 M48.9,1.35
|
||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M44.25-22.9l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65V-22.9l-4.65-2.7V-31 M53.55-17.5
|
||||
l4.65,2.65v5.4 M48.9-9.45v-5.4 M53.55-33.7v-5.4l4.65-2.7l4.65,2.7v5.4L58.2-31L53.55-33.7z M62.85-22.9l-4.65-2.7V-31 M48.9-25.6
|
||||
V-31l4.65-2.7 M48.9-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M48.9-41.8v-5.4l4.65-2.65l4.65,2.65v5.4 M76.85-25.6V-31l4.65-2.7
|
||||
M76.85-31l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7 M62.85-33.7L67.5-31v5.4 M72.15-39.1l-4.65-2.7v-5.4l4.65-2.65l4.7,2.65v5.4
|
||||
M62.85-39.1l4.65-2.7 M72.15-33.7L67.5-31 M53.55-22.9l4.65-2.7 M58.2-14.85l4.65-2.65 M30.3,1.35l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7
|
||||
v5.4 M30.3-9.45v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M16.3-1.35v-5.4l4.65-2.7l4.65,2.7 M30.3-14.85l-4.7-2.65v-5.4l4.7-2.7
|
||||
l4.65,2.7v5.4 M25.6-17.5l-4.65,2.65L16.3-17.5v-5.4l4.65-2.7l4.65,2.7 M20.95-14.85v5.4 M16.3-6.75l-4.65-2.7v-5.4l4.65-2.65
|
||||
M2.35,1.35l-4.65-2.7v-5.4l4.65-2.7L7-6.75v5.4 M7-17.5l-4.65,2.65L-2.3-17.5v-5.4l4.65-2.7L7-22.9V-17.5l4.65,2.65 M11.65-9.45
|
||||
L7-6.75 M2.35-9.45v-5.4 M11.65-31L7-33.7v-5.4l4.65-2.7l4.65,2.7v5.4L11.65-31z M16.3-22.9l-4.65-2.7V-31 M2.35-25.6V-31L7-33.7
|
||||
M7-39.1l-4.65-2.7v-5.4L7-49.85l4.65,2.65v5.4 M44.25-33.7L39.6-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M20.95-25.6V-31l4.65-2.7
|
||||
l4.7,2.7v5.4 M20.95-47.2l4.65-2.65l4.7,2.65v5.4l-4.7,2.7l-4.65-2.7V-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M30.3-47.2
|
||||
l4.65-2.65l4.65,2.65v5.4 M30.3-41.8l4.65,2.7 M25.6-33.7v-5.4 M34.95-33.7L30.3-31 M34.95-22.9l4.65-2.7 M20.95-31l-4.65-2.7
|
||||
M16.3-39.1l4.65-2.7 M7-22.9l4.65-2.7 M34.95-55.25l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L34.95-55.25v5.4 M25.6-49.85v-5.4
|
||||
l4.7-2.7 M30.3-63.35l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7v5.4 M25.6-66.05l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M30.3-74.15
|
||||
v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M20.95-63.35v5.4 M7-49.85v-5.4l4.65-2.7l4.65,2.7 M2.35-47.2l-4.65-2.65v-5.4l4.65-2.7
|
||||
L7-55.25 M2.35-63.35l-4.65-2.7v-5.4l4.65-2.7L7-71.45v5.4L2.35-63.35z M16.3-71.45l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4
|
||||
M11.65-57.95v-5.4l4.65-2.7 M2.35-57.95v-5.4 M7-66.05l4.65,2.7 M11.65-74.15L7-71.45 M2.35-74.15v-5.4L7-82.2l4.65,2.65
|
||||
M11.65-95.7v5.4L7-87.6l-4.65-2.7v-5.4 M20.95-95.7v5.4l-4.65,2.7l-4.65-2.7 M7-87.6v5.4 M16.3-87.6v5.4 M20.95-90.3l4.65,2.7v5.4
|
||||
l-4.65,2.65 M30.3-79.55l-4.7-2.65 M30.3-95.7v5.4l-4.7,2.7 M48.9-95.7v5.4l-4.65,2.7l-4.65-2.7v-5.4 M34.95-82.2v-5.4l4.65-2.7
|
||||
M30.3-90.3l4.65,2.7 M72.15-49.85v-5.4l4.7-2.7l4.65,2.7 M67.5-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M67.5-74.15l4.65,2.7v5.4
|
||||
l-4.65,2.7l-4.65-2.7v-5.4L67.5-74.15v-5.4l4.65-2.65l4.7,2.65 M81.5-66.05l-4.65,2.7l-4.7-2.7 M72.15-71.45l4.7-2.7 M76.85-63.35
|
||||
v5.4 M67.5-57.95v-5.4 M53.55-49.85v-5.4l4.65-2.7l4.65,2.7 M48.9-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M44.25-66.05v-5.4
|
||||
l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L44.25-66.05l-4.65,2.7 M62.85-66.05l-4.65,2.7l-4.65-2.7 M53.55-71.45l4.65-2.7l4.65,2.7
|
||||
M58.2-57.95v-5.4 M48.9-57.95v-5.4 M48.9-74.15v-5.4l4.65-2.65l4.65,2.65v5.4 M48.9-79.55l-4.65-2.65v-5.4 M58.2-95.7v5.4
|
||||
l-4.65,2.7l-4.65-2.7 M53.55-87.6v5.4 M58.2-79.55l4.65-2.65l4.65,2.65 M62.85-82.2v-5.4l4.65-2.7l4.65,2.7v5.4 M67.5-90.3v-5.4
|
||||
M76.85-95.7v5.4l-4.7,2.7 M58.2-90.3l4.65,2.7 M44.25-17.5l-4.65,2.65 M39.6-9.45l4.65,2.7 M39.6-74.15l4.65,2.7 M39.6-57.95
|
||||
l4.65,2.7 M44.25-49.85L39.6-47.2 M62.85-49.85L58.2-47.2 M16.3-49.85l-4.65,2.65 M44.25-82.2l-4.65,2.65 M76.85-90.3l4.65,2.7
|
||||
M81.5-49.85l-4.65,2.65 M86.15,1.35l-4.65-2.7 M44.25-1.35l-4.65,2.7 M62.85-1.35l-4.65,2.7 M109.4-1.35l-4.65,2.7 M25.6-1.35
|
||||
l-4.65,2.7 M-95.4,95.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-86.1,90.3l4.7-2.7l4.65,2.7v5.4 M-104.7,95.7v-5.4l4.65-2.7l4.65,2.7
|
||||
M-100.05,82.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4L-100.05,82.2z M-95.4,74.15l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65
|
||||
M-86.1,74.15l4.7-2.7l4.65,2.7v5.4l-4.65,2.65l-4.7-2.65 M-100.05,87.6v-5.4 M-90.75,87.6v-5.4 M-81.4,87.6v-5.4 M-109.35,87.6
|
||||
l4.65,2.7 M-104.7,79.55l-4.65,2.65 M-109.35,55.25l4.65,2.7v5.4l-4.65,2.7 M-109.35,71.45l4.65,2.7 M-90.75,66.05l-4.65-2.7v-5.4
|
||||
l4.65-2.7l4.65,2.7v5.4L-90.75,66.05v5.4 M-86.1,57.95l4.7-2.7l4.65,2.7v5.4l-4.65,2.7l-4.7-2.7 M-81.4,71.45v-5.4 M-100.05,71.45
|
||||
v-5.4l4.65-2.7 M-95.4,57.95l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-81.4,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
||||
M-100.05,66.05l-4.65-2.7 M-104.7,57.95l4.65-2.7 M-86.1,41.8l-4.65-2.7v-5.4l4.65-2.7l4.7,2.7v5.4L-86.1,41.8z M-81.4,49.85
|
||||
l-4.7-2.65v-5.4 M-100.05,49.85l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-95.4,31l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7V31
|
||||
l4.65,2.7 M-86.1,31v-5.4l4.7-2.7l4.65,2.7V31l-4.65,2.7 M-100.05,39.1v-5.4 M-90.75,39.1l-4.65,2.7 M-109.35,39.1l4.65,2.7
|
||||
M-104.7,31l-4.65,2.7 M-109.35,6.75l4.65,2.7v5.4l-4.65,2.65 M-86.1,14.85v-5.4l4.7-2.7l4.65,2.7v5.4l-4.65,2.65L-86.1,14.85z
|
||||
M-81.4,22.9v-5.4 M-86.1,25.6l-4.65-2.7v-5.4l4.65-2.65 M-100.05,22.9v-5.4l4.65-2.65l4.65,2.65 M-100.05,6.75v-5.4l4.65-2.7
|
||||
l4.65,2.7v5.4l-4.65,2.7L-100.05,6.75z M-81.4,6.75v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-90.75,6.75l4.65,2.7 M-95.4,14.85v-5.4
|
||||
M-95.4,25.6l4.65-2.7 M-100.05,17.5l-4.65-2.65 M-104.7,9.45l4.65-2.7 M-109.35,22.9l4.65,2.7 M-86.1,47.2l-4.65,2.65
|
||||
M-104.7,47.2l-4.65,2.65 M-11.6,95.7v-5.4l4.65-2.7l4.65,2.7 M-20.9,95.7v-5.4l4.65-2.7l4.65,2.7 M-16.25,82.2l-4.65-2.65v-5.4
|
||||
l4.65-2.7l4.65,2.7v5.4L-16.25,82.2v5.4 M-2.3,79.55l-4.65,2.65l-4.65-2.65 M-6.95,82.2v5.4 M-30.2,95.7v-5.4l4.65-2.7l4.65,2.7
|
||||
M-39.55,95.7v-5.4l4.7-2.7l4.65,2.7 M-39.55,79.55v-5.4l4.7-2.7l4.65,2.7v5.4l-4.65,2.65L-39.55,79.55l-4.65,2.65l-4.65-2.65
|
||||
M-20.9,79.55l-4.65,2.65l-4.65-2.65 M-34.85,87.6v-5.4 M-25.55,87.6v-5.4 M-20.9,74.15l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
||||
M-30.2,74.15l4.65-2.7 M-25.55,66.05l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-39.55,74.15l-4.65-2.7v-5.4l4.65-2.7l4.7,2.7v5.4
|
||||
M-30.2,57.95l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-39.55,63.35v-5.4l4.7-2.7 M-30.2,63.35l-4.65,2.7 M-11.6,74.15l4.65-2.7
|
||||
l4.65,2.7 M-6.95,66.05l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95,66.05v5.4 M-16.25,66.05l4.65-2.7 M-11.6,57.95l-4.65-2.7v-5.4
|
||||
l4.65-2.65l4.65,2.65v5.4 M-16.25,55.25l-4.65,2.7 M-48.85,95.7v-5.4l4.65-2.7l4.65,2.7 M-58.15,95.7v-5.4l4.65-2.7l4.65,2.7
|
||||
M-58.15,79.55v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65L-58.15,79.55l-4.65,2.65l-4.65-2.65 M-44.2,87.6v-5.4 M-53.5,87.6v-5.4
|
||||
M-67.45,95.7v-5.4l4.65-2.7l4.65,2.7 M-76.75,90.3l4.65-2.7l4.65,2.7 M-76.75,74.15l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65
|
||||
M-62.8,87.6v-5.4 M-72.1,87.6v-5.4 M-67.45,74.15l4.65-2.7l4.65,2.7 M-62.8,71.45v-5.4l4.65-2.7l4.65,2.7v5.4 M-62.8,66.05
|
||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-76.75,63.35l4.65,2.7v5.4 M-62.8,55.25v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
||||
M-67.45,63.35l-4.65,2.7 M-72.1,55.25l4.65,2.7 M-48.85,74.15l4.65-2.7 M-44.2,66.05l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7
|
||||
M-53.5,49.85l4.65-2.65l4.65,2.65v5.4 M-53.5,66.05l4.65-2.7 M-53.5,55.25l4.65,2.7 M-48.85,47.2v-5.4l4.65-2.7l4.65,2.7v5.4
|
||||
l-4.65,2.65 M-58.15,47.2v-5.4l4.65-2.7l4.65,2.7 M-58.15,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7l-4.65-2.7V25.6l-4.65-2.7v-5.4
|
||||
M-48.85,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7l-4.65-2.7 M-44.2,39.1v-5.4 M-53.5,39.1v-5.4 M-62.8,49.85l-4.65-2.65v-5.4l4.65-2.7
|
||||
l4.65,2.7 M-76.75,47.2v-5.4l4.65-2.7l4.65,2.7 M-76.75,25.6l4.65-2.7l4.65,2.7V31l-4.65,2.7l-4.65-2.7 M-58.15,31l-4.65,2.7
|
||||
l-4.65-2.7 M-72.1,39.1v-5.4 M-62.8,39.1v-5.4 M-67.45,14.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65L-67.45,14.85l-4.65,2.65
|
||||
l-4.65-2.65 M-72.1,22.9v-5.4 M-62.8,6.75v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-72.1,6.75l4.65,2.7 M-44.2,22.9v-5.4l4.65-2.65
|
||||
l4.7,2.65v5.4l-4.7,2.7 M-44.2,17.5l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-48.85,14.85l-4.65,2.65l-4.65-2.65 M-53.5,22.9v-5.4
|
||||
M-44.2,6.75v-5.4l4.65-2.7l4.7,2.7v5.4l-4.7,2.7 M-53.5,6.75l4.65,2.7 M-67.45,25.6l4.65-2.7 M-11.6,47.2v-5.4l4.65-2.7l4.65,2.7
|
||||
M-11.6,41.8l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-16.25,33.7L-20.9,31v-5.4l4.65-2.7l4.65,2.7V31 M-2.3,31l-4.65,2.7
|
||||
M-30.2,47.2v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-39.55,41.8l4.7-2.7l4.65,2.7 M-34.85,22.9l4.65,2.7V31l-4.65,2.7l-4.7-2.7
|
||||
M-20.9,31l-4.65,2.7L-30.2,31 M-34.85,39.1v-5.4 M-25.55,39.1v-5.4 M-20.9,25.6l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4
|
||||
M-25.55,17.5l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-25.55,6.75v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-30.2,14.85l-4.65,2.65
|
||||
M-34.85,6.75l4.65,2.7 M-6.95,17.5l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95,17.5v5.4l-4.65,2.7 M-11.6,14.85l-4.65,2.65
|
||||
M-16.25,6.75l4.65,2.7 M-16.25,1.35l4.65-2.7l4.65,2.7v5.4 M-6.95,22.9l4.65,2.7 M-30.2,25.6l4.65-2.7 M-16.25,39.1l-4.65,2.7
|
||||
M-67.45,47.2l-4.65,2.65 M-2.3,47.2l-4.65,2.65 M-34.85,49.85l-4.7-2.65 M-16.25,49.85l-4.65-2.65 M-81.4,39.1l4.65,2.7
|
||||
M-11.6-1.35v-5.4l4.65-2.7l4.65,2.7 M-11.6-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-16.25-14.85l-4.65-2.65v-5.4l4.65-2.7
|
||||
l4.65,2.7v5.4 M-2.3-17.5l-4.65,2.65 M-20.9-1.35v-5.4l4.65-2.7 M-20.9-6.75l-4.65-2.7v-5.4l4.65-2.65 M-25.55-9.45l-4.65,2.7
|
||||
l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65 M-30.2-6.75v5.4l-4.65,2.7 M-39.55-1.35v-5.4l4.7-2.7 M-34.85-14.85l-4.7-2.65v-5.4l4.7-2.7
|
||||
l4.65,2.7v5.4 M-30.2-33.7v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7L-30.2-33.7l-4.65,2.7l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7 M-20.9-22.9
|
||||
l-4.65-2.7V-31 M-34.85-25.6V-31 M-39.55-39.1l-4.65-2.7v-5.4l4.65-2.65l4.7,2.65v5.4 M-25.55-41.8v-5.4l4.65-2.65l4.65,2.65v5.4
|
||||
l-4.65,2.7 M-6.95-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95-31v5.4l-4.65,2.7 M-16.25-25.6V-31l4.65-2.7 M-16.25-41.8
|
||||
l4.65,2.7 M-16.25-47.2l4.65-2.65l4.65,2.65v5.4 M-30.2-22.9l4.65-2.7 M-16.25-31l-4.65-2.7 M-6.95-25.6l4.65,2.7 M-44.2,1.35
|
||||
l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-58.15-1.35v-5.4l4.65-2.7l4.65,2.7 M-58.15-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4
|
||||
M-62.8-14.85l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4 M-39.55-17.5l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M-44.2-9.45v-5.4
|
||||
M-53.5-14.85l4.65-2.65 M-62.8,1.35l-4.65-2.7v-5.4l4.65-2.7 M-76.75-6.75l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4L-76.75-6.75
|
||||
v5.4 M-76.75-17.5v-5.4l4.65-2.7l4.65,2.7 M-67.45-17.5l-4.65,2.65 M-72.1-9.45l4.65,2.7 M-67.45-33.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
||||
L-62.8-31L-67.45-33.7z M-62.8-25.6V-31 M-72.1-25.6V-31l4.65-2.7 M-72.1-31l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-76.75-39.1
|
||||
l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-62.8-41.8v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7 M-44.2-25.6V-31l4.65-2.7 M-44.2-31
|
||||
l-4.65-2.7v-5.4l4.65-2.7 M-48.85-33.7L-53.5-31l-4.65-2.7 M-48.85-22.9l-4.65-2.7V-31 M-53.5-41.8l4.65,2.7 M-58.15-22.9l4.65-2.7
|
||||
M-58.15-49.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-48.85-55.25l4.65-2.7l4.65,2.7v5.4 M-58.15-71.45l4.65-2.7l4.65,2.7v5.4
|
||||
l-4.65,2.7l-4.65-2.7V-71.45z M-48.85-71.45l4.65-2.7l4.65,2.7v5.4l-4.65,2.7l-4.65-2.7 M-44.2-57.95v-5.4 M-53.5-57.95v-5.4
|
||||
M-76.75-49.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-67.45-55.25l4.65-2.7l4.65,2.7 M-76.75-55.25l-4.65-2.7v-5.4l4.65-2.7
|
||||
l4.65,2.7v5.4 M-81.4-63.35l-4.7-2.7v-5.4l4.7-2.7l4.65,2.7v5.4 M-81.4-74.15v-5.4l4.65-2.65l4.65,2.65v5.4l-4.65,2.7
|
||||
M-58.15-66.05l-4.65,2.7l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-62.8-57.95v-5.4 M-72.1-74.15l4.65,2.7 M-67.45-66.05l-4.65,2.7
|
||||
M-67.45-82.2v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65L-67.45-82.2l-4.65,2.65 M-76.75-82.2v-5.4l4.65-2.7l4.65,2.7 M-72.1-90.3
|
||||
v-5.4 M-62.8-90.3v-5.4 M-53.5-74.15v-5.4l4.65-2.65l4.65,2.65v5.4 M-58.15-82.2l4.65,2.65 M-58.15-87.6l4.65-2.7l4.65,2.7v5.4
|
||||
M-53.5-90.3v-5.4 M-44.2-95.7v5.4l-4.65,2.7 M-62.8-74.15v-5.4 M-11.6-49.85v-5.4l4.65-2.7l4.65,2.7 M-20.9-49.85v-5.4l4.65-2.7
|
||||
l4.65,2.7 M-16.25-63.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4L-16.25-63.35v5.4 M-2.3-66.05l-4.65,2.7l-4.65-2.7 M-11.6-71.45
|
||||
l4.65-2.7l4.65,2.7 M-6.95-63.35v5.4 M-25.55-47.2l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M-39.55-55.25l4.7-2.7l4.65,2.7
|
||||
M-39.55-71.45l4.7-2.7l4.65,2.7v5.4l-4.65,2.7l-4.7-2.7 M-20.9-71.45l-4.65-2.7v-5.4l4.65-2.65l4.65,2.65v5.4 M-20.9-66.05
|
||||
l-4.65,2.7l-4.65-2.7 M-25.55-74.15l-4.65,2.7 M-34.85-63.35v5.4 M-25.55-57.95v-5.4 M-34.85-74.15v-5.4l4.65-2.65l4.65,2.65
|
||||
M-44.2-79.55l4.65-2.65l4.7,2.65 M-39.55-82.2v-5.4l4.7-2.7l4.65,2.7v5.4 M-34.85-90.3v-5.4 M-16.25-95.7v5.4l-4.65,2.7l-4.65-2.7
|
||||
v-5.4 M-25.55-90.3l-4.65,2.7 M-20.9-82.2v-5.4 M-6.95-79.55l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7v5.4L-6.95-79.55v5.4 M-16.25-79.55
|
||||
l4.65-2.65 M-11.6-87.6l-4.65-2.7 M-6.95-95.7v5.4 M-44.2-90.3l4.65,2.7 M-62.8-47.2l-4.65-2.65 M-44.2-47.2l-4.65-2.65
|
||||
M-30.2-49.85l-4.65,2.65 M-2.3-49.85l-4.65,2.65 M-95.4-1.35v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.7 M-86.1-6.75l4.7-2.7
|
||||
M-100.05,1.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7 M-95.4-17.5l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7V-17.5z M-95.4-22.9
|
||||
l4.65-2.7l4.65,2.7v5.4l-4.65,2.65l-4.65-2.65 M-81.4-14.85l-4.7-2.65 M-100.05-9.45v-5.4 M-90.75-14.85v5.4 M-109.35-9.45
|
||||
l4.65,2.7 M-104.7-17.5l-4.65,2.65 M-109.35-41.8l4.65,2.7v5.4l-4.65,2.7 M-90.75-25.6V-31l4.65-2.7l4.7,2.7v5.4l-4.7,2.7
|
||||
M-100.05-25.6V-31l4.65-2.7l4.65,2.7 M-100.05-47.2l4.65-2.65l4.65,2.65v5.4l-4.65,2.7l-4.65-2.7V-47.2l-4.65-2.65 M-90.75-41.8
|
||||
l4.65,2.7v5.4 M-86.1-39.1l4.7-2.7 M-95.4-33.7v-5.4 M-109.35-25.6l4.65,2.7 M-100.05-31l-4.65-2.7 M-104.7-39.1l4.65-2.7
|
||||
M-95.4-49.85v-5.4l4.65-2.7l4.65,2.7v5.4l-4.65,2.65 M-86.1-55.25l4.7-2.7 M-95.4-55.25l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4
|
||||
M-100.05-63.35l-4.65-2.7v-5.4l4.65-2.7l4.65,2.7v5.4 M-95.4-71.45l4.65-2.7l4.65,2.7 M-86.1-66.05l-4.65,2.7 M-109.35-57.95
|
||||
l4.65,2.7v5.4l-4.65,2.65 M-109.35-74.15l4.65,2.7 M-104.7-66.05l-4.65,2.7 M-109.35-90.3l4.65,2.7v5.4l-4.65,2.65 M-81.4-79.55
|
||||
l-4.7-2.65v-5.4l4.7-2.7l4.65,2.7 M-86.1-82.2l-4.65,2.65l-4.65-2.65v-5.4l4.65-2.7l4.65,2.7 M-100.05-74.15v-5.4l4.65-2.65
|
||||
M-95.4-87.6l-4.65-2.7v-5.4 M-81.4-95.7v5.4 M-90.75-95.7v5.4 M-90.75-79.55v5.4 M-104.7-55.25l4.65-2.7 M-100.05-79.55
|
||||
l-4.65-2.65 M-104.7-87.6l4.65-2.7 M-81.4-47.2l-4.7-2.65 M-76.75-33.7L-81.4-31 M-81.4-25.6l4.65,2.7 M-67.45-1.35l-4.65,2.7
|
||||
M-104.7-1.35l-4.65,2.7 M-81.4,1.35l-4.7-2.7 M-25.55,1.35l-4.65-2.7 M-53.5,1.35l4.65-2.7 M-2.3-1.35l-4.65,2.7 M-2.3,57.95
|
||||
l4.65-2.7 M2.35,66.05l-4.65-2.7 M-2.3-39.1l4.65-2.7 M2.35-31l-4.65-2.7 M2.35-79.55L-2.3-82.2 M-2.3-87.6l4.65-2.7 M-2.3,9.45
|
||||
l4.65-2.7 M2.35,17.5l-4.65-2.65"/>
|
||||
</symbol>
|
||||
<g id="Layer_1">
|
||||
</g>
|
||||
<g id="Layer_6">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#EFEEEE" d="M217.5,108.95c0,29.833-10.533,55.399-31.6,76.7
|
||||
c-0.7,0.833-1.484,1.6-2.351,2.3c-3.466,3.399-7.134,6.483-11,9.25c-18.267,13.467-39.366,20.2-63.3,20.2
|
||||
c-23.967,0-45.033-6.733-63.2-20.2c-4.8-3.4-9.3-7.25-13.5-11.55c-16.367-16.267-26.417-35.167-30.15-56.7
|
||||
c-0.733-4.2-1.217-8.467-1.45-12.8c-0.1-2.4-0.15-4.801-0.15-7.2c0-2.534,0.05-4.95,0.15-7.25c0-0.233,0.066-0.467,0.2-0.7
|
||||
c1.567-26.6,12.033-49.583,31.4-68.95C53.85,11.017,79.417,0.5,109.25,0.5c29.934,0,55.483,10.517,76.65,31.55
|
||||
C206.967,53.483,217.5,79.117,217.5,108.95z"/>
|
||||
</g>
|
||||
<g id="Layer_5">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#010101" d="M195.45,43l-22.4,22.4c-8.833,13-13.25,27.867-13.25,44.6
|
||||
c0,17.934,5.067,33.833,15.2,47.7l19,18.95c-2.5,3.066-5.2,6.066-8.1,9c-0.7,0.833-1.484,1.6-2.351,2.3
|
||||
c-2.533,2.5-5.167,4.816-7.899,6.95L158.1,177.35c-13.934-10.733-30.133-16.1-48.6-16.1c-17.933,0-33.833,5.1-47.7,15.3
|
||||
L43.25,195.15c-3.767-2.867-7.333-6.034-10.7-9.5c-2.8-2.801-5.417-5.667-7.85-8.601l19.15-19.2
|
||||
c10.066-13.966,15.1-29.916,15.1-47.85c0-17.5-4.867-33.017-14.6-46.55l-21.05-21c2.833-3.6,5.917-7.067,9.25-10.4
|
||||
c2.934-2.867,5.934-5.55,9-8.05L61.9,44.35C75.7,54.583,91.567,59.7,109.5,59.7c18.467,0,34.666-5.367,48.6-16.1L177.4,24.35
|
||||
c2.899,2.367,5.732,4.933,8.5,7.7C189.367,35.583,192.55,39.233,195.45,43z"/>
|
||||
</g>
|
||||
<g id="Layer_4">
|
||||
<defs>
|
||||
<path id="SVGID_1_" d="M159.8,110c0-16.733,4.417-31.6,13.25-44.6l22.4-22.4c-2.9-3.767-6.083-7.417-9.55-10.95
|
||||
c-2.768-2.767-5.601-5.333-8.5-7.7L158.1,43.6c-13.934,10.733-30.133,16.1-48.6,16.1c-17.933,0-33.8-5.117-47.6-15.35L41.55,24
|
||||
c-3.066,2.5-6.066,5.183-9,8.05c-3.333,3.333-6.417,6.8-9.25,10.4l21.05,21c9.733,13.533,14.6,29.05,14.6,46.55
|
||||
c0,17.934-5.034,33.884-15.1,47.85l-19.15,19.2c2.433,2.934,5.05,5.8,7.85,8.601c3.367,3.466,6.934,6.633,10.7,9.5L61.8,176.55
|
||||
c13.867-10.2,29.767-15.3,47.7-15.3c18.467,0,34.666,5.366,48.6,16.1L175.65,194.9c2.732-2.134,5.366-4.45,7.899-6.95
|
||||
c0.866-0.7,1.65-1.467,2.351-2.3c2.899-2.934,5.6-5.934,8.1-9l-19-18.95C164.867,143.833,159.8,127.934,159.8,110z"/>
|
||||
</defs>
|
||||
<clipPath id="SVGID_2_">
|
||||
<use xlink:href="#SVGID_1_" overflow="visible"/>
|
||||
</clipPath>
|
||||
<g clip-path="url(#SVGID_2_)">
|
||||
|
||||
<use xlink:href="#hex_grid" width="228.55" height="197.233" x="-114.25" y="-98.617" transform="matrix(1.1415 0 0 -1.1415 105.5 107.75)" overflow="visible"/>
|
||||
</g>
|
||||
</g>
|
||||
<g id="Layer_2">
|
||||
<g>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="#35C6F4" d="M79.1,110.95c-0.033-0.667-0.05-1.333-0.05-2
|
||||
c0-0.7,0.017-1.366,0.05-2c0-0.067,0.017-0.134,0.05-0.2c0.434-7.367,3.333-13.733,8.7-19.1c5.9-5.833,12.983-8.75,21.25-8.75
|
||||
c8.301,0,15.384,2.917,21.25,8.75c5.834,5.934,8.75,13.033,8.75,21.3c0,8.267-2.916,15.35-8.75,21.25
|
||||
c-0.199,0.233-0.416,0.45-0.649,0.649c-0.967,0.934-1.983,1.784-3.05,2.551c-5.066,3.733-10.917,5.6-17.551,5.6
|
||||
c-6.633,0-12.466-1.866-17.5-5.6c-1.333-0.934-2.583-2-3.75-3.2c-4.533-4.5-7.317-9.733-8.35-15.7
|
||||
C79.3,113.334,79.167,112.15,79.1,110.95z M126.1,127.25l3.601,3.6L126.1,127.25z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="none" stroke="#35C6F4" stroke-width="2" stroke-miterlimit="1" d="
|
||||
M158.6,60.25l-15,14.65 M31.7,33.1l40.75,40.65 M126.1,127.25l3.601,3.6 M157.05,158l27.65,28.6 M153.05,153.95l-10.75-11.2
|
||||
M186.6,33l-28,27.25 M33.15,186.25l27.35-27.4"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" fill="none" stroke="#35C6F4" stroke-width="7" stroke-miterlimit="1" d="
|
||||
M158.6,60.25l-16.949,17.2 M59.4,61.35L76.6,78.5 M60.5,158.85l16.75-17.399 M153.05,153.95l4,4.05 M139.45,140.4l13.6,13.55"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 26 KiB |
94
README.md
Normal file
@@ -0,0 +1,94 @@
|
||||
## Status
|
||||
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
[](https://github.com/Radarr/Radarr/pulls)
|
||||
[](http://www.gnu.org/licenses/gpl.html)
|
||||
[](https://github.com/Radarr/Radarr)
|
||||
[](https://github.com/Radar/Radarr/releases/latest)
|
||||
[](https://hub.docker.com/r/linuxserver/radarr/)
|
||||
|
||||
| Service | Master | Develop |
|
||||
|----------|:---------------------------:|:----------------------------:|
|
||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr-usby1) |
|
||||
| Travis | [](https://travis-ci.org/Radarr/Radarr) | [](https://travis-ci.org/Radarr/Radarr) |
|
||||
|
||||
A fork of [Sonarr](https://github.com/Sonarr/Sonarr) to work with movies à la Couchpotato.
|
||||
|
||||
**This fork works independently of Sonarr and will not interfere with it.**
|
||||
|
||||
## Downloads
|
||||
|
||||
[](https://github.com/Radarr/Radarr/releases)
|
||||
|
||||
[](https://ci.appveyor.com/project/galli-leo/radarr-usby1/build/artifacts)
|
||||
|
||||
[](https://store.docker.com/community/images/linuxserver/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr)
|
||||
[](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64)
|
||||
|
||||
To connect to the UI, fire up your browser and open <http://localhost:7878> or <http://your-ip:7878>.
|
||||
|
||||
## Support
|
||||
|
||||
[](https://discord.gg/AD3UP37)
|
||||
[](https://www.reddit.com/r/radarr)
|
||||
[](https://github.com/Radarr/Radarr/issues)
|
||||
|
||||
## Features
|
||||
|
||||
### Current Features
|
||||
|
||||
* Adding new movies with lots of information, such as trailers, ratings, etc.
|
||||
* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc.
|
||||
* Can watch for better quality of the movies you have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
||||
* Full integration with SABnzbd and NZBGet
|
||||
* Automatically searching for releases as well as RSS Sync
|
||||
* Automatically importing downloaded movies
|
||||
* Recognizing Special Editions, Director's Cut, etc.
|
||||
* Identifying releases with hardcoded subs
|
||||
* All indexers supported by Sonarr also supported
|
||||
* New PassThePopcorn Indexer
|
||||
* QBittorrent, Deluge, rTorrent, Transmission and uTorrent download client (Other clients are coming)
|
||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||
* And a beautiful UI
|
||||
|
||||
### Planned Features
|
||||
|
||||
* Scanning PreDB to know when a new release is available
|
||||
* Fixing the other Indexers and download clients
|
||||
* 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, metadata)
|
||||
|
||||
|
||||
## Configuring Development Environment
|
||||
|
||||
### Requirements
|
||||
|
||||
* [Visual Studio Community](https://www.visualstudio.com/vs/community/) or [MonoDevelop](http://www.monodevelop.com)
|
||||
* [Git](https://git-scm.com/downloads)
|
||||
* [Node.js](https://nodejs.org/en/download/)
|
||||
|
||||
### Setup
|
||||
|
||||
* Make sure all the required software mentioned above are installed
|
||||
* Clone the repository into your development machine ([*info*](https://help.github.com/desktop/guides/contributing/working-with-your-remote-repository-on-github-or-github-enterprise))
|
||||
* Grab the submodules `git submodule init && git submodule update`
|
||||
* Install the required Node Packages `npm install`
|
||||
* Start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
> **Notice**
|
||||
> Gulp must be running at all times while you are working with Radarr client source files.
|
||||
|
||||
### Development
|
||||
|
||||
* 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
|
||||
|
||||
## Sponsors
|
||||
|
||||
[JetBrains](http://www.jetbrains.com) for providing us with free licenses to their great tools:
|
||||
* [ReSharper](http://www.jetbrains.com/resharper)
|
||||
* [WebStorm](http://www.jetbrains.com/webstorm)
|
||||
* [TeamCity](http://www.jetbrains.com/teamcity)
|
||||
48
appveyor.yml
Normal file
@@ -0,0 +1,48 @@
|
||||
version: '0.2.0.{build}'
|
||||
|
||||
branches:
|
||||
only:
|
||||
- develop
|
||||
|
||||
assembly_info:
|
||||
patch: true
|
||||
file: 'src\NzbDrone.Common\Properties\SharedAssemblyInfo.cs'
|
||||
assembly_version: '{version}'
|
||||
assembly_file_version: '{version}'
|
||||
assembly_informational_version: '{version}-rc1'
|
||||
|
||||
environment:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: 1
|
||||
|
||||
install:
|
||||
- git submodule update --init --recursive
|
||||
|
||||
build_script:
|
||||
- ps: ./build-appveyor.ps1
|
||||
|
||||
test: off
|
||||
# test:
|
||||
# assemblies:
|
||||
# - '_tests\*Test.dll'
|
||||
# categories:
|
||||
# except:
|
||||
# - IntegrationTest
|
||||
# - AutomationTest
|
||||
|
||||
artifacts:
|
||||
- path: '_artifacts\*.zip'
|
||||
- path: '_artifacts\*.tar.gz'
|
||||
|
||||
cache:
|
||||
- '%USERPROFILE%\.nuget\packages'
|
||||
- node_modules
|
||||
|
||||
pull_requests:
|
||||
do_not_increment_build_number: true
|
||||
|
||||
only_commits:
|
||||
files:
|
||||
- src/
|
||||
- osx/
|
||||
- gulp/
|
||||
- logo/
|
||||
303
build-appveyor.cake
Normal file
@@ -0,0 +1,303 @@
|
||||
#addin "Cake.Npm"
|
||||
#addin "SharpZipLib"
|
||||
#addin "Cake.Compression"
|
||||
|
||||
// Build variables
|
||||
var outputFolder = "./_output";
|
||||
var outputFolderMono = outputFolder + "_mono";
|
||||
var outputFolderOsx = outputFolder + "_osx";
|
||||
var outputFolderOsxApp = outputFolderOsx + "_app";
|
||||
var testPackageFolder = "./_tests";
|
||||
var testSearchPattern = "*.Test/bin/x86/Release";
|
||||
var sourceFolder = "./src";
|
||||
var solutionFile = sourceFolder + "/NzbDrone.sln";
|
||||
var updateFolder = outputFolder + "/NzbDrone.Update";
|
||||
var updateFolderMono = outputFolderMono + "/NzbDrone.Update";
|
||||
|
||||
// Artifact variables
|
||||
var artifactsFolder = "./_artifacts";
|
||||
var artifactsFolderWindows = artifactsFolder + "/windows";
|
||||
var artifactsFolderLinux = artifactsFolder + "/linux";
|
||||
var artifactsFolderOsx = artifactsFolder + "/osx";
|
||||
var artifactsFolderOsxApp = artifactsFolder + "/osx-app";
|
||||
|
||||
// Utility methods
|
||||
public void RemoveEmptyFolders(string startLocation) {
|
||||
foreach (var directory in System.IO.Directory.GetDirectories(startLocation))
|
||||
{
|
||||
RemoveEmptyFolders(directory);
|
||||
|
||||
if (System.IO.Directory.GetFiles(directory).Length == 0 &&
|
||||
System.IO.Directory.GetDirectories(directory).Length == 0)
|
||||
{
|
||||
DeleteDirectory(directory, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanFolder(string path, bool keepConfigFiles) {
|
||||
DeleteFiles(path + "/**/*.transform");
|
||||
|
||||
if (!keepConfigFiles) {
|
||||
DeleteFiles(path + "/**/*.dll.config");
|
||||
}
|
||||
|
||||
DeleteFiles(path + "/**/FluentValidation.resources.dll");
|
||||
DeleteFiles(path + "/**/App.config");
|
||||
|
||||
DeleteFiles(path + "/**/*.less");
|
||||
|
||||
DeleteFiles(path + "/**/*.vshost.exe");
|
||||
|
||||
DeleteFiles(path + "/**/*.dylib");
|
||||
|
||||
RemoveEmptyFolders(path);
|
||||
}
|
||||
|
||||
public void CreateMdbs(string path) {
|
||||
foreach (var file in System.IO.Directory.EnumerateFiles(path, "*.pdb", System.IO.SearchOption.AllDirectories)) {
|
||||
var actualFile = file.Substring(0, file.Length - 4);
|
||||
|
||||
if (FileExists(actualFile + ".exe")) {
|
||||
StartProcess("./tools/pdb2mdb/pdb2mdb.exe", new ProcessSettings()
|
||||
.WithArguments(args => args.Append(actualFile + ".exe")));
|
||||
}
|
||||
|
||||
if (FileExists(actualFile + ".dll")) {
|
||||
StartProcess("./tools/pdb2mdb/pdb2mdb.exe", new ProcessSettings()
|
||||
.WithArguments(args => args.Append(actualFile + ".dll")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build Tasks
|
||||
Task("Compile").Does(() => {
|
||||
// Build
|
||||
if (DirectoryExists(outputFolder)) {
|
||||
DeleteDirectory(outputFolder, true);
|
||||
}
|
||||
|
||||
MSBuild(solutionFile, config =>
|
||||
config.UseToolVersion(MSBuildToolVersion.VS2015)
|
||||
.WithTarget("Clean")
|
||||
.SetVerbosity(Verbosity.Minimal));
|
||||
|
||||
NuGetRestore(solutionFile);
|
||||
|
||||
MSBuild(solutionFile, config =>
|
||||
config.UseToolVersion(MSBuildToolVersion.VS2015)
|
||||
.SetPlatformTarget(PlatformTarget.x86)
|
||||
.SetConfiguration("Release")
|
||||
.WithProperty("AllowedReferenceRelatedFileExtensions", new string[] { ".pdb" })
|
||||
.WithTarget("Build")
|
||||
.SetVerbosity(Verbosity.Minimal));
|
||||
|
||||
CleanFolder(outputFolder, false);
|
||||
|
||||
// Add JsonNet
|
||||
DeleteFiles(outputFolder + "/Newtonsoft.Json.*");
|
||||
CopyFiles(sourceFolder + "/packages/Newtonsoft.Json.*/lib/net35/*.dll", outputFolder);
|
||||
CopyFiles(sourceFolder + "/packages/Newtonsoft.Json.*/lib/net35/*.dll", updateFolder);
|
||||
|
||||
// Remove Mono stuff
|
||||
DeleteFile(outputFolder + "/Mono.Posix.dll");
|
||||
});
|
||||
|
||||
Task("Gulp").Does(() => {
|
||||
Npm
|
||||
.WithLogLevel(NpmLogLevel.Silent)
|
||||
.FromPath(".")
|
||||
.Install()
|
||||
.RunScript("build");
|
||||
});
|
||||
|
||||
Task("PackageMono").Does(() => {
|
||||
// Start mono package
|
||||
if (DirectoryExists(outputFolderMono)) {
|
||||
DeleteDirectory(outputFolderMono, true);
|
||||
}
|
||||
|
||||
CopyDirectory(outputFolder, outputFolderMono);
|
||||
|
||||
// Create MDBs
|
||||
CreateMdbs(outputFolderMono);
|
||||
|
||||
// Remove PDBs
|
||||
DeleteFiles(outputFolderMono + "/**/*.pdb");
|
||||
|
||||
// Remove service helpers
|
||||
DeleteFiles(outputFolderMono + "/ServiceUninstall.*");
|
||||
DeleteFiles(outputFolderMono + "/ServiceInstall.*");
|
||||
|
||||
// Remove native windows binaries
|
||||
DeleteFiles(outputFolderMono + "/sqlite3.*");
|
||||
DeleteFiles(outputFolderMono + "/MediaInfo.*");
|
||||
|
||||
// Adding NzbDrone.Core.dll.config (for dllmap)
|
||||
CopyFile(sourceFolder + "/NzbDrone.Core/NzbDrone.Core.dll.config", outputFolderMono + "/NzbDrone.Core.dll.config");
|
||||
|
||||
// Adding CurlSharp.dll.config (for dllmap)
|
||||
CopyFile(sourceFolder + "/NzbDrone.Common/CurlSharp.dll.config", outputFolderMono + "/CurlSharp.dll.config");
|
||||
|
||||
// Renaming Radarr.Console.exe to Radarr.exe
|
||||
DeleteFiles(outputFolderMono + "/Radarr.exe*");
|
||||
MoveFile(outputFolderMono + "/Radarr.Console.exe", outputFolderMono + "/Radarr.exe");
|
||||
MoveFile(outputFolderMono + "/Radarr.Console.exe.config", outputFolderMono + "/Radarr.exe.config");
|
||||
MoveFile(outputFolderMono + "/Radarr.Console.exe.mdb", outputFolderMono + "/Radarr.exe.mdb");
|
||||
|
||||
// Remove NzbDrone.Windows.*
|
||||
DeleteFiles(outputFolderMono + "/NzbDrone.Windows.*");
|
||||
|
||||
// Adding NzbDrone.Mono to updatePackage
|
||||
CopyFiles(outputFolderMono + "/NzbDrone.Mono.*", updateFolderMono);
|
||||
});
|
||||
|
||||
Task("PackageOsx").Does(() => {
|
||||
// Start osx package
|
||||
if (DirectoryExists(outputFolderOsx)) {
|
||||
DeleteDirectory(outputFolderOsx, true);
|
||||
}
|
||||
|
||||
CopyDirectory(outputFolderMono, outputFolderOsx);
|
||||
|
||||
// Adding sqlite dylibs
|
||||
CopyFiles(sourceFolder + "/Libraries/Sqlite/*.dylib", outputFolderOsx);
|
||||
|
||||
// Adding MediaInfo dylib
|
||||
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
|
||||
|
||||
// Adding Startup script
|
||||
CopyFile("./osx/Sonarr", outputFolderOsx + "/Sonarr");
|
||||
});
|
||||
|
||||
Task("PackageOsxApp").Does(() => {
|
||||
// Start osx app package
|
||||
if (DirectoryExists(outputFolderOsxApp)) {
|
||||
DeleteDirectory(outputFolderOsxApp, true);
|
||||
}
|
||||
|
||||
CreateDirectory(outputFolderOsxApp);
|
||||
|
||||
// Copy osx package files
|
||||
CopyDirectory("./osx/Radarr.app", outputFolderOsxApp + "/Radarr.app");
|
||||
CopyDirectory(outputFolderOsx, outputFolderOsxApp + "/Radarr.app/Contents/MacOS");
|
||||
});
|
||||
|
||||
Task("PackageTests").Does(() => {
|
||||
// Start tests package
|
||||
if (DirectoryExists(testPackageFolder)) {
|
||||
DeleteDirectory(testPackageFolder, true);
|
||||
}
|
||||
|
||||
CreateDirectory(testPackageFolder);
|
||||
|
||||
// Copy tests
|
||||
CopyFiles(sourceFolder + "/" + testSearchPattern + "/*", testPackageFolder);
|
||||
foreach (var directory in System.IO.Directory.GetDirectories(sourceFolder, "*.Test")) {
|
||||
var releaseDirectory = directory + "/bin/x86/Release";
|
||||
if (DirectoryExists(releaseDirectory)) {
|
||||
foreach (var releaseSubDirectory in System.IO.Directory.GetDirectories(releaseDirectory)) {
|
||||
Information(System.IO.Path.GetDirectoryName(releaseSubDirectory));
|
||||
CopyDirectory(releaseSubDirectory, testPackageFolder + "/" + System.IO.Path.GetFileName(releaseSubDirectory));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Install NUnit.ConsoleRunner
|
||||
NuGetInstall("NUnit.ConsoleRunner", new NuGetInstallSettings {
|
||||
Version = "3.2.0",
|
||||
OutputDirectory = testPackageFolder
|
||||
});
|
||||
|
||||
// Copy dlls
|
||||
CopyFiles(outputFolder + "/*.dll", testPackageFolder);
|
||||
|
||||
// Copy scripts
|
||||
CopyFiles("./*.sh", testPackageFolder);
|
||||
|
||||
// Create MDBs for tests
|
||||
CreateMdbs(testPackageFolder);
|
||||
|
||||
// Remove config
|
||||
DeleteFiles(testPackageFolder + "/*.log.config");
|
||||
|
||||
// Clean
|
||||
CleanFolder(testPackageFolder, true);
|
||||
|
||||
// Adding NzbDrone.Core.dll.config (for dllmap)
|
||||
CopyFile(sourceFolder + "/NzbDrone.Core/NzbDrone.Core.dll.config", testPackageFolder + "/NzbDrone.Core.dll.config");
|
||||
|
||||
// Adding CurlSharp.dll.config (for dllmap)
|
||||
CopyFile(sourceFolder + "/NzbDrone.Common/CurlSharp.dll.config", testPackageFolder + "/CurlSharp.dll.config");
|
||||
|
||||
// Adding CurlSharp libraries
|
||||
CopyFiles(sourceFolder + "/ExternalModules/CurlSharp/libs/i386/*", testPackageFolder);
|
||||
});
|
||||
|
||||
Task("CleanupWindowsPackage").Does(() => {
|
||||
// Remove mono
|
||||
DeleteFiles(outputFolder + "/NzbDrone.Mono.*");
|
||||
|
||||
// Adding NzbDrone.Windows to updatePackage
|
||||
CopyFiles(outputFolder + "/NzbDrone.Windows.*", updateFolder);
|
||||
});
|
||||
|
||||
Task("Build")
|
||||
.IsDependentOn("Compile")
|
||||
.IsDependentOn("Gulp")
|
||||
.IsDependentOn("PackageMono")
|
||||
.IsDependentOn("PackageOsx")
|
||||
.IsDependentOn("PackageOsxApp")
|
||||
.IsDependentOn("PackageTests")
|
||||
.IsDependentOn("CleanupWindowsPackage");
|
||||
|
||||
// Build Artifacts
|
||||
Task("CleanArtifacts").Does(() => {
|
||||
if (DirectoryExists(artifactsFolder)) {
|
||||
DeleteDirectory(artifactsFolder, true);
|
||||
}
|
||||
|
||||
CreateDirectory(artifactsFolder);
|
||||
});
|
||||
|
||||
Task("ArtifactsWindows").Does(() => {
|
||||
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
|
||||
});
|
||||
|
||||
Task("ArtifactsLinux").Does(() => {
|
||||
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
|
||||
});
|
||||
|
||||
Task("ArtifactsOsx").Does(() => {
|
||||
CopyDirectory(outputFolderOsx, artifactsFolderOsx + "/Radarr");
|
||||
});
|
||||
|
||||
Task("ArtifactsOsxApp").Does(() => {
|
||||
CopyDirectory(outputFolderOsxApp, artifactsFolderOsxApp);
|
||||
});
|
||||
|
||||
Task("CompressArtifacts").Does(() => {
|
||||
var prefix = "";
|
||||
|
||||
if (AppVeyor.IsRunningOnAppVeyor) {
|
||||
prefix += AppVeyor.Environment.Repository.Branch + ".";
|
||||
prefix += AppVeyor.Environment.Build.Version + ".";
|
||||
}
|
||||
|
||||
Zip(artifactsFolderWindows, artifactsFolder + "/Radarr." + prefix + "windows.zip");
|
||||
GZipCompress(artifactsFolderLinux, artifactsFolder + "/Radarr." + prefix + "linux.tar.gz");
|
||||
GZipCompress(artifactsFolderOsx, artifactsFolder + "/Radarr." + prefix + "osx.tar.gz");
|
||||
Zip(artifactsFolderOsxApp, artifactsFolder + "/Radarr." + prefix + "osx-app.zip");
|
||||
});
|
||||
|
||||
Task("Artifacts")
|
||||
.IsDependentOn("CleanArtifacts")
|
||||
.IsDependentOn("ArtifactsWindows")
|
||||
.IsDependentOn("ArtifactsLinux")
|
||||
.IsDependentOn("ArtifactsOsx")
|
||||
.IsDependentOn("ArtifactsOsxApp")
|
||||
.IsDependentOn("CompressArtifacts");
|
||||
|
||||
// Run
|
||||
RunTarget("Build");
|
||||
RunTarget("Artifacts");
|
||||
184
build-appveyor.ps1
Normal file
@@ -0,0 +1,184 @@
|
||||
##########################################################################
|
||||
# This is the Cake bootstrapper script for PowerShell.
|
||||
# This file was downloaded from https://github.com/cake-build/resources
|
||||
# Feel free to change this file to fit your needs.
|
||||
##########################################################################
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This is a Powershell script to bootstrap a Cake build.
|
||||
.DESCRIPTION
|
||||
This Powershell script will download NuGet if missing, restore NuGet tools (including Cake)
|
||||
and execute your Cake build script with the parameters you provide.
|
||||
.PARAMETER Script
|
||||
The build script to execute.
|
||||
.PARAMETER Target
|
||||
The build script target to run.
|
||||
.PARAMETER Configuration
|
||||
The build configuration to use.
|
||||
.PARAMETER Verbosity
|
||||
Specifies the amount of information to be displayed.
|
||||
.PARAMETER Experimental
|
||||
Tells Cake to use the latest Roslyn release.
|
||||
.PARAMETER WhatIf
|
||||
Performs a dry run of the build script.
|
||||
No tasks will be executed.
|
||||
.PARAMETER Mono
|
||||
Tells Cake to use the Mono scripting engine.
|
||||
.PARAMETER SkipToolPackageRestore
|
||||
Skips restoring of packages.
|
||||
.PARAMETER ScriptArgs
|
||||
Remaining arguments are added here.
|
||||
.LINK
|
||||
http://cakebuild.net
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
Param(
|
||||
[string]$Script = "build-appveyor.cake",
|
||||
[string]$Target = "Default",
|
||||
[ValidateSet("Release", "Debug")]
|
||||
[string]$Configuration = "Release",
|
||||
[ValidateSet("Quiet", "Minimal", "Normal", "Verbose", "Diagnostic")]
|
||||
[string]$Verbosity = "Verbose",
|
||||
[switch]$Experimental,
|
||||
[Alias("DryRun","Noop")]
|
||||
[switch]$WhatIf,
|
||||
[switch]$Mono,
|
||||
[switch]$SkipToolPackageRestore,
|
||||
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
|
||||
[string[]]$ScriptArgs
|
||||
)
|
||||
|
||||
[Reflection.Assembly]::LoadWithPartialName("System.Security") | Out-Null
|
||||
function MD5HashFile([string] $filePath)
|
||||
{
|
||||
if ([string]::IsNullOrEmpty($filePath) -or !(Test-Path $filePath -PathType Leaf))
|
||||
{
|
||||
return $null
|
||||
}
|
||||
|
||||
[System.IO.Stream] $file = $null;
|
||||
[System.Security.Cryptography.MD5] $md5 = $null;
|
||||
try
|
||||
{
|
||||
$md5 = [System.Security.Cryptography.MD5]::Create()
|
||||
$file = [System.IO.File]::OpenRead($filePath)
|
||||
return [System.BitConverter]::ToString($md5.ComputeHash($file))
|
||||
}
|
||||
finally
|
||||
{
|
||||
if ($file -ne $null)
|
||||
{
|
||||
$file.Dispose()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Preparing to run build script..."
|
||||
|
||||
if(!$PSScriptRoot){
|
||||
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
|
||||
}
|
||||
|
||||
$TOOLS_DIR = Join-Path $PSScriptRoot "tools-cake"
|
||||
$NUGET_EXE = Join-Path $TOOLS_DIR "nuget.exe"
|
||||
$CAKE_EXE = Join-Path $TOOLS_DIR "Cake/Cake.exe"
|
||||
$NUGET_URL = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||
$PACKAGES_CONFIG = Join-Path $TOOLS_DIR "packages.config"
|
||||
$PACKAGES_CONFIG_MD5 = Join-Path $TOOLS_DIR "packages.config.md5sum"
|
||||
|
||||
# Should we use mono?
|
||||
$UseMono = "";
|
||||
if($Mono.IsPresent) {
|
||||
Write-Verbose -Message "Using the Mono based scripting engine."
|
||||
$UseMono = "-mono"
|
||||
}
|
||||
|
||||
# Should we use the new Roslyn?
|
||||
$UseExperimental = "";
|
||||
if($Experimental.IsPresent -and !($Mono.IsPresent)) {
|
||||
Write-Verbose -Message "Using experimental version of Roslyn."
|
||||
$UseExperimental = "-experimental"
|
||||
}
|
||||
|
||||
# Is this a dry run?
|
||||
$UseDryRun = "";
|
||||
if($WhatIf.IsPresent) {
|
||||
$UseDryRun = "-dryrun"
|
||||
}
|
||||
|
||||
# Make sure tools folder exists
|
||||
if ((Test-Path $PSScriptRoot) -and !(Test-Path $TOOLS_DIR)) {
|
||||
Write-Verbose -Message "Creating tools directory..."
|
||||
New-Item -Path $TOOLS_DIR -Type directory | out-null
|
||||
}
|
||||
|
||||
# Make sure that packages.config exist.
|
||||
if (!(Test-Path $PACKAGES_CONFIG)) {
|
||||
Write-Verbose -Message "Downloading packages.config..."
|
||||
try { (New-Object System.Net.WebClient).DownloadFile("http://cakebuild.net/download/bootstrapper/packages", $PACKAGES_CONFIG) } catch {
|
||||
Throw "Could not download packages.config."
|
||||
}
|
||||
}
|
||||
|
||||
# Try find NuGet.exe in path if not exists
|
||||
if (!(Test-Path $NUGET_EXE)) {
|
||||
Write-Verbose -Message "Trying to find nuget.exe in PATH..."
|
||||
$existingPaths = $Env:Path -Split ';' | Where-Object { (![string]::IsNullOrEmpty($_)) -and (Test-Path $_) }
|
||||
$NUGET_EXE_IN_PATH = Get-ChildItem -Path $existingPaths -Filter "nuget.exe" | Select -First 1
|
||||
if ($NUGET_EXE_IN_PATH -ne $null -and (Test-Path $NUGET_EXE_IN_PATH.FullName)) {
|
||||
Write-Verbose -Message "Found in PATH at $($NUGET_EXE_IN_PATH.FullName)."
|
||||
$NUGET_EXE = $NUGET_EXE_IN_PATH.FullName
|
||||
}
|
||||
}
|
||||
|
||||
# Try download NuGet.exe if not exists
|
||||
if (!(Test-Path $NUGET_EXE)) {
|
||||
Write-Verbose -Message "Downloading NuGet.exe..."
|
||||
try {
|
||||
(New-Object System.Net.WebClient).DownloadFile($NUGET_URL, $NUGET_EXE)
|
||||
} catch {
|
||||
Throw "Could not download NuGet.exe."
|
||||
}
|
||||
}
|
||||
|
||||
# Save nuget.exe path to environment to be available to child processed
|
||||
$ENV:NUGET_EXE = $NUGET_EXE
|
||||
|
||||
# Restore tools from NuGet?
|
||||
if(-Not $SkipToolPackageRestore.IsPresent) {
|
||||
Push-Location
|
||||
Set-Location $TOOLS_DIR
|
||||
|
||||
# Check for changes in packages.config and remove installed tools if true.
|
||||
[string] $md5Hash = MD5HashFile($PACKAGES_CONFIG)
|
||||
if((!(Test-Path $PACKAGES_CONFIG_MD5)) -Or
|
||||
($md5Hash -ne (Get-Content $PACKAGES_CONFIG_MD5 ))) {
|
||||
Write-Verbose -Message "Missing or changed package.config hash..."
|
||||
Remove-Item * -Recurse -Exclude packages.config,nuget.exe
|
||||
}
|
||||
|
||||
Write-Verbose -Message "Restoring tools from NuGet..."
|
||||
$NuGetOutput = Invoke-Expression "&`"$NUGET_EXE`" install -ExcludeVersion -OutputDirectory `"$TOOLS_DIR`""
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Throw "An error occured while restoring NuGet tools."
|
||||
}
|
||||
else
|
||||
{
|
||||
$md5Hash | Out-File $PACKAGES_CONFIG_MD5 -Encoding "ASCII"
|
||||
}
|
||||
Write-Verbose -Message ($NuGetOutput | out-string)
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
# Make sure that Cake has been installed.
|
||||
if (!(Test-Path $CAKE_EXE)) {
|
||||
Throw "Could not find Cake.exe at $CAKE_EXE"
|
||||
}
|
||||
|
||||
# Start Cake
|
||||
Write-Host "Running build script..."
|
||||
Invoke-Expression "& `"$CAKE_EXE`" `"$Script`" -target=`"$Target`" -configuration=`"$Configuration`" -verbosity=`"$Verbosity`" $UseMono $UseDryRun $UseExperimental $ScriptArgs"
|
||||
exit $LASTEXITCODE
|
||||
8
build.sh
@@ -154,8 +154,8 @@ PackageMono()
|
||||
cp $sourceFolder/NzbDrone.Common/CurlSharp.dll.config $outputFolderMono
|
||||
|
||||
echo "Renaming NzbDrone.Console.exe to NzbDrone.exe"
|
||||
rm $outputFolderMono/NzbDrone.exe*
|
||||
for file in $outputFolderMono/NzbDrone.Console.exe*; do
|
||||
rm $outputFolderMono/Radarr.exe*
|
||||
for file in $outputFolderMono/Radarr.Console.exe*; do
|
||||
mv "$file" "${file//.Console/}"
|
||||
done
|
||||
|
||||
@@ -192,8 +192,8 @@ PackageOsxApp()
|
||||
rm -rf $outputFolderOsxApp
|
||||
mkdir $outputFolderOsxApp
|
||||
|
||||
cp -r ./osx/Sonarr.app $outputFolderOsxApp
|
||||
cp -r $outputFolderOsx $outputFolderOsxApp/Sonarr.app/Contents/MacOS
|
||||
cp -r ./osx/Radarr.app $outputFolderOsxApp
|
||||
cp -r $outputFolderOsx $outputFolderOsxApp/Radarr.app/Contents/MacOS
|
||||
|
||||
echo "##teamcity[progressFinish 'Creating OS X App Package']"
|
||||
}
|
||||
|
||||
@@ -19,13 +19,16 @@ gulp.task('less', function() {
|
||||
paths.src.root + 'Series/series.less',
|
||||
paths.src.root + 'Activity/activity.less',
|
||||
paths.src.root + 'AddSeries/addSeries.less',
|
||||
paths.src.root + 'AddMovies/addMovies.less',
|
||||
paths.src.root + 'Calendar/calendar.less',
|
||||
paths.src.root + 'Cells/cells.less',
|
||||
paths.src.root + 'ManualImport/manualimport.less',
|
||||
paths.src.root + 'Settings/settings.less',
|
||||
paths.src.root + 'System/Logs/logs.less',
|
||||
paths.src.root + 'System/Update/update.less',
|
||||
paths.src.root + 'System/Info/info.less'
|
||||
paths.src.root + 'System/Info/info.less',
|
||||
paths.src.root + 'Movies/movies.less',
|
||||
|
||||
];
|
||||
|
||||
return gulp.src(src)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>Sonarr</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>sonarr.icns</string>
|
||||
<string>radarr.icns</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>com.osx.sonarr.tv</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
BIN
osx/Radarr.app/Contents/Resources/radarr.icns
Normal file
16
osx/Sonarr
@@ -4,9 +4,9 @@
|
||||
DIR=$(cd "$(dirname "$0")"; pwd)
|
||||
|
||||
#change these values to match your app
|
||||
EXE_PATH="$DIR/NzbDrone.exe"
|
||||
EXE_PATH="$DIR/Radarr.exe"
|
||||
APPNAME="Sonarr"
|
||||
|
||||
|
||||
#set up environment
|
||||
if [[ -x '/opt/local/bin/mono' ]]; then
|
||||
export PATH="/opt/local/bin:$PATH"
|
||||
@@ -29,11 +29,11 @@ export DYLD_FALLBACK_LIBRARY_PATH="$DYLD_FALLBACK_LIBRARY_PATH:$HOME/lib:/usr/lo
|
||||
#mono version check
|
||||
REQUIRED_MAJOR=3
|
||||
REQUIRED_MINOR=10
|
||||
|
||||
|
||||
VERSION_TITLE="Cannot launch $APPNAME"
|
||||
VERSION_MSG="$APPNAME requires Mono Runtime Environment(MRE) $REQUIRED_MAJOR.$REQUIRED_MINOR or later."
|
||||
DOWNLOAD_URL="http://www.mono-project.com/download/#download-mac"
|
||||
|
||||
|
||||
MONO_VERSION="$(mono --version | grep 'Mono JIT compiler version ' | cut -f5 -d\ )"
|
||||
# if [[ -o DEBUG ]]; then osascript -e "display dialog \"MONO_VERSION: $MONO_VERSION\""; fi
|
||||
|
||||
@@ -42,7 +42,7 @@ MONO_VERSION_MAJOR="$(echo $MONO_VERSION | cut -f1 -d.)"
|
||||
MONO_VERSION_MINOR="$(echo $MONO_VERSION | cut -f2 -d.)"
|
||||
if [ -z "$MONO_VERSION" ] \
|
||||
|| [ $MONO_VERSION_MAJOR -lt $REQUIRED_MAJOR ] \
|
||||
|| [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ]
|
||||
|| [ $MONO_VERSION_MAJOR -eq $REQUIRED_MAJOR -a $MONO_VERSION_MINOR -lt $REQUIRED_MINOR ]
|
||||
then
|
||||
osascript \
|
||||
-e "set question to display dialog \"$VERSION_MSG\" with title \"$VERSION_TITLE\" buttons {\"Cancel\", \"Download...\"} default button 2" \
|
||||
@@ -51,8 +51,8 @@ then
|
||||
echo "$VERSION_MSG"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
MONO_EXEC="exec mono --debug"
|
||||
|
||||
|
||||
#run app using mono
|
||||
$MONO_EXEC "$EXE_PATH"
|
||||
$MONO_EXEC "$EXE_PATH"
|
||||
|
||||
68
package.sh
Normal file
@@ -0,0 +1,68 @@
|
||||
if [ $# -eq 0 ]; then
|
||||
if [ "$TRAVIS_PULL_REQUEST" != false ]; then
|
||||
echo "Need to supply version argument" && exit;
|
||||
fi
|
||||
fi
|
||||
|
||||
# Use mono or .net depending on OS
|
||||
case "$(uname -s)" in
|
||||
CYGWIN*|MINGW32*|MINGW64*|MSYS*)
|
||||
# on windows, use dotnet
|
||||
runtime="dotnet"
|
||||
;;
|
||||
*)
|
||||
# otherwise use mono
|
||||
runtime="mono"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
||||
VERSION="`date +%H:%M:%S`"
|
||||
YEAR="`date +%Y`"
|
||||
MONTH="`date +%m`"
|
||||
DAY="`date +%d`"
|
||||
else
|
||||
VERSION=$1
|
||||
fi
|
||||
outputFolder='./_output'
|
||||
outputFolderMono='./_output_mono'
|
||||
outputFolderOsx='./_output_osx'
|
||||
outputFolderOsxApp='./_output_osx_app'
|
||||
|
||||
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
||||
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr
|
||||
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
||||
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log
|
||||
|
||||
cp -r $outputFolder/ Radarr_Windows_$VERSION
|
||||
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
|
||||
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
|
||||
|
||||
if [ $runtime = "dotnet" ] ; then
|
||||
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
|
||||
./7za.exe a -ttar -so Radarr_Mono_$VERSION.tar ./Radarr_Mono_$VERSION/* | ./7za.exe a -si Radarr_Mono_$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
|
||||
else
|
||||
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null
|
||||
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz
|
||||
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null
|
||||
fi
|
||||
ftp -n ftp.leonardogalli.ch << END_SCRIPT
|
||||
passive
|
||||
quote USER $FTP_USER
|
||||
quote PASS $FTP_PASS
|
||||
mkdir builds
|
||||
cd builds
|
||||
mkdir $YEAR
|
||||
cd $YEAR
|
||||
mkdir $MONTH
|
||||
cd $MONTH
|
||||
mkdir $DAY
|
||||
cd $DAY
|
||||
binary
|
||||
put Radarr_Windows_$VERSION.zip
|
||||
put Radarr_Mono_$VERSION.zip
|
||||
put Radarr_OSX_$VERSION.zip
|
||||
quit
|
||||
END_SCRIPT
|
||||
53
readme.md
@@ -1,53 +0,0 @@
|
||||
# Sonarr #
|
||||
|
||||
This fork of Sonarr aims to turn it into something like Couchpotato.
|
||||
At the moment almost nothing is implemented.
|
||||
|
||||
## Major Features Include: ##
|
||||
|
||||
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
||||
* Automatically detects new episodes
|
||||
* Can scan your existing library and download any missing episodes
|
||||
* Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray*
|
||||
* Automatic failed download handling will try another release if one fails
|
||||
* Manual search so you can pick any release or to see why a release was not downloaded automatically
|
||||
* Fully configurable episode renaming
|
||||
* Full integration with SABNzbd and NzbGet
|
||||
* Full integration with XBMC, Plex (notification, library update, metadata)
|
||||
* Full support for specials and multi-episode releases
|
||||
* And a beautiful UI
|
||||
|
||||
|
||||
## Configuring Development Environment: ##
|
||||
|
||||
### Requirements ###
|
||||
- Visual Studio 2015 [Free Community Edition](https://www.visualstudio.com/en-us/products/visual-studio-community-vs.aspx)
|
||||
- [Git](http://git-scm.com/downloads)
|
||||
- [NodeJS](http://nodejs.org/download/)
|
||||
|
||||
### Setup ###
|
||||
|
||||
- Make sure all the required software mentioned above are installed.
|
||||
- Clone the repository into your development machine. [*info*](https://help.github.com/articles/working-with-repositories)
|
||||
- Grab the submodules `git submodule init && git submodule update`
|
||||
- install the required Node Packages `npm install`
|
||||
- start gulp to monitor your dev environment for any changes that need post processing using `npm start` command.
|
||||
|
||||
*Please note gulp must be running at all times while you are working with Sonarr client source files.*
|
||||
|
||||
|
||||
### Development ###
|
||||
- Open `NzbDrone.sln` in Visual Studio
|
||||
- Make sure `NzbDrone.Console` is set as the startup project
|
||||
|
||||
|
||||
### License ###
|
||||
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||
Copyright 2010-2016
|
||||
|
||||
|
||||
### Sponsors ###
|
||||
- [JetBrains](http://www.jetbrains.com/) for providing us with free licenses to their great tools
|
||||
- [ReSharper](http://www.jetbrains.com/resharper/)
|
||||
- [WebStorm](http://www.jetbrains.com/webstorm/)
|
||||
- [TeamCity](http://www.jetbrains.com/teamcity/)
|
||||
BIN
sonarr.icns
Normal file
@@ -2,4 +2,4 @@
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
[assembly: AssemblyVersion("0.1.0.*")]
|
||||
|
||||
@@ -21,4 +21,3 @@ using System.Runtime.InteropServices;
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("260b2ff9-d3b7-4d8a-b720-a12c93d045e5")]
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
|
||||
@@ -64,6 +64,8 @@ namespace NzbDrone.Api.Authentication
|
||||
new DefaultHmacProvider(new PassphraseKeyGenerator(_configService.HmacPassphrase, Encoding.ASCII.GetBytes(_configService.HmacSalt)))
|
||||
);
|
||||
|
||||
FormsAuthentication.FormsAuthenticationCookieName = "_ncfaradarr"; //For those people that both have sonarr and radarr.
|
||||
|
||||
FormsAuthentication.Enable(pipelines, new FormsAuthenticationConfiguration
|
||||
{
|
||||
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Api.Series;
|
||||
@@ -11,13 +12,14 @@ namespace NzbDrone.Api.Blacklist
|
||||
{
|
||||
public int SeriesId { get; set; }
|
||||
public List<int> EpisodeIds { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public DateTime Date { get; set; }
|
||||
public DownloadProtocol Protocol { get; set; }
|
||||
public string Indexer { get; set; }
|
||||
public string Message { get; set; }
|
||||
|
||||
public MovieResource Movie { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
}
|
||||
|
||||
@@ -30,7 +32,7 @@ namespace NzbDrone.Api.Blacklist
|
||||
return new BlacklistResource
|
||||
{
|
||||
Id = model.Id,
|
||||
|
||||
MovieId = model.MovieId,
|
||||
SeriesId = model.SeriesId,
|
||||
EpisodeIds = model.EpisodeIds,
|
||||
SourceTitle = model.SourceTitle,
|
||||
@@ -39,7 +41,7 @@ namespace NzbDrone.Api.Blacklist
|
||||
Protocol = model.Protocol,
|
||||
Indexer = model.Indexer,
|
||||
Message = model.Message,
|
||||
|
||||
Movie = model.Movie.ToResource(),
|
||||
Series = model.Series.ToResource()
|
||||
};
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ namespace NzbDrone.Api.Calendar
|
||||
|
||||
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
|
||||
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
||||
Get["/Radarr.ics"] = options => GetCalendarFeed();
|
||||
}
|
||||
|
||||
private Response GetCalendarFeed()
|
||||
|
||||
@@ -2,24 +2,38 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.MovieStats;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.Calendar
|
||||
{
|
||||
public class CalendarModule : EpisodeModuleWithSignalR
|
||||
public class CalendarModule : MovieModule
|
||||
{
|
||||
public CalendarModule(IEpisodeService episodeService,
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "calendar")
|
||||
public CalendarModule(IBroadcastSignalRMessage signalR,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper)
|
||||
: base(signalR, moviesService, moviesStatisticsService, sceneMappingService, coverMapper, "calendar")
|
||||
{
|
||||
|
||||
GetResourceAll = GetCalendar;
|
||||
}
|
||||
|
||||
private List<EpisodeResource> GetCalendar()
|
||||
private List<MovieResource> GetCalendar()
|
||||
{
|
||||
var start = DateTime.Today;
|
||||
var end = DateTime.Today.AddDays(2);
|
||||
@@ -33,9 +47,9 @@ namespace NzbDrone.Api.Calendar
|
||||
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
|
||||
if (queryIncludeUnmonitored.HasValue) includeUnmonitored = Convert.ToBoolean(queryIncludeUnmonitored.Value);
|
||||
|
||||
var resources = MapToResource(_episodeService.EpisodesBetweenDates(start, end, includeUnmonitored), true, true);
|
||||
var resources = _moviesService.GetMoviesBetweenDates(start, end, includeUnmonitored).Select(MapToResource);
|
||||
|
||||
return resources.OrderBy(e => e.AirDateUtc).ToList();
|
||||
return resources.OrderBy(e => e.InCinemas).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,13 @@ namespace NzbDrone.Api.Config
|
||||
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
||||
|
||||
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
|
||||
SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
|
||||
/*SharedValidator.RuleFor(c => c.StandardEpisodeFormat).ValidEpisodeFormat();
|
||||
SharedValidator.RuleFor(c => c.DailyEpisodeFormat).ValidDailyEpisodeFormat();
|
||||
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
||||
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
|
||||
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();
|
||||
SharedValidator.RuleFor(c => c.SeasonFolderFormat).ValidSeasonFolderFormat();*/
|
||||
SharedValidator.RuleFor(c => c.StandardMovieFormat).ValidMovieFormat();
|
||||
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
|
||||
}
|
||||
|
||||
private void UpdateNamingConfig(NamingConfigResource resource)
|
||||
@@ -54,7 +56,13 @@ namespace NzbDrone.Api.Config
|
||||
var nameSpec = _namingConfigService.GetConfig();
|
||||
var resource = nameSpec.ToResource();
|
||||
|
||||
if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
|
||||
//if (resource.StandardEpisodeFormat.IsNotNullOrWhiteSpace())
|
||||
//{
|
||||
// var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
|
||||
// basicConfig.AddToResource(resource);
|
||||
//}
|
||||
|
||||
if (resource.StandardMovieFormat.IsNotNullOrWhiteSpace())
|
||||
{
|
||||
var basicConfig = _filenameBuilder.GetBasicNamingConfig(nameSpec);
|
||||
basicConfig.AddToResource(resource);
|
||||
@@ -73,39 +81,50 @@ namespace NzbDrone.Api.Config
|
||||
var nameSpec = config.ToModel();
|
||||
var sampleResource = new NamingSampleResource();
|
||||
|
||||
var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
|
||||
var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
|
||||
var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
|
||||
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||
//var singleEpisodeSampleResult = _filenameSampleService.GetStandardSample(nameSpec);
|
||||
//var multiEpisodeSampleResult = _filenameSampleService.GetMultiEpisodeSample(nameSpec);
|
||||
//var dailyEpisodeSampleResult = _filenameSampleService.GetDailySample(nameSpec);
|
||||
//var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||
//var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||
|
||||
sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
|
||||
? "Invalid format"
|
||||
: singleEpisodeSampleResult.FileName;
|
||||
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
||||
|
||||
|
||||
sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
|
||||
? "Invalid format"
|
||||
: multiEpisodeSampleResult.FileName;
|
||||
//sampleResource.SingleEpisodeExample = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult) != null
|
||||
// ? "Invalid format"
|
||||
// : singleEpisodeSampleResult.FileName;
|
||||
|
||||
sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
|
||||
? "Invalid format"
|
||||
: dailyEpisodeSampleResult.FileName;
|
||||
//sampleResource.MultiEpisodeExample = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult) != null
|
||||
// ? "Invalid format"
|
||||
// : multiEpisodeSampleResult.FileName;
|
||||
|
||||
sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
|
||||
? "Invalid format"
|
||||
: animeEpisodeSampleResult.FileName;
|
||||
//sampleResource.DailyEpisodeExample = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult) != null
|
||||
// ? "Invalid format"
|
||||
// : dailyEpisodeSampleResult.FileName;
|
||||
|
||||
sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
|
||||
? "Invalid format"
|
||||
: animeMultiEpisodeSampleResult.FileName;
|
||||
//sampleResource.AnimeEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult) != null
|
||||
// ? "Invalid format"
|
||||
// : animeEpisodeSampleResult.FileName;
|
||||
|
||||
sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
|
||||
//sampleResource.AnimeMultiEpisodeExample = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult) != null
|
||||
// ? "Invalid format"
|
||||
// : animeMultiEpisodeSampleResult.FileName;
|
||||
|
||||
sampleResource.MovieExample = nameSpec.StandardMovieFormat.IsNullOrWhiteSpace()
|
||||
? "Invalid Format"
|
||||
: movieSampleResult.FileName;
|
||||
|
||||
//sampleResource.SeriesFolderExample = nameSpec.SeriesFolderFormat.IsNullOrWhiteSpace()
|
||||
// ? "Invalid format"
|
||||
// : _filenameSampleService.GetSeriesFolderSample(nameSpec);
|
||||
|
||||
//sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
|
||||
// ? "Invalid format"
|
||||
// : _filenameSampleService.GetSeasonFolderSample(nameSpec);
|
||||
|
||||
sampleResource.MovieFolderExample = nameSpec.MovieFolderFormat.IsNullOrWhiteSpace()
|
||||
? "Invalid format"
|
||||
: _filenameSampleService.GetSeriesFolderSample(nameSpec);
|
||||
|
||||
sampleResource.SeasonFolderExample = nameSpec.SeasonFolderFormat.IsNullOrWhiteSpace()
|
||||
? "Invalid format"
|
||||
: _filenameSampleService.GetSeasonFolderSample(nameSpec);
|
||||
: _filenameSampleService.GetMovieFolderSample(nameSpec);
|
||||
|
||||
return sampleResource.AsResponse();
|
||||
}
|
||||
@@ -118,19 +137,25 @@ namespace NzbDrone.Api.Config
|
||||
var animeEpisodeSampleResult = _filenameSampleService.GetAnimeSample(nameSpec);
|
||||
var animeMultiEpisodeSampleResult = _filenameSampleService.GetAnimeMultiEpisodeSample(nameSpec);
|
||||
|
||||
var movieSampleResult = _filenameSampleService.GetMovieSample(nameSpec);
|
||||
|
||||
var singleEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(singleEpisodeSampleResult);
|
||||
var multiEpisodeValidationResult = _filenameValidationService.ValidateStandardFilename(multiEpisodeSampleResult);
|
||||
var dailyEpisodeValidationResult = _filenameValidationService.ValidateDailyFilename(dailyEpisodeSampleResult);
|
||||
var animeEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeEpisodeSampleResult);
|
||||
var animeMultiEpisodeValidationResult = _filenameValidationService.ValidateAnimeFilename(animeMultiEpisodeSampleResult);
|
||||
|
||||
//var standardMovieValidationResult = _filenameValidationService.ValidateMovieFilename(movieSampleResult); For now, let's hope the user is not stupid enough :/
|
||||
|
||||
var validationFailures = new List<ValidationFailure>();
|
||||
|
||||
validationFailures.AddIfNotNull(singleEpisodeValidationResult);
|
||||
validationFailures.AddIfNotNull(multiEpisodeValidationResult);
|
||||
validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
|
||||
validationFailures.AddIfNotNull(animeEpisodeValidationResult);
|
||||
validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
|
||||
//validationFailures.AddIfNotNull(singleEpisodeValidationResult);
|
||||
//validationFailures.AddIfNotNull(multiEpisodeValidationResult);
|
||||
//validationFailures.AddIfNotNull(dailyEpisodeValidationResult);
|
||||
//validationFailures.AddIfNotNull(animeEpisodeValidationResult);
|
||||
//validationFailures.AddIfNotNull(animeMultiEpisodeValidationResult);
|
||||
|
||||
//validationFailures.AddIfNotNull(standardMovieValidationResult);
|
||||
|
||||
if (validationFailures.Any())
|
||||
{
|
||||
|
||||
@@ -7,6 +7,8 @@ namespace NzbDrone.Api.Config
|
||||
{
|
||||
public bool RenameEpisodes { get; set; }
|
||||
public bool ReplaceIllegalCharacters { get; set; }
|
||||
public string StandardMovieFormat { get; set; }
|
||||
public string MovieFolderFormat { get; set; }
|
||||
public int MultiEpisodeStyle { get; set; }
|
||||
public string StandardEpisodeFormat { get; set; }
|
||||
public string DailyEpisodeFormat { get; set; }
|
||||
@@ -36,7 +38,9 @@ namespace NzbDrone.Api.Config
|
||||
DailyEpisodeFormat = model.DailyEpisodeFormat,
|
||||
AnimeEpisodeFormat = model.AnimeEpisodeFormat,
|
||||
SeriesFolderFormat = model.SeriesFolderFormat,
|
||||
SeasonFolderFormat = model.SeasonFolderFormat
|
||||
SeasonFolderFormat = model.SeasonFolderFormat,
|
||||
StandardMovieFormat = model.StandardMovieFormat,
|
||||
MovieFolderFormat = model.MovieFolderFormat
|
||||
//IncludeSeriesTitle
|
||||
//IncludeEpisodeTitle
|
||||
//IncludeQuality
|
||||
@@ -64,12 +68,14 @@ namespace NzbDrone.Api.Config
|
||||
|
||||
RenameEpisodes = resource.RenameEpisodes,
|
||||
ReplaceIllegalCharacters = resource.ReplaceIllegalCharacters,
|
||||
MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
||||
StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
||||
DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
||||
AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
||||
SeriesFolderFormat = resource.SeriesFolderFormat,
|
||||
SeasonFolderFormat = resource.SeasonFolderFormat
|
||||
//MultiEpisodeStyle = resource.MultiEpisodeStyle,
|
||||
//StandardEpisodeFormat = resource.StandardEpisodeFormat,
|
||||
//DailyEpisodeFormat = resource.DailyEpisodeFormat,
|
||||
//AnimeEpisodeFormat = resource.AnimeEpisodeFormat,
|
||||
//SeriesFolderFormat = resource.SeriesFolderFormat,
|
||||
//SeasonFolderFormat = resource.SeasonFolderFormat,
|
||||
StandardMovieFormat = resource.StandardMovieFormat,
|
||||
MovieFolderFormat = resource.MovieFolderFormat
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,5 +9,8 @@
|
||||
public string AnimeMultiEpisodeExample { get; set; }
|
||||
public string SeriesFolderExample { get; set; }
|
||||
public string SeasonFolderExample { get; set; }
|
||||
|
||||
public string MovieExample { get; set; }
|
||||
public string MovieFolderExample { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Api.Frontend.Mappers
|
||||
|
||||
public override bool CanHandle(string resourceUrl)
|
||||
{
|
||||
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("nzbdrone_backup_") && resourceUrl.EndsWith(".zip");
|
||||
return resourceUrl.StartsWith("/backup/") && resourceUrl.ContainsIgnoreCase("radarr_backup_") && resourceUrl.EndsWith(".zip");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using Nancy;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Download;
|
||||
@@ -34,12 +35,18 @@ namespace NzbDrone.Api.History
|
||||
|
||||
resource.Series = model.Series.ToResource();
|
||||
resource.Episode = model.Episode.ToResource();
|
||||
resource.Movie = model.Movie.ToResource();
|
||||
|
||||
if (model.Series != null)
|
||||
{
|
||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
|
||||
}
|
||||
|
||||
if (model.Movie != null)
|
||||
{
|
||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Movie.Profile.Value, model.Quality);
|
||||
}
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
@@ -47,6 +54,8 @@ namespace NzbDrone.Api.History
|
||||
{
|
||||
var episodeId = Request.Query.EpisodeId;
|
||||
|
||||
var movieId = Request.Query.MovieId;
|
||||
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, Core.History.History>("date", SortDirection.Descending);
|
||||
|
||||
if (pagingResource.FilterKey == "eventType")
|
||||
@@ -61,6 +70,12 @@ namespace NzbDrone.Api.History
|
||||
pagingSpec.FilterExpression = h => h.EpisodeId == i;
|
||||
}
|
||||
|
||||
if (movieId.HasValue)
|
||||
{
|
||||
int i = (int)movieId;
|
||||
pagingSpec.FilterExpression = h => h.MovieId == i;
|
||||
}
|
||||
|
||||
return ApplyToPage(_historyService.Paged, pagingSpec, MapToResource);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
@@ -12,6 +13,7 @@ namespace NzbDrone.Api.History
|
||||
public class HistoryResource : RestResource
|
||||
{
|
||||
public int EpisodeId { get; set; }
|
||||
public int MovieId { get; set; }
|
||||
public int SeriesId { get; set; }
|
||||
public string SourceTitle { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
@@ -22,7 +24,7 @@ namespace NzbDrone.Api.History
|
||||
public HistoryEventType EventType { get; set; }
|
||||
|
||||
public Dictionary<string, string> Data { get; set; }
|
||||
|
||||
public MovieResource Movie { get; set; }
|
||||
public EpisodeResource Episode { get; set; }
|
||||
public SeriesResource Series { get; set; }
|
||||
}
|
||||
@@ -39,6 +41,7 @@ namespace NzbDrone.Api.History
|
||||
|
||||
EpisodeId = model.EpisodeId,
|
||||
SeriesId = model.SeriesId,
|
||||
MovieId = model.MovieId,
|
||||
SourceTitle = model.SourceTitle,
|
||||
Quality = model.Quality,
|
||||
//QualityCutoffNotMet
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace NzbDrone.Api.Indexers
|
||||
private readonly Logger _logger;
|
||||
|
||||
private readonly ICached<RemoteEpisode> _remoteEpisodeCache;
|
||||
private readonly ICached<RemoteMovie> _remoteMovieCache;
|
||||
|
||||
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
||||
ISearchForNzb nzbSearchService,
|
||||
@@ -49,6 +50,7 @@ namespace NzbDrone.Api.Indexers
|
||||
PostValidator.RuleFor(s => s.Guid).NotEmpty();
|
||||
|
||||
_remoteEpisodeCache = cacheManager.GetCache<RemoteEpisode>(GetType(), "remoteEpisodes");
|
||||
_remoteMovieCache = cacheManager.GetCache<RemoteMovie>(GetType(), "remoteMovies");
|
||||
}
|
||||
|
||||
private Response DownloadRelease(ReleaseResource release)
|
||||
@@ -59,7 +61,26 @@ namespace NzbDrone.Api.Indexers
|
||||
{
|
||||
_logger.Debug("Couldn't find requested release in cache, cache timeout probably expired.");
|
||||
|
||||
return new NotFoundResponse();
|
||||
var remoteMovie = _remoteMovieCache.Find(release.Guid);
|
||||
|
||||
if (remoteMovie == null)
|
||||
{
|
||||
return new NotFoundResponse();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_downloadService.DownloadReport(remoteMovie);
|
||||
}
|
||||
catch (ReleaseDownloadException ex)
|
||||
{
|
||||
_logger.Error(ex, ex.Message);
|
||||
throw new NzbDroneClientException(HttpStatusCode.Conflict, "Getting release from indexer failed");
|
||||
}
|
||||
|
||||
return release.AsResponse();
|
||||
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
@@ -82,6 +103,11 @@ namespace NzbDrone.Api.Indexers
|
||||
return GetEpisodeReleases(Request.Query.episodeId);
|
||||
}
|
||||
|
||||
if (Request.Query.movieId != null)
|
||||
{
|
||||
return GetMovieReleases(Request.Query.movieId);
|
||||
}
|
||||
|
||||
return GetRss();
|
||||
}
|
||||
|
||||
@@ -102,6 +128,27 @@ namespace NzbDrone.Api.Indexers
|
||||
return new List<ReleaseResource>();
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetMovieReleases(int movieId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var decisions = _nzbSearchService.MovieSearch(movieId, true);
|
||||
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisionsForMovies(decisions);
|
||||
|
||||
return MapDecisions(prioritizedDecisions);
|
||||
}
|
||||
catch (NotImplementedException ex)
|
||||
{
|
||||
_logger.Error(ex, "One or more indexer you selected does not support movie search yet: " + ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error(ex, "Movie search failed: " + ex.Message);
|
||||
}
|
||||
|
||||
return new List<ReleaseResource>();
|
||||
}
|
||||
|
||||
private List<ReleaseResource> GetRss()
|
||||
{
|
||||
var reports = _rssFetcherAndParser.Fetch();
|
||||
@@ -113,7 +160,15 @@ namespace NzbDrone.Api.Indexers
|
||||
|
||||
protected override ReleaseResource MapDecision(DownloadDecision decision, int initialWeight)
|
||||
{
|
||||
_remoteEpisodeCache.Set(decision.RemoteEpisode.Release.Guid, decision.RemoteEpisode, TimeSpan.FromMinutes(30));
|
||||
if (decision.IsForMovie)
|
||||
{
|
||||
_remoteMovieCache.Set(decision.RemoteMovie.Release.Guid, decision.RemoteMovie, TimeSpan.FromMinutes(30));
|
||||
}
|
||||
else
|
||||
{
|
||||
_remoteEpisodeCache.Set(decision.RemoteEpisode.Release.Guid, decision.RemoteEpisode, TimeSpan.FromMinutes(30));
|
||||
}
|
||||
|
||||
return base.MapDecision(decision, initialWeight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace NzbDrone.Api.Indexers
|
||||
public string Indexer { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
public string ReleaseHash { get; set; }
|
||||
public string Edition { get; set; }
|
||||
public string Title { get; set; }
|
||||
public bool FullSeason { get; set; }
|
||||
public int SeasonNumber { get; set; }
|
||||
@@ -86,6 +87,60 @@ namespace NzbDrone.Api.Indexers
|
||||
var parsedEpisodeInfo = model.RemoteEpisode.ParsedEpisodeInfo;
|
||||
var remoteEpisode = model.RemoteEpisode;
|
||||
var torrentInfo = (model.RemoteEpisode.Release as TorrentInfo) ?? new TorrentInfo();
|
||||
var downloadAllowed = model.RemoteEpisode.DownloadAllowed;
|
||||
if (model.IsForMovie)
|
||||
{
|
||||
downloadAllowed = model.RemoteMovie.DownloadAllowed;
|
||||
var parsedMovieInfo = model.RemoteMovie.ParsedMovieInfo;
|
||||
|
||||
return new ReleaseResource
|
||||
{
|
||||
Guid = releaseInfo.Guid,
|
||||
Quality = parsedMovieInfo.Quality,
|
||||
QualityWeight = parsedMovieInfo.Quality.Quality.Id, //Id kinda hacky for wheight, but what you gonna do? TODO: Fix this shit!
|
||||
Age = releaseInfo.Age,
|
||||
AgeHours = releaseInfo.AgeHours,
|
||||
AgeMinutes = releaseInfo.AgeMinutes,
|
||||
Size = releaseInfo.Size,
|
||||
IndexerId = releaseInfo.IndexerId,
|
||||
Indexer = releaseInfo.Indexer,
|
||||
ReleaseGroup = parsedMovieInfo.ReleaseGroup,
|
||||
ReleaseHash = parsedMovieInfo.ReleaseHash,
|
||||
Title = releaseInfo.Title,
|
||||
//FullSeason = parsedMovieInfo.FullSeason,
|
||||
//SeasonNumber = parsedMovieInfo.SeasonNumber,
|
||||
Language = parsedMovieInfo.Language,
|
||||
AirDate = "",
|
||||
SeriesTitle = parsedMovieInfo.MovieTitle,
|
||||
EpisodeNumbers = new int[0],
|
||||
AbsoluteEpisodeNumbers = new int[0],
|
||||
Approved = model.Approved,
|
||||
TemporarilyRejected = model.TemporarilyRejected,
|
||||
Rejected = model.Rejected,
|
||||
TvdbId = releaseInfo.TvdbId,
|
||||
TvRageId = releaseInfo.TvRageId,
|
||||
Rejections = model.Rejections.Select(r => r.Reason).ToList(),
|
||||
PublishDate = releaseInfo.PublishDate,
|
||||
CommentUrl = releaseInfo.CommentUrl,
|
||||
DownloadUrl = releaseInfo.DownloadUrl,
|
||||
InfoUrl = releaseInfo.InfoUrl,
|
||||
DownloadAllowed = downloadAllowed,
|
||||
//ReleaseWeight
|
||||
|
||||
MagnetUrl = torrentInfo.MagnetUrl,
|
||||
InfoHash = torrentInfo.InfoHash,
|
||||
Seeders = torrentInfo.Seeders,
|
||||
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
||||
Protocol = releaseInfo.DownloadProtocol,
|
||||
|
||||
Edition = parsedMovieInfo.Edition,
|
||||
|
||||
IsDaily = false,
|
||||
IsAbsoluteNumbering = false,
|
||||
IsPossibleSpecialEpisode = false,
|
||||
//Special = parsedMovieInfo.Special,
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: Clean this mess up. don't mix data from multiple classes, use sub-resources instead? (Got a huge Deja Vu, didn't we talk about this already once?)
|
||||
return new ReleaseResource
|
||||
@@ -119,7 +174,7 @@ namespace NzbDrone.Api.Indexers
|
||||
CommentUrl = releaseInfo.CommentUrl,
|
||||
DownloadUrl = releaseInfo.DownloadUrl,
|
||||
InfoUrl = releaseInfo.InfoUrl,
|
||||
DownloadAllowed = remoteEpisode.DownloadAllowed,
|
||||
DownloadAllowed = downloadAllowed,
|
||||
//ReleaseWeight
|
||||
|
||||
MagnetUrl = torrentInfo.MagnetUrl,
|
||||
|
||||
31
src/NzbDrone.Api/Movies/MovieEditorModule.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
public class MovieEditorModule : NzbDroneApiModule
|
||||
{
|
||||
private readonly IMovieService _movieService;
|
||||
|
||||
public MovieEditorModule(IMovieService movieService)
|
||||
: base("/movie/editor")
|
||||
{
|
||||
_movieService = movieService;
|
||||
Put["/"] = Movie => SaveAll();
|
||||
}
|
||||
|
||||
private Response SaveAll()
|
||||
{
|
||||
var resources = Request.Body.FromJson<List<MovieResource>>();
|
||||
|
||||
var Movie = resources.Select(MovieResource => MovieResource.ToModel(_movieService.GetMovie(MovieResource.Id))).ToList();
|
||||
|
||||
return _movieService.UpdateMovie(Movie)
|
||||
.ToResource()
|
||||
.AsResponse(HttpStatusCode.Accepted);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
src/NzbDrone.Api/Movies/MovieFileModule.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using NLog;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.EpisodeFiles
|
||||
{
|
||||
public class MovieFileModule : NzbDroneRestModuleWithSignalR<MovieFileResource, MovieFile>
|
||||
//IHandle<EpisodeFileAddedEvent>
|
||||
{
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||
private readonly IMovieService _seriesService;
|
||||
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public MovieFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMediaFileService mediaFileService,
|
||||
IRecycleBinProvider recycleBinProvider,
|
||||
IMovieService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
Logger logger)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_mediaFileService = mediaFileService;
|
||||
_recycleBinProvider = recycleBinProvider;
|
||||
_seriesService = seriesService;
|
||||
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||
_logger = logger;
|
||||
/*GetResourceById = GetEpisodeFile;
|
||||
GetResourceAll = GetEpisodeFiles;
|
||||
UpdateResource = SetQuality;*/
|
||||
DeleteResource = DeleteEpisodeFile;
|
||||
}
|
||||
|
||||
/*private EpisodeFileResource GetEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(id);
|
||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||
|
||||
return episodeFile.ToResource(series, _qualityUpgradableSpecification);
|
||||
}
|
||||
|
||||
private List<EpisodeFileResource> GetEpisodeFiles()
|
||||
{
|
||||
if (!Request.Query.SeriesId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("seriesId is missing");
|
||||
}
|
||||
|
||||
var seriesId = (int)Request.Query.SeriesId;
|
||||
|
||||
var series = _seriesService.GetSeries(seriesId);
|
||||
|
||||
return _mediaFileService.GetFilesBySeries(seriesId).ConvertAll(f => f.ToResource(series, _qualityUpgradableSpecification));
|
||||
}
|
||||
|
||||
private void SetQuality(EpisodeFileResource episodeFileResource)
|
||||
{
|
||||
var episodeFile = _mediaFileService.Get(episodeFileResource.Id);
|
||||
episodeFile.Quality = episodeFileResource.Quality;
|
||||
_mediaFileService.Update(episodeFile);
|
||||
}*/
|
||||
|
||||
private void DeleteEpisodeFile(int id)
|
||||
{
|
||||
var episodeFile = _mediaFileService.GetMovie(id);
|
||||
var series = _seriesService.GetMovie(episodeFile.MovieId);
|
||||
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||
|
||||
_logger.Info("Deleting episode file: {0}", fullPath);
|
||||
_recycleBinProvider.DeleteFile(fullPath);
|
||||
_mediaFileService.Delete(episodeFile, DeleteMediaFileReason.Manual);
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileAddedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
11
src/NzbDrone.Api/Movies/MovieModule.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Api.Movies
|
||||
{
|
||||
class MovieModule
|
||||
{
|
||||
}
|
||||
}
|
||||
35
src/NzbDrone.Api/Movies/RenameMovieModule.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace NzbDrone.Api.Movies
|
||||
{
|
||||
public class RenameMovieModule : NzbDroneRestModule<RenameMovieResource>
|
||||
{
|
||||
private readonly IRenameMovieFileService _renameMovieFileService;
|
||||
|
||||
public RenameMovieModule(IRenameMovieFileService renameMovieFileService)
|
||||
: base("renameMovie")
|
||||
{
|
||||
_renameMovieFileService = renameMovieFileService;
|
||||
|
||||
GetResourceAll = GetMovies; //TODO: GetResourceSingle?
|
||||
}
|
||||
|
||||
private List<RenameMovieResource> GetMovies()
|
||||
{
|
||||
if(!Request.Query.MovieId.HasValue)
|
||||
{
|
||||
throw new BadRequestException("movieId is missing");
|
||||
}
|
||||
|
||||
var movieId = (int)Request.Query.MovieId;
|
||||
|
||||
return _renameMovieFileService.GetRenamePreviews(movieId).ToResource();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
35
src/NzbDrone.Api/Movies/RenameMovieResource.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using NzbDrone.Api.REST;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Movies
|
||||
{
|
||||
public class RenameMovieResource : RestResource
|
||||
{
|
||||
public int MovieId { get; set; }
|
||||
public int MovieFileId { get; set; }
|
||||
public string ExistingPath { get; set; }
|
||||
public string NewPath { get; set; }
|
||||
}
|
||||
|
||||
public static class RenameMovieResourceMapper
|
||||
{
|
||||
public static RenameMovieResource ToResource(this Core.MediaFiles.RenameMovieFilePreview model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
return new RenameMovieResource
|
||||
{
|
||||
MovieId = model.MovieId,
|
||||
MovieFileId = model.MovieFileId,
|
||||
ExistingPath = model.ExistingPath,
|
||||
NewPath = model.NewPath
|
||||
};
|
||||
}
|
||||
|
||||
public static List<RenameMovieResource> ToResource(this IEnumerable<Core.MediaFiles.RenameMovieFilePreview> models)
|
||||
{
|
||||
return models.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,6 +116,11 @@
|
||||
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
||||
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||
<Compile Include="Movies\MovieFileModule.cs" />
|
||||
<Compile Include="Movies\MovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||
<Compile Include="Movies\MovieEditorModule.cs" />
|
||||
<Compile Include="Parse\ParseModule.cs" />
|
||||
<Compile Include="Parse\ParseResource.cs" />
|
||||
<Compile Include="ManualImport\ManualImportModule.cs" />
|
||||
@@ -228,11 +233,15 @@
|
||||
<Compile Include="RootFolders\RootFolderResource.cs" />
|
||||
<Compile Include="SeasonPass\SeasonPassResource.cs" />
|
||||
<Compile Include="Series\AlternateTitleResource.cs" />
|
||||
<Compile Include="Series\MovieFileResource.cs" />
|
||||
<Compile Include="Series\SeasonResource.cs" />
|
||||
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
||||
<Compile Include="Series\SeriesEditorModule.cs" />
|
||||
<Compile Include="Series\MovieLookupModule.cs" />
|
||||
<Compile Include="Series\SeriesLookupModule.cs" />
|
||||
<Compile Include="Series\MovieModule.cs" />
|
||||
<Compile Include="Series\SeriesModule.cs" />
|
||||
<Compile Include="Series\MovieResource.cs" />
|
||||
<Compile Include="Series\SeriesResource.cs" />
|
||||
<Compile Include="Series\SeasonStatisticsResource.cs" />
|
||||
<Compile Include="System\Backup\BackupModule.cs" />
|
||||
@@ -251,6 +260,7 @@
|
||||
<Compile Include="Wanted\CutoffModule.cs" />
|
||||
<Compile Include="Wanted\LegacyMissingModule.cs" />
|
||||
<Compile Include="Wanted\MissingModule.cs" />
|
||||
<Compile Include="Wanted\MovieMissingModule.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="app.config" />
|
||||
@@ -285,4 +295,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -6,6 +6,5 @@ using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: Guid("4c0922d7-979e-4ff7-b44b-b8ac2100eeb5")]
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
|
||||
[assembly: InternalsVisibleTo("NzbDrone.Core")]
|
||||
|
||||
@@ -4,6 +4,7 @@ using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Core.Download.TrackedDownloads;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using System.Linq;
|
||||
@@ -14,6 +15,7 @@ namespace NzbDrone.Api.Queue
|
||||
{
|
||||
public SeriesResource Series { get; set; }
|
||||
public EpisodeResource Episode { get; set; }
|
||||
public MovieResource Movie { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public decimal Size { get; set; }
|
||||
public string Title { get; set; }
|
||||
@@ -49,7 +51,8 @@ namespace NzbDrone.Api.Queue
|
||||
TrackedDownloadStatus = model.TrackedDownloadStatus,
|
||||
StatusMessages = model.StatusMessages,
|
||||
DownloadId = model.DownloadId,
|
||||
Protocol = model.Protocol
|
||||
Protocol = model.Protocol,
|
||||
Movie = model.Movie.ToResource()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
86
src/NzbDrone.Api/Series/MovieFileResource.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
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;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
public class MovieFileResource : RestResource
|
||||
{
|
||||
public MovieFileResource()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//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 string RelativePath { get; set; }
|
||||
public string Path { get; set; }
|
||||
public long Size { get; set; }
|
||||
public DateTime DateAdded { get; set; }
|
||||
public string SceneName { get; set; }
|
||||
public string ReleaseGroup { get; set; }
|
||||
public QualityModel Quality { get; set; }
|
||||
public MovieResource Movie { get; set; }
|
||||
public string Edition { get; set; }
|
||||
public Core.MediaFiles.MediaInfo.MediaInfoModel MediaInfo { get; set; }
|
||||
|
||||
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||
}
|
||||
|
||||
public static class MovieFileResourceMapper
|
||||
{
|
||||
public static MovieFileResource ToResource(this MovieFile model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
MovieResource movie = null;
|
||||
|
||||
if (model.Movie != null)
|
||||
{
|
||||
model.Movie.LazyLoad();
|
||||
if (model.Movie.Value != null)
|
||||
{
|
||||
//movie = model.Movie.Value.ToResource();
|
||||
}
|
||||
}
|
||||
|
||||
return new MovieFileResource
|
||||
{
|
||||
Id = model.Id,
|
||||
RelativePath = model.RelativePath,
|
||||
Path = model.Path,
|
||||
Size = model.Size,
|
||||
DateAdded = model.DateAdded,
|
||||
ReleaseGroup = model.ReleaseGroup,
|
||||
Quality = model.Quality,
|
||||
Movie = movie,
|
||||
MediaInfo = model.MediaInfo,
|
||||
Edition = model.Edition
|
||||
};
|
||||
}
|
||||
|
||||
public static MovieFile ToModel(this MovieFileResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new MovieFile
|
||||
{
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
public static List<MovieFileResource> ToResource(this IEnumerable<MovieFile> movies)
|
||||
{
|
||||
return movies.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/NzbDrone.Api/Series/MovieLookupModule.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
using Nancy;
|
||||
using NzbDrone.Api.Extensions;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MetadataSource;
|
||||
using System.Linq;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
public class MovieLookupModule : NzbDroneRestModule<MovieResource>
|
||||
{
|
||||
private readonly ISearchForNewMovie _searchProxy;
|
||||
|
||||
public MovieLookupModule(ISearchForNewMovie searchProxy)
|
||||
: base("/movies/lookup")
|
||||
{
|
||||
_searchProxy = searchProxy;
|
||||
Get["/"] = x => Search();
|
||||
}
|
||||
|
||||
|
||||
private Response Search()
|
||||
{
|
||||
var imdbResults = _searchProxy.SearchForNewMovie((string)Request.Query.term);
|
||||
return MapToResource(imdbResults).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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
247
src/NzbDrone.Api/Series/MovieModule.cs
Normal file
@@ -0,0 +1,247 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using FluentValidation;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.MovieStats;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
using NzbDrone.Core.Validation.Paths;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Validation;
|
||||
using NzbDrone.SignalR;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
public class MovieModule : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||
IHandle<EpisodeImportedEvent>,
|
||||
IHandle<EpisodeFileDeletedEvent>,
|
||||
IHandle<MovieUpdatedEvent>,
|
||||
IHandle<MovieEditedEvent>,
|
||||
IHandle<MovieDeletedEvent>,
|
||||
IHandle<MovieRenamedEvent>,
|
||||
IHandle<MediaCoversUpdatedEvent>
|
||||
|
||||
{
|
||||
protected readonly IMovieService _moviesService;
|
||||
private readonly IMovieStatisticsService _moviesStatisticsService;
|
||||
private readonly IMapCoversToLocal _coverMapper;
|
||||
|
||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
RootFolderValidator rootFolderValidator,
|
||||
MoviePathValidator moviesPathValidator,
|
||||
MovieExistsValidator moviesExistsValidator,
|
||||
DroneFactoryValidator droneFactoryValidator,
|
||||
MovieAncestorValidator moviesAncestorValidator,
|
||||
ProfileExistsValidator profileExistsValidator
|
||||
)
|
||||
: base(signalRBroadcaster)
|
||||
{
|
||||
_moviesService = moviesService;
|
||||
_moviesStatisticsService = moviesStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
|
||||
GetResourceAll = AllMovie;
|
||||
GetResourceById = GetMovie;
|
||||
CreateResource = AddMovie;
|
||||
UpdateResource = UpdateMovie;
|
||||
DeleteResource = DeleteMovie;
|
||||
|
||||
Validation.RuleBuilderExtensions.ValidId(SharedValidator.RuleFor(s => s.ProfileId));
|
||||
|
||||
SharedValidator.RuleFor(s => s.Path)
|
||||
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||
.IsValidPath()
|
||||
.SetValidator(rootFolderValidator)
|
||||
.SetValidator(moviesPathValidator)
|
||||
.SetValidator(droneFactoryValidator)
|
||||
.SetValidator(moviesAncestorValidator)
|
||||
.When(s => !s.Path.IsNullOrWhiteSpace());
|
||||
|
||||
SharedValidator.RuleFor(s => s.ProfileId).SetValidator(profileExistsValidator);
|
||||
|
||||
PostValidator.RuleFor(s => s.Path).IsValidPath().When(s => s.RootFolderPath.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.RootFolderPath).IsValidPath().When(s => s.Path.IsNullOrWhiteSpace());
|
||||
PostValidator.RuleFor(s => s.Title).NotEmpty();
|
||||
PostValidator.RuleFor(s => s.TmdbId).NotNull().NotEmpty().SetValidator(moviesExistsValidator);
|
||||
|
||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
||||
}
|
||||
|
||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||
IMovieService moviesService,
|
||||
IMovieStatisticsService moviesStatisticsService,
|
||||
ISceneMappingService sceneMappingService,
|
||||
IMapCoversToLocal coverMapper,
|
||||
string resource)
|
||||
: base(signalRBroadcaster, resource)
|
||||
{
|
||||
_moviesService = moviesService;
|
||||
_moviesStatisticsService = moviesStatisticsService;
|
||||
|
||||
_coverMapper = coverMapper;
|
||||
|
||||
GetResourceAll = AllMovie;
|
||||
GetResourceById = GetMovie;
|
||||
CreateResource = AddMovie;
|
||||
UpdateResource = UpdateMovie;
|
||||
DeleteResource = DeleteMovie;
|
||||
}
|
||||
|
||||
private MovieResource GetMovie(int id)
|
||||
{
|
||||
var movies = _moviesService.GetMovie(id);
|
||||
return MapToResource(movies);
|
||||
}
|
||||
|
||||
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
||||
{
|
||||
if (movies == null) return null;
|
||||
|
||||
var resource = movies.ToResource();
|
||||
MapCoversToLocal(resource);
|
||||
FetchAndLinkMovieStatistics(resource);
|
||||
PopulateAlternateTitles(resource);
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
private List<MovieResource> AllMovie()
|
||||
{
|
||||
var moviesStats = _moviesStatisticsService.MovieStatistics();
|
||||
var moviesResources = _moviesService.GetAllMovies().ToResource();
|
||||
|
||||
MapCoversToLocal(moviesResources.ToArray());
|
||||
LinkMovieStatistics(moviesResources, moviesStats);
|
||||
PopulateAlternateTitles(moviesResources);
|
||||
|
||||
return moviesResources;
|
||||
}
|
||||
|
||||
private int AddMovie(MovieResource moviesResource)
|
||||
{
|
||||
var model = moviesResource.ToModel();
|
||||
|
||||
return _moviesService.AddMovie(model).Id;
|
||||
}
|
||||
|
||||
private void UpdateMovie(MovieResource moviesResource)
|
||||
{
|
||||
var model = moviesResource.ToModel(_moviesService.GetMovie(moviesResource.Id));
|
||||
|
||||
_moviesService.UpdateMovie(model);
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, moviesResource);
|
||||
}
|
||||
|
||||
private void DeleteMovie(int id)
|
||||
{
|
||||
var deleteFiles = false;
|
||||
var deleteFilesQuery = Request.Query.deleteFiles;
|
||||
|
||||
if (deleteFilesQuery.HasValue)
|
||||
{
|
||||
deleteFiles = Convert.ToBoolean(deleteFilesQuery.Value);
|
||||
}
|
||||
|
||||
_moviesService.DeleteMovie(id, deleteFiles);
|
||||
}
|
||||
|
||||
private void MapCoversToLocal(params MovieResource[] movies)
|
||||
{
|
||||
foreach (var moviesResource in movies)
|
||||
{
|
||||
_coverMapper.ConvertToLocalUrls(moviesResource.Id, moviesResource.Images);
|
||||
}
|
||||
}
|
||||
|
||||
private void FetchAndLinkMovieStatistics(MovieResource resource)
|
||||
{
|
||||
LinkMovieStatistics(resource, _moviesStatisticsService.MovieStatistics(resource.Id));
|
||||
}
|
||||
|
||||
private void LinkMovieStatistics(List<MovieResource> resources, List<MovieStatistics> moviesStatistics)
|
||||
{
|
||||
var dictMovieStats = moviesStatistics.ToDictionary(v => v.MovieId);
|
||||
|
||||
foreach (var movies in resources)
|
||||
{
|
||||
var stats = dictMovieStats.GetValueOrDefault(movies.Id);
|
||||
if (stats == null) continue;
|
||||
|
||||
LinkMovieStatistics(movies, stats);
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
|
||||
{
|
||||
resource.SizeOnDisk = moviesStatistics.SizeOnDisk;
|
||||
}
|
||||
|
||||
private void PopulateAlternateTitles(List<MovieResource> resources)
|
||||
{
|
||||
foreach (var resource in resources)
|
||||
{
|
||||
PopulateAlternateTitles(resource);
|
||||
}
|
||||
}
|
||||
|
||||
private void PopulateAlternateTitles(MovieResource resource)
|
||||
{
|
||||
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
||||
|
||||
//if (mappings == null) return;
|
||||
|
||||
//Not necessary anymore
|
||||
|
||||
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||
}
|
||||
|
||||
public void Handle(EpisodeImportedEvent message)
|
||||
{
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.ImportedEpisode.MovieId);
|
||||
}
|
||||
|
||||
public void Handle(EpisodeFileDeletedEvent message)
|
||||
{
|
||||
if (message.Reason == DeleteMediaFileReason.Upgrade) return;
|
||||
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.EpisodeFile.MovieId);
|
||||
}
|
||||
|
||||
public void Handle(MovieUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
}
|
||||
|
||||
public void Handle(MovieEditedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
}
|
||||
|
||||
public void Handle(MovieDeletedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Deleted, message.Movie.ToResource());
|
||||
}
|
||||
|
||||
public void Handle(MovieRenamedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
}
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
226
src/NzbDrone.Api/Series/MovieResource.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.MediaCover;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Api.Series;
|
||||
|
||||
namespace NzbDrone.Api.Movie
|
||||
{
|
||||
public class MovieResource : RestResource
|
||||
{
|
||||
public MovieResource()
|
||||
{
|
||||
Monitored = true;
|
||||
}
|
||||
|
||||
//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
|
||||
|
||||
//View Only
|
||||
public string Title { get; set; }
|
||||
public List<AlternateTitleResource> AlternateTitles { get; set; }
|
||||
public string SortTitle { get; set; }
|
||||
public long? SizeOnDisk { get; set; }
|
||||
public MovieStatusType Status { get; set; }
|
||||
public string Overview { get; set; }
|
||||
public DateTime? InCinemas { get; set; }
|
||||
public DateTime? PhysicalRelease { get; set; }
|
||||
public List<MediaCover> Images { get; set; }
|
||||
public string Website { get; set; }
|
||||
public bool Downloaded { get; set; }
|
||||
public string RemotePoster { get; set; }
|
||||
public int Year { get; set; }
|
||||
public bool HasFile { get; set; }
|
||||
public string YouTubeTrailerId { get; set; }
|
||||
public string Studio { get; set; }
|
||||
|
||||
//View & Edit
|
||||
public string Path { get; set; }
|
||||
public int ProfileId { get; set; }
|
||||
|
||||
//Editing Only
|
||||
public bool Monitored { get; set; }
|
||||
public int Runtime { get; set; }
|
||||
public DateTime? LastInfoSync { get; set; }
|
||||
public string CleanTitle { get; set; }
|
||||
public string ImdbId { get; set; }
|
||||
public int TmdbId { get; set; }
|
||||
public string TitleSlug { get; set; }
|
||||
public string RootFolderPath { get; set; }
|
||||
public string Certification { get; set; }
|
||||
public List<string> Genres { get; set; }
|
||||
public HashSet<int> Tags { get; set; }
|
||||
public DateTime Added { get; set; }
|
||||
public AddMovieOptions AddOptions { get; set; }
|
||||
public Ratings Ratings { get; set; }
|
||||
public List<string> AlternativeTitles { get; set; }
|
||||
public MovieFileResource MovieFile { get; set; }
|
||||
|
||||
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||
|
||||
//Used to support legacy consumers
|
||||
public int QualityProfileId
|
||||
{
|
||||
get
|
||||
{
|
||||
return ProfileId;
|
||||
}
|
||||
set
|
||||
{
|
||||
if (value > 0 && ProfileId == 0)
|
||||
{
|
||||
ProfileId = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class MovieResourceMapper
|
||||
{
|
||||
public static MovieResource ToResource(this Core.Tv.Movie model)
|
||||
{
|
||||
if (model == null) return null;
|
||||
|
||||
|
||||
long size = 0;
|
||||
bool downloaded = false;
|
||||
MovieFileResource movieFile = null;
|
||||
|
||||
|
||||
if(model.MovieFile != null)
|
||||
{
|
||||
model.MovieFile.LazyLoad();
|
||||
}
|
||||
|
||||
if (model.MovieFile != null && model.MovieFile.IsLoaded && model.MovieFile.Value != null)
|
||||
{
|
||||
size = model.MovieFile.Value.Size;
|
||||
downloaded = true;
|
||||
movieFile = model.MovieFile.Value.ToResource();
|
||||
}
|
||||
|
||||
return new MovieResource
|
||||
{
|
||||
Id = model.Id,
|
||||
TmdbId = model.TmdbId,
|
||||
Title = model.Title,
|
||||
//AlternateTitles
|
||||
SortTitle = model.SortTitle,
|
||||
InCinemas = model.InCinemas,
|
||||
PhysicalRelease = model.PhysicalRelease,
|
||||
HasFile = model.HasFile,
|
||||
Downloaded = downloaded,
|
||||
//TotalEpisodeCount
|
||||
//EpisodeCount
|
||||
//EpisodeFileCount
|
||||
//SizeOnDisk
|
||||
Status = model.Status,
|
||||
Overview = model.Overview,
|
||||
//NextAiring
|
||||
//PreviousAiring
|
||||
Images = model.Images,
|
||||
|
||||
Year = model.Year,
|
||||
|
||||
Path = model.Path,
|
||||
ProfileId = model.ProfileId,
|
||||
|
||||
Monitored = model.Monitored,
|
||||
|
||||
SizeOnDisk = size,
|
||||
|
||||
Runtime = model.Runtime,
|
||||
LastInfoSync = model.LastInfoSync,
|
||||
CleanTitle = model.CleanTitle,
|
||||
ImdbId = model.ImdbId,
|
||||
TitleSlug = model.TitleSlug,
|
||||
RootFolderPath = model.RootFolderPath,
|
||||
Certification = model.Certification,
|
||||
Website = model.Website,
|
||||
Genres = model.Genres,
|
||||
Tags = model.Tags,
|
||||
Added = model.Added,
|
||||
AddOptions = model.AddOptions,
|
||||
AlternativeTitles = model.AlternativeTitles,
|
||||
Ratings = model.Ratings,
|
||||
MovieFile = movieFile,
|
||||
YouTubeTrailerId = model.YouTubeTrailerId,
|
||||
Studio = model.Studio
|
||||
};
|
||||
}
|
||||
|
||||
public static Core.Tv.Movie ToModel(this MovieResource resource)
|
||||
{
|
||||
if (resource == null) return null;
|
||||
|
||||
return new Core.Tv.Movie
|
||||
{
|
||||
Id = resource.Id,
|
||||
TmdbId = resource.TmdbId,
|
||||
|
||||
Title = resource.Title,
|
||||
//AlternateTitles
|
||||
SortTitle = resource.SortTitle,
|
||||
InCinemas = resource.InCinemas,
|
||||
PhysicalRelease = resource.PhysicalRelease,
|
||||
//TotalEpisodeCount
|
||||
//EpisodeCount
|
||||
//EpisodeFileCount
|
||||
//SizeOnDisk
|
||||
Overview = resource.Overview,
|
||||
//NextAiring
|
||||
//PreviousAiring
|
||||
Images = resource.Images,
|
||||
|
||||
Year = resource.Year,
|
||||
|
||||
Path = resource.Path,
|
||||
ProfileId = resource.ProfileId,
|
||||
|
||||
Monitored = resource.Monitored,
|
||||
|
||||
Runtime = resource.Runtime,
|
||||
LastInfoSync = resource.LastInfoSync,
|
||||
CleanTitle = resource.CleanTitle,
|
||||
ImdbId = resource.ImdbId,
|
||||
TitleSlug = resource.TitleSlug,
|
||||
RootFolderPath = resource.RootFolderPath,
|
||||
Certification = resource.Certification,
|
||||
Website = resource.Website,
|
||||
Genres = resource.Genres,
|
||||
Tags = resource.Tags,
|
||||
Added = resource.Added,
|
||||
AddOptions = resource.AddOptions,
|
||||
AlternativeTitles = resource.AlternativeTitles,
|
||||
Ratings = resource.Ratings,
|
||||
YouTubeTrailerId = resource.YouTubeTrailerId,
|
||||
Studio = resource.Studio
|
||||
};
|
||||
}
|
||||
|
||||
public static Core.Tv.Movie ToModel(this MovieResource resource, Core.Tv.Movie movie)
|
||||
{
|
||||
movie.ImdbId = resource.ImdbId;
|
||||
movie.TmdbId = resource.TmdbId;
|
||||
|
||||
movie.Path = resource.Path;
|
||||
movie.ProfileId = resource.ProfileId;
|
||||
|
||||
movie.Monitored = resource.Monitored;
|
||||
|
||||
movie.RootFolderPath = resource.RootFolderPath;
|
||||
movie.Tags = resource.Tags;
|
||||
movie.AddOptions = resource.AddOptions;
|
||||
|
||||
return movie;
|
||||
}
|
||||
|
||||
public static List<MovieResource> ToResource(this IEnumerable<Core.Tv.Movie> movies)
|
||||
{
|
||||
return movies.Select(ToResource).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -236,7 +236,7 @@ namespace NzbDrone.Api.Series
|
||||
|
||||
public void Handle(MediaCoversUpdatedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||
//BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace NzbDrone.Api.System.Tasks
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public string TaskName { get; set; }
|
||||
public int Interval { get; set; }
|
||||
public double Interval { get; set; }
|
||||
public DateTime LastExecution { get; set; }
|
||||
public DateTime NextExecution { get; set; }
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Wanted
|
||||
ISeriesService seriesService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing_episodes")
|
||||
{
|
||||
GetResourcePaged = GetMissingEpisodes;
|
||||
}
|
||||
|
||||
77
src/NzbDrone.Api/Wanted/MovieMissingModule.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using NzbDrone.Api.Movie;
|
||||
using NzbDrone.Api.Movies;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.SignalR;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using System;
|
||||
using NzbDrone.Core.Datastore.Events;
|
||||
|
||||
namespace NzbDrone.Api.Wanted
|
||||
{
|
||||
class MovieMissingModule : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||
IHandle<MovieGrabbedEvent>,
|
||||
IHandle<MovieDownloadedEvent>
|
||||
{
|
||||
protected readonly IMovieService _movieService;
|
||||
|
||||
public MovieMissingModule(IMovieService movieService,
|
||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||
IBroadcastSignalRMessage signalRBroadcaster)
|
||||
: base(signalRBroadcaster, "wanted/missing")
|
||||
{
|
||||
|
||||
_movieService = movieService;
|
||||
GetResourcePaged = GetMissingMovies;
|
||||
}
|
||||
|
||||
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
|
||||
{
|
||||
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("physicalRelease", SortDirection.Descending);
|
||||
|
||||
if (pagingResource.FilterKey == "monitored" && pagingResource.FilterValue == "false")
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == false;
|
||||
}
|
||||
else
|
||||
{
|
||||
pagingSpec.FilterExpression = v => v.Monitored == true;
|
||||
}
|
||||
|
||||
var resource = ApplyToPage(_movieService.MoviesWithoutFiles, pagingSpec, v => MapToResource(v, false));
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
private MovieResource GetMovie(int id)
|
||||
{
|
||||
var movie = _movieService.GetMovie(id);
|
||||
var resource = MapToResource(movie, true);
|
||||
return resource;
|
||||
}
|
||||
|
||||
private MovieResource MapToResource(Core.Tv.Movie movie, bool includeMovieFile)
|
||||
{
|
||||
var resource = movie.ToResource();
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void Handle(MovieGrabbedEvent message)
|
||||
{
|
||||
var resource = message.Movie.Movie.ToResource();
|
||||
|
||||
//add a grabbed field in MovieResource?
|
||||
//resource.Grabbed = true;
|
||||
|
||||
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||
}
|
||||
|
||||
public void Handle(MovieDownloadedEvent message)
|
||||
{
|
||||
BroadcastResourceChange(ModelAction.Updated, message.Movie.Movie.Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ using NzbDrone.Core.Jobs;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Host;
|
||||
using Radarr.Host;
|
||||
using NzbDrone.Test.Common;
|
||||
using FluentAssertions;
|
||||
using System.Linq;
|
||||
|
||||
@@ -3,8 +3,9 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Model;
|
||||
using NzbDrone.Common.Processes;
|
||||
using NzbDrone.Host;
|
||||
using Radarr.Host;
|
||||
using NzbDrone.Test.Common;
|
||||
using Radarr.Host;
|
||||
|
||||
namespace NzbDrone.App.Test
|
||||
{
|
||||
|
||||
@@ -21,4 +21,3 @@ using System.Runtime.InteropServices;
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("b47d34ef-05e8-4826-8a57-9dd05106c964")]
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
|
||||
@@ -3,7 +3,7 @@ using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Host;
|
||||
using Radarr.Host;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.App.Test
|
||||
|
||||
@@ -40,7 +40,7 @@ namespace NzbDrone.Automation.Test
|
||||
_runner.KillAll();
|
||||
_runner.Start();
|
||||
|
||||
driver.Url = "http://localhost:8989";
|
||||
driver.Url = "http://localhost:7878";
|
||||
|
||||
var page = new PageBase(driver);
|
||||
page.WaitForNoSpinner();
|
||||
|
||||
@@ -20,5 +20,3 @@ using System.Runtime.InteropServices;
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("6b8945f5-f5b5-4729-865d-f958fbd673d9")]
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
|
||||
@@ -49,7 +49,7 @@ namespace NzbDrone.Common.Test
|
||||
public void GetValue_Success()
|
||||
{
|
||||
const string key = "Port";
|
||||
const string value = "8989";
|
||||
const string value = "7878";
|
||||
|
||||
var result = Subject.GetValue(key, value);
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace NzbDrone.Common.Test
|
||||
public void GetInt_Success()
|
||||
{
|
||||
const string key = "Port";
|
||||
const int value = 8989;
|
||||
const int value = 7878;
|
||||
|
||||
|
||||
var result = Subject.GetValueInt(key, value);
|
||||
@@ -95,7 +95,7 @@ namespace NzbDrone.Common.Test
|
||||
[Test]
|
||||
public void GetPort_Success()
|
||||
{
|
||||
const int value = 8989;
|
||||
const int value = 7878;
|
||||
|
||||
|
||||
var result = Subject.Port;
|
||||
|
||||
@@ -263,7 +263,7 @@ namespace NzbDrone.Common.Test
|
||||
[Test]
|
||||
public void GetUpdateClientExePath()
|
||||
{
|
||||
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\NzbDrone.Update.exe".AsOsAgnostic());
|
||||
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\Radarr.Update.exe".AsOsAgnostic());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -5,7 +5,7 @@ using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Host;
|
||||
using Radarr.Host;
|
||||
using NzbDrone.Test.Common;
|
||||
|
||||
namespace NzbDrone.Common.Test
|
||||
|
||||
@@ -6,22 +6,33 @@ namespace NzbDrone.Common.Cloud
|
||||
{
|
||||
IHttpRequestBuilderFactory Services { get; }
|
||||
IHttpRequestBuilderFactory SkyHookTvdb { get; }
|
||||
IHttpRequestBuilderFactory TMDB { get; }
|
||||
IHttpRequestBuilderFactory TMDBSingle { get; }
|
||||
}
|
||||
|
||||
public class SonarrCloudRequestBuilder : ISonarrCloudRequestBuilder
|
||||
{
|
||||
public SonarrCloudRequestBuilder()
|
||||
{
|
||||
Services = new HttpRequestBuilder("http://services.sonarr.tv/v1/")
|
||||
Services = new HttpRequestBuilder("http://radarr.aeonlucid.com/v1/")
|
||||
.CreateFactory();
|
||||
|
||||
SkyHookTvdb = new HttpRequestBuilder("http://skyhook.sonarr.tv/v1/tvdb/{route}/{language}/")
|
||||
.SetSegment("language", "en")
|
||||
.CreateFactory();
|
||||
|
||||
TMDB = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}/{id}{secondaryRoute}")
|
||||
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||
.CreateFactory();
|
||||
|
||||
TMDBSingle = new HttpRequestBuilder("https://api.themoviedb.org/3/{route}")
|
||||
.AddQueryParam("api_key", "1a7373301961d03f97f853a876dd1212")
|
||||
.CreateFactory();
|
||||
}
|
||||
|
||||
public IHttpRequestBuilderFactory Services { get; private set; }
|
||||
|
||||
public IHttpRequestBuilderFactory SkyHookTvdb { get; private set; }
|
||||
public IHttpRequestBuilderFactory TMDB { get; private set; }
|
||||
public IHttpRequestBuilderFactory TMDBSingle { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Common
|
||||
Console.WriteLine(" Commands:");
|
||||
Console.WriteLine(" /{0} Install the application as a Windows Service ({1}).", StartupContext.INSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||
Console.WriteLine(" /{0} Uninstall already installed Windows Service ({1}).", StartupContext.UNINSTALL_SERVICE, ServiceProvider.NZBDRONE_SERVICE_NAME);
|
||||
Console.WriteLine(" /{0} Don't open Sonarr in a browser", StartupContext.NO_BROWSER);
|
||||
Console.WriteLine(" /{0} Don't open Radarr in a browser", StartupContext.NO_BROWSER);
|
||||
Console.WriteLine(" <No Arguments> Run application in console mode.");
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace NzbDrone.Common.EnvironmentInfo
|
||||
}
|
||||
else
|
||||
{
|
||||
AppDataFolder = Path.Combine(Environment.GetFolderPath(DATA_SPECIAL_FOLDER, Environment.SpecialFolderOption.None), "NzbDrone");
|
||||
AppDataFolder = Path.Combine(Environment.GetFolderPath(DATA_SPECIAL_FOLDER, Environment.SpecialFolderOption.None), "Radarr");
|
||||
}
|
||||
|
||||
StartUpFolder = new FileInfo(Assembly.GetExecutingAssembly().Location).Directory.FullName;
|
||||
|
||||
@@ -13,13 +13,13 @@ namespace NzbDrone.Common.Extensions
|
||||
private const string NZBDRONE_DB = "nzbdrone.db";
|
||||
private const string NZBDRONE_LOG_DB = "logs.db";
|
||||
private const string NLOG_CONFIG_FILE = "nlog.config";
|
||||
private const string UPDATE_CLIENT_EXE = "NzbDrone.Update.exe";
|
||||
private const string UPDATE_CLIENT_EXE = "Radarr.Update.exe";
|
||||
private const string BACKUP_FOLDER = "Backups";
|
||||
|
||||
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "nzbdrone_update" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "NzbDrone" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_BACKUP_FOLDER_NAME = "nzbdrone_backup" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "nzbdrone_appdata_backup" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_SANDBOX_FOLDER_NAME = "radarr_update" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_PACKAGE_FOLDER_NAME = "Radarr" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_BACKUP_FOLDER_NAME = "radarr_backup" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_BACKUP_APPDATA_FOLDER_NAME = "radarr_appdata_backup" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_CLIENT_FOLDER_NAME = "NzbDrone.Update" + Path.DirectorySeparatorChar;
|
||||
private static readonly string UPDATE_LOG_FOLDER_NAME = "UpdateLogs" + Path.DirectorySeparatorChar;
|
||||
|
||||
|
||||
@@ -9,12 +9,12 @@ namespace NzbDrone.Common.Http
|
||||
|
||||
static UserAgentBuilder()
|
||||
{
|
||||
UserAgent = string.Format("Sonarr/{0} ({1} {2})",
|
||||
UserAgent = string.Format("Radarr/{0} ({1} {2})",
|
||||
BuildInfo.Version,
|
||||
OsInfo.Os, OsInfo.Version.ToString(2));
|
||||
|
||||
UserAgentSimplified = string.Format("Sonarr/{0}",
|
||||
UserAgentSimplified = string.Format("Radarr/{0}",
|
||||
BuildInfo.Version.ToString(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,9 +103,9 @@ namespace NzbDrone.Common.Instrumentation
|
||||
|
||||
private static void RegisterAppFile(IAppFolderInfo appFolderInfo)
|
||||
{
|
||||
RegisterAppFile(appFolderInfo, "appFileInfo", "sonarr.txt", 5, LogLevel.Info);
|
||||
RegisterAppFile(appFolderInfo, "appFileDebug", "sonarr.debug.txt", 50, LogLevel.Off);
|
||||
RegisterAppFile(appFolderInfo, "appFileTrace", "sonarr.trace.txt", 50, LogLevel.Off);
|
||||
RegisterAppFile(appFolderInfo, "appFileInfo", "radarr.txt", 5, LogLevel.Info);
|
||||
RegisterAppFile(appFolderInfo, "appFileDebug", "radarr.debug.txt", 50, LogLevel.Off);
|
||||
RegisterAppFile(appFolderInfo, "appFileTrace", "radarr.trace.txt", 50, LogLevel.Off);
|
||||
}
|
||||
|
||||
private static LoggingRule RegisterAppFile(IAppFolderInfo appFolderInfo, string name, string fileName, int maxArchiveFiles, LogLevel minLogLevel)
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace NzbDrone.Common.Processes
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public const string NZB_DRONE_PROCESS_NAME = "NzbDrone";
|
||||
public const string NZB_DRONE_CONSOLE_PROCESS_NAME = "NzbDrone.Console";
|
||||
public const string NZB_DRONE_PROCESS_NAME = "Radarr";
|
||||
public const string NZB_DRONE_CONSOLE_PROCESS_NAME = "Radarr.Console";
|
||||
|
||||
public ProcessProvider(Logger logger)
|
||||
{
|
||||
|
||||
@@ -9,4 +9,3 @@ using System.Runtime.InteropServices;
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("b6eaa144-e13b-42e5-a738-c60d89c0f728")]
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("sonarr.tv")]
|
||||
[assembly: AssemblyCompany("radarr.tv")]
|
||||
[assembly: AssemblyProduct("NzbDrone")]
|
||||
[assembly: AssemblyVersion("0.1.0.*")]
|
||||
[assembly: AssemblyCopyright("GNU General Public v3")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Common
|
||||
|
||||
public class ServiceProvider : IServiceProvider
|
||||
{
|
||||
public const string NZBDRONE_SERVICE_NAME = "NzbDrone";
|
||||
public const string NZBDRONE_SERVICE_NAME = "Radarr";
|
||||
|
||||
private readonly IProcessProvider _processProvider;
|
||||
private readonly Logger _logger;
|
||||
@@ -78,7 +78,7 @@ namespace NzbDrone.Common
|
||||
serviceInstaller.Context = context;
|
||||
serviceInstaller.DisplayName = serviceName;
|
||||
serviceInstaller.ServiceName = serviceName;
|
||||
serviceInstaller.Description = "NzbDrone Application Server";
|
||||
serviceInstaller.Description = "Radarr Application Server";
|
||||
serviceInstaller.StartType = ServiceStartMode.Automatic;
|
||||
serviceInstaller.ServicesDependedOn = new[] { "EventLog", "Tcpip", "http" };
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using NzbDrone.Host;
|
||||
using Radarr.Host;
|
||||
|
||||
namespace NzbDrone.Console
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Net.Sockets;
|
||||
using NLog;
|
||||
using NzbDrone.Common.EnvironmentInfo;
|
||||
using NzbDrone.Common.Instrumentation;
|
||||
using NzbDrone.Host;
|
||||
using Radarr.Host;
|
||||
|
||||
namespace NzbDrone.Console
|
||||
{
|
||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Console
|
||||
{
|
||||
System.Console.WriteLine("");
|
||||
System.Console.WriteLine("");
|
||||
Logger.Fatal(exception.Message + ". This can happen if another instance of Sonarr is already running another application is using the same port (default: 8989) or the user has insufficient permissions");
|
||||
Logger.Fatal(exception.Message + ". This can happen if another instance of Radarr is already running another application is using the same port (default: 7878) or the user has insufficient permissions");
|
||||
System.Console.WriteLine("Press enter to exit...");
|
||||
System.Console.ReadLine();
|
||||
Environment.Exit(1);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<OutputType>Exe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>NzbDrone.Console</RootNamespace>
|
||||
<AssemblyName>NzbDrone.Console</AssemblyName>
|
||||
<AssemblyName>Radarr.Console</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<TargetFrameworkProfile>
|
||||
@@ -54,7 +54,7 @@
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>..\NzbDrone.Host\NzbDrone.ico</ApplicationIcon>
|
||||
<ApplicationIcon>Radarr.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<StartupObject>NzbDrone.Console.ConsoleApp</StartupObject>
|
||||
@@ -139,6 +139,9 @@
|
||||
</None>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Radarr.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
|
||||
@@ -7,5 +7,3 @@ using System.Runtime.InteropServices;
|
||||
|
||||
[assembly: AssemblyTitle("NzbDrone.Host")]
|
||||
[assembly: Guid("67AADCD9-89AA-4D95-8281-3193740E70E5")]
|
||||
|
||||
[assembly: AssemblyVersion("10.0.0.*")]
|
||||
BIN
src/NzbDrone.Console/Radarr.ico
Normal file
|
After Width: | Height: | Size: 41 KiB |
@@ -178,8 +178,9 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||
public void should_return_an_empty_list_when_none_are_appproved()
|
||||
{
|
||||
var decisions = new List<DownloadDecision>();
|
||||
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
|
||||
decisions.Add(new DownloadDecision(null, new Rejection("Failure!")));
|
||||
RemoteEpisode ep = null;
|
||||
decisions.Add(new DownloadDecision(ep, new Rejection("Failure!")));
|
||||
decisions.Add(new DownloadDecision(ep, new Rejection("Failure!")));
|
||||
|
||||
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.DelugeTests
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new DelugeSettings()
|
||||
{
|
||||
TvCategory = null
|
||||
MovieCategory = null
|
||||
};
|
||||
|
||||
_queued = new DelugeTorrent
|
||||
|
||||
@@ -92,14 +92,14 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.NzbgetTests
|
||||
protected void GivenFailedDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns((string)null);
|
||||
}
|
||||
|
||||
protected void GivenSuccessfulDownload()
|
||||
{
|
||||
Mocker.GetMock<INzbgetProxy>()
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<NzbgetSettings>()))
|
||||
.Setup(s => s.DownloadNzb(It.IsAny<byte[]>(), It.IsAny<string>(), It.IsAny<string>(), It.IsAny<int>(), It.IsAny<bool>(), It.IsAny<NzbgetSettings>()))
|
||||
.Returns(Guid.NewGuid().ToString().Replace("-", ""));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.QBittorrentTests
|
||||
Port = 2222,
|
||||
Username = "admin",
|
||||
Password = "pass",
|
||||
TvCategory = "tv"
|
||||
MovieCategory = "movies-radarr"
|
||||
};
|
||||
|
||||
Mocker.GetMock<ITorrentFileInfoReader>()
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.RTorrentTests
|
||||
Subject.Definition = new DownloadClientDefinition();
|
||||
Subject.Definition.Settings = new RTorrentSettings()
|
||||
{
|
||||
TvCategory = null
|
||||
MovieCategory = null
|
||||
};
|
||||
|
||||
_downloading = new RTorrentTorrent
|
||||
|
||||
@@ -112,12 +112,12 @@ namespace NzbDrone.Core.Test.Download.DownloadClientTests.TransmissionTests
|
||||
|
||||
protected void GivenTvCategory()
|
||||
{
|
||||
_settings.TvCategory = "sonarr";
|
||||
_settings.MovieCategory = "radarr";
|
||||
}
|
||||
|
||||
protected void GivenTvDirectory()
|
||||
{
|
||||
_settings.TvDirectory = @"C:/Downloads/Finished/sonarr";
|
||||
_settings.MovieDirectory = @"C:/Downloads/Finished/radarr";
|
||||
}
|
||||
|
||||
protected void GivenFailedDownload()
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.BitMeTv;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.BitMeTvTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BitMeTvFixture : CoreTest<BitMeTv>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "BitMeTV",
|
||||
Settings = new BitMeTvSettings() { Cookie = "uid=123" }
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_BitMeTv()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/BitMeTv/BitMeTv.xml");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = releases.First() as TorrentInfo;
|
||||
|
||||
torrentInfo.Title.Should().Be("Total.Divas.S02E08.HDTV.x264-CRiMSON");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("http://www.bitmetv.org/download.php/12/Total.Divas.S02E08.HDTV.x264-CRiMSON.torrent");
|
||||
torrentInfo.InfoUrl.Should().BeNullOrEmpty();
|
||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/13 17:04:29"));
|
||||
torrentInfo.Size.Should().Be(395009065);
|
||||
torrentInfo.InfoHash.Should().Be(null);
|
||||
torrentInfo.MagnetUrl.Should().Be(null);
|
||||
torrentInfo.Peers.Should().Be(null);
|
||||
torrentInfo.Seeders.Should().Be(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,161 +0,0 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.BroadcastheNet;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Test.Common;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.BroadcastheNetTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class BroadcastheNetFixture : CoreTest<BroadcastheNet>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "BroadcastheNet",
|
||||
Settings = new BroadcastheNetSettings() { ApiKey = "abc", BaseUrl = "https://api.btnapps.net/" }
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_BroadcastheNet()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/BroadcastheNet/RecentFeed.json");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(2);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = releases.First() as TorrentInfo;
|
||||
|
||||
torrentInfo.Guid.Should().Be("BTN-123");
|
||||
torrentInfo.Title.Should().Be("Jimmy.Kimmel.2014.09.15.Jane.Fonda.HDTV.x264-aAF");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("https://broadcasthe.net/torrents.php?action=download&id=123&authkey=123&torrent_pass=123");
|
||||
torrentInfo.InfoUrl.Should().Be("https://broadcasthe.net/torrents.php?id=237457&torrentid=123");
|
||||
torrentInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/16 21:15:33"));
|
||||
torrentInfo.Size.Should().Be(505099926);
|
||||
torrentInfo.InfoHash.Should().Be("123");
|
||||
torrentInfo.TvdbId.Should().Be(71998);
|
||||
torrentInfo.TvRageId.Should().Be(4055);
|
||||
torrentInfo.MagnetUrl.Should().BeNullOrEmpty();
|
||||
torrentInfo.Peers.Should().Be(40+9);
|
||||
torrentInfo.Seeders.Should().Be(40);
|
||||
|
||||
torrentInfo.Origin.Should().Be("Scene");
|
||||
torrentInfo.Source.Should().Be("HDTV");
|
||||
torrentInfo.Container.Should().Be("MP4");
|
||||
torrentInfo.Codec.Should().Be("x264");
|
||||
torrentInfo.Resolution.Should().Be("SD");
|
||||
}
|
||||
|
||||
private void VerifyBackOff()
|
||||
{
|
||||
Mocker.GetMock<IIndexerStatusService>()
|
||||
.Verify(v => v.RecordFailure(It.IsAny<int>(), It.IsAny<TimeSpan>()), Times.Once());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_back_off_on_bad_request()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.BadRequest));
|
||||
|
||||
var results = Subject.FetchRecent();
|
||||
|
||||
results.Should().BeEmpty();
|
||||
|
||||
VerifyBackOff();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_back_off_and_report_api_key_invalid()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.Unauthorized));
|
||||
|
||||
var results = Subject.FetchRecent();
|
||||
|
||||
results.Should().BeEmpty();
|
||||
|
||||
VerifyBackOff();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_back_off_on_unknown_method()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.NotFound));
|
||||
|
||||
var results = Subject.FetchRecent();
|
||||
|
||||
results.Should().BeEmpty();
|
||||
|
||||
VerifyBackOff();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_back_off_api_limit_reached()
|
||||
{
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(v => v.Execute(It.IsAny<HttpRequest>()))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), new byte[0], System.Net.HttpStatusCode.ServiceUnavailable));
|
||||
|
||||
var results = Subject.FetchRecent();
|
||||
|
||||
results.Should().BeEmpty();
|
||||
|
||||
VerifyBackOff();
|
||||
|
||||
ExceptionVerification.ExpectedWarns(1);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_replace_https_http_as_needed()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/BroadcastheNet/RecentFeed.json");
|
||||
|
||||
(Subject.Definition.Settings as BroadcastheNetSettings).BaseUrl = "http://api.btnapps.net/";
|
||||
|
||||
recentFeed = recentFeed.Replace("http:", "https:");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.POST)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(2);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = releases.First() as TorrentInfo;
|
||||
|
||||
torrentInfo.DownloadUrl.Should().Be("http://broadcasthe.net/torrents.php?action=download&id=123&authkey=123&torrent_pass=123");
|
||||
torrentInfo.InfoUrl.Should().Be("http://broadcasthe.net/torrents.php?id=237457&torrentid=123");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Fanzub;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.FanzubTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class FanzubFixture : CoreTest<Fanzub>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "Fanzub",
|
||||
Settings = new FanzubSettings()
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_fanzub()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/Fanzub/fanzub.xml");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(3);
|
||||
|
||||
var releaseInfo = releases.First();
|
||||
|
||||
releaseInfo.Title.Should().Be("[Vivid] Hanayamata - 10 [A33D6606]");
|
||||
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
|
||||
releaseInfo.DownloadUrl.Should().Be("http://fanzub.com/nzb/296464/Vivid%20Hanayamata%20-%2010.nzb");
|
||||
releaseInfo.InfoUrl.Should().BeNullOrEmpty();
|
||||
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2014/09/13 12:56:53"));
|
||||
releaseInfo.Size.Should().Be(556246858);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,14 +42,14 @@ namespace NzbDrone.Core.Test.IndexerTests.OmgwtfnzbsTests
|
||||
|
||||
var releaseInfo = releases.First();
|
||||
|
||||
releaseInfo.Title.Should().Be("Stephen.Fry.Gadget.Man.S01E05.HDTV.x264-C4TV");
|
||||
releaseInfo.Title.Should().Be("Un.Petit.Boulot.2016.FRENCH.720p.BluRay.DTS.x264-LOST");
|
||||
releaseInfo.DownloadProtocol.Should().Be(DownloadProtocol.Usenet);
|
||||
releaseInfo.DownloadUrl.Should().Be("http://api.omgwtfnzbs.org/sn.php?id=OAl4g&user=nzbdrone&api=nzbdrone");
|
||||
releaseInfo.InfoUrl.Should().Be("http://omgwtfnzbs.org/details.php?id=OAl4g");
|
||||
releaseInfo.DownloadUrl.Should().Be("https://api.omgwtfnzbs.me/nzb/?id=8a2Bw&user=nzbdrone&api=nzbdrone");
|
||||
releaseInfo.InfoUrl.Should().Be("https://omgwtfnzbs.me/details.php?id=8a2Bw");
|
||||
releaseInfo.CommentUrl.Should().BeNullOrEmpty();
|
||||
releaseInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2012/12/17 23:30:13"));
|
||||
releaseInfo.Size.Should().Be(236822906);
|
||||
releaseInfo.PublishDate.Should().Be(DateTime.Parse("2017/01/09 00:16:54"));
|
||||
releaseInfo.Size.Should().Be(5354909355);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Common.Http;
|
||||
using NzbDrone.Core.Indexers;
|
||||
using NzbDrone.Core.Indexers.Torrentleech;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
|
||||
namespace NzbDrone.Core.Test.IndexerTests.TorrentleechTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class TorrentleechFixture : CoreTest<Torrentleech>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Subject.Definition = new IndexerDefinition()
|
||||
{
|
||||
Name = "Torrentleech",
|
||||
Settings = new TorrentleechSettings()
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_parse_recent_feed_from_Torrentleech()
|
||||
{
|
||||
var recentFeed = ReadAllText(@"Files/Indexers/Torrentleech/Torrentleech.xml");
|
||||
|
||||
Mocker.GetMock<IHttpClient>()
|
||||
.Setup(o => o.Execute(It.Is<HttpRequest>(v => v.Method == HttpMethod.GET)))
|
||||
.Returns<HttpRequest>(r => new HttpResponse(r, new HttpHeader(), recentFeed));
|
||||
|
||||
var releases = Subject.FetchRecent();
|
||||
|
||||
releases.Should().HaveCount(5);
|
||||
releases.First().Should().BeOfType<TorrentInfo>();
|
||||
|
||||
var torrentInfo = releases.First() as TorrentInfo;
|
||||
|
||||
torrentInfo.Title.Should().Be("Classic Car Rescue S02E04 720p HDTV x264-C4TV");
|
||||
torrentInfo.DownloadProtocol.Should().Be(DownloadProtocol.Torrent);
|
||||
torrentInfo.DownloadUrl.Should().Be("http://www.torrentleech.org/rss/download/513575/1234/Classic.Car.Rescue.S02E04.720p.HDTV.x264-C4TV.torrent");
|
||||
torrentInfo.InfoUrl.Should().Be("http://www.torrentleech.org/torrent/513575");
|
||||
torrentInfo.CommentUrl.Should().Be("http://www.torrentleech.org/torrent/513575#comments");
|
||||
torrentInfo.Indexer.Should().Be(Subject.Definition.Name);
|
||||
torrentInfo.PublishDate.Should().Be(DateTime.Parse("2014/05/12 19:15:28"));
|
||||
torrentInfo.Size.Should().Be(0);
|
||||
torrentInfo.InfoHash.Should().Be(null);
|
||||
torrentInfo.MagnetUrl.Should().Be(null);
|
||||
torrentInfo.Peers.Should().Be(7+1);
|
||||
torrentInfo.Seeders.Should().Be(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -237,8 +237,6 @@
|
||||
<Compile Include="IndexerSearchTests\NzbSearchServiceFixture.cs" />
|
||||
<Compile Include="IndexerSearchTests\SearchDefinitionFixture.cs" />
|
||||
<Compile Include="IndexerTests\BasicRssParserFixture.cs" />
|
||||
<Compile Include="IndexerTests\BitMeTvTests\BitMeTvFixture.cs" />
|
||||
<Compile Include="IndexerTests\BroadcastheNetTests\BroadcastheNetFixture.cs" />
|
||||
<Compile Include="IndexerTests\HDBitsTests\HDBitsFixture.cs" />
|
||||
<Compile Include="IndexerTests\IndexerServiceFixture.cs" />
|
||||
<Compile Include="IndexerTests\IndexerStatusServiceFixture.cs" />
|
||||
@@ -251,7 +249,6 @@
|
||||
<Compile Include="IndexerTests\NewznabTests\NewznabFixture.cs" />
|
||||
<Compile Include="IndexerTests\NewznabTests\NewznabRequestGeneratorFixture.cs" />
|
||||
<Compile Include="IndexerTests\NewznabTests\NewznabSettingFixture.cs" />
|
||||
<Compile Include="IndexerTests\FanzubTests\FanzubFixture.cs" />
|
||||
<Compile Include="IndexerTests\OmgwtfnzbsTests\OmgwtfnzbsFixture.cs" />
|
||||
<Compile Include="IndexerTests\SeasonSearchFixture.cs" />
|
||||
<Compile Include="IndexerTests\TestIndexer.cs" />
|
||||
@@ -259,7 +256,6 @@
|
||||
<Compile Include="IndexerTests\IPTorrentsTests\IPTorrentsFixture.cs" />
|
||||
<Compile Include="IndexerTests\KickassTorrentsTests\KickassTorrentsFixture.cs" />
|
||||
<Compile Include="IndexerTests\NyaaTests\NyaaFixture.cs" />
|
||||
<Compile Include="IndexerTests\TorrentleechTests\TorrentleechFixture.cs" />
|
||||
<Compile Include="IndexerTests\TorrentRssIndexerTests\TorrentRssIndexerFixture.cs" />
|
||||
<Compile Include="IndexerTests\TorrentRssIndexerTests\TestTorrentRssIndexer.cs" />
|
||||
<Compile Include="IndexerTests\WomblesTests\WomblesFixture.cs" />
|
||||
|
||||