Compare commits
851 Commits
v0.2.0.18
...
v0.2.0.778
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f2e5d9e996 | ||
|
|
bae3a48aa1 | ||
|
|
6d033c57f4 | ||
|
|
d6cf53e12c | ||
|
|
5238b78813 | ||
|
|
705b233819 | ||
|
|
295536ae30 | ||
|
|
42c980c905 | ||
|
|
0a71aac56c | ||
|
|
c312ffd7db | ||
|
|
5c5f06a92c | ||
|
|
3eab8248e6 | ||
|
|
c33d9727a0 | ||
|
|
ca6784f7b5 | ||
|
|
ca00d0d6cc | ||
|
|
756fc7556c | ||
|
|
9f4ce50dd6 | ||
|
|
a460e89a8d | ||
|
|
edda8786ad | ||
|
|
b1c5dd8167 | ||
|
|
a620c4b5d8 | ||
|
|
28b523b504 | ||
|
|
7af88037bb | ||
|
|
43446ee3d0 | ||
|
|
accf8a9efa | ||
|
|
b70ed720c5 | ||
|
|
cff4578c66 | ||
|
|
7bbebe53a3 | ||
|
|
d81e3a79cf | ||
|
|
09c86013b0 | ||
|
|
f1873a9684 | ||
|
|
3d48da2111 | ||
|
|
86634006e5 | ||
|
|
234827d5fd | ||
|
|
10bceaf370 | ||
|
|
b7f6ff7b2e | ||
|
|
6767f602fb | ||
|
|
e43e7d2b8d | ||
|
|
811a4bf117 | ||
|
|
9dee1d6fad | ||
|
|
390e4c3014 | ||
|
|
aace29e1e1 | ||
|
|
8fb257d5b7 | ||
|
|
28e0f85e88 | ||
|
|
41d3f6d7ea | ||
|
|
b19fbcbb71 | ||
|
|
5200758200 | ||
|
|
6210c5b8f8 | ||
|
|
6e31f7220c | ||
|
|
797a9acff5 | ||
|
|
b36053e1f4 | ||
|
|
212bcebdaf | ||
|
|
3c8162f1d6 | ||
|
|
096d24ed91 | ||
|
|
63e3361fb5 | ||
|
|
51854ef73b | ||
|
|
a0486b54a6 | ||
|
|
7ed0db10cb | ||
|
|
e94591a290 | ||
|
|
fccd02a0ca | ||
|
|
b49f0e70ed | ||
|
|
fc1585e900 | ||
|
|
b36ac091fc | ||
|
|
ab28bfead2 | ||
|
|
3ab3fbfd57 | ||
|
|
d133ee3143 | ||
|
|
98b6932ffe | ||
|
|
58e81a916c | ||
|
|
817f48448c | ||
|
|
1eca179b4e | ||
|
|
b05d505bce | ||
|
|
ace426e69f | ||
|
|
a57c9917cc | ||
|
|
9e84b4a782 | ||
|
|
494ef16735 | ||
|
|
5a0f02007f | ||
|
|
b1025e7229 | ||
|
|
446d661345 | ||
|
|
3eb351823e | ||
|
|
835a7cffa1 | ||
|
|
e728330ce4 | ||
|
|
6f3118c142 | ||
|
|
b568072140 | ||
|
|
7db92c6bcf | ||
|
|
f1e8a9acfc | ||
|
|
dae389ce64 | ||
|
|
7c3d8c8ff9 | ||
|
|
8ca66fb61a | ||
|
|
064844ac0c | ||
|
|
5540594ecf | ||
|
|
433ae019de | ||
|
|
10091b9454 | ||
|
|
475851775f | ||
|
|
0fff862fd2 | ||
|
|
23754c49dc | ||
|
|
fbf790e9fd | ||
|
|
6d00bd0f7a | ||
|
|
5bf95e0d9e | ||
|
|
8bb4b02be7 | ||
|
|
b26a036eed | ||
|
|
ef57882291 | ||
|
|
32a2407ad1 | ||
|
|
33b48eec95 | ||
|
|
3790dc9109 | ||
|
|
343d849536 | ||
|
|
c36b259fa9 | ||
|
|
6463913f22 | ||
|
|
e39deb4bdc | ||
|
|
9ca2c21547 | ||
|
|
f376360611 | ||
|
|
3e966d4d58 | ||
|
|
e036267c33 | ||
|
|
7d4378ca7a | ||
|
|
ee1ebfd893 | ||
|
|
403fd0f0c0 | ||
|
|
fc5ac8219f | ||
|
|
600a433faa | ||
|
|
5609facd9d | ||
|
|
36ea6c6b99 | ||
|
|
56ac87c760 | ||
|
|
47753c47a5 | ||
|
|
712c0eb84a | ||
|
|
8765155223 | ||
|
|
63d7596e98 | ||
|
|
640edf0cce | ||
|
|
280445e756 | ||
|
|
bae8d5e9a4 | ||
|
|
07254adf91 | ||
|
|
d33ec334f3 | ||
|
|
a80e9f11f2 | ||
|
|
4a0ef984fb | ||
|
|
685012280b | ||
|
|
6963078669 | ||
|
|
7182081fca | ||
|
|
87ee360818 | ||
|
|
ad222570be | ||
|
|
680681c8bd | ||
|
|
e2ae7536ad | ||
|
|
98c117a460 | ||
|
|
c54f8806b3 | ||
|
|
454d5c37f9 | ||
|
|
e9f084fd81 | ||
|
|
d1bbcdc039 | ||
|
|
c17deb7d92 | ||
|
|
7066b078ab | ||
|
|
b4bb8875d3 | ||
|
|
cb596488f2 | ||
|
|
3403ddf993 | ||
|
|
17118cf24d | ||
|
|
27ab70333c | ||
|
|
f4031f1e5f | ||
|
|
a9154559b8 | ||
|
|
0f2f2e4b32 | ||
|
|
6deefbb997 | ||
|
|
43a71da0a7 | ||
|
|
499e46e10a | ||
|
|
3f013271c9 | ||
|
|
529591bc18 | ||
|
|
79307d3c25 | ||
|
|
8f79563cf0 | ||
|
|
0dc67419be | ||
|
|
066c746e5f | ||
|
|
31fcac5bd9 | ||
|
|
1b29b89bf1 | ||
|
|
c593f4250d | ||
|
|
59c07cc5f3 | ||
|
|
2b1023e768 | ||
|
|
f10af08f95 | ||
|
|
18fcda5fd6 | ||
|
|
1ccfde334f | ||
|
|
421a191650 | ||
|
|
35e046bb87 | ||
|
|
8ece7e8b4d | ||
|
|
fadc5f0099 | ||
|
|
680430737d | ||
|
|
5d3750a295 | ||
|
|
e525f23281 | ||
|
|
2e41763b92 | ||
|
|
5b70ecaee0 | ||
|
|
06ad30397b | ||
|
|
f2218006a1 | ||
|
|
e26fd22540 | ||
|
|
05a83e4e95 | ||
|
|
3b3fe197ca | ||
|
|
149c5292f1 | ||
|
|
3cf5301e46 | ||
|
|
4b1f7da317 | ||
|
|
a25c056def | ||
|
|
0db27d9029 | ||
|
|
e6dfd89300 | ||
|
|
db6e91cd95 | ||
|
|
1bae7bb623 | ||
|
|
7cf2a8cb62 | ||
|
|
1a4fb6e7bb | ||
|
|
ae0fc019e5 | ||
|
|
3f438563b8 | ||
|
|
51e0cdf982 | ||
|
|
3d9fd3ff25 | ||
|
|
866cec096d | ||
|
|
71eaa98518 | ||
|
|
2899bbf330 | ||
|
|
72f40470a7 | ||
|
|
7c5c4e7594 | ||
|
|
77f369caab | ||
|
|
571730ddec | ||
|
|
5c22d0b61d | ||
|
|
fe0a54685f | ||
|
|
2d951bf378 | ||
|
|
54df46df8c | ||
|
|
b9eab860f5 | ||
|
|
24a394bf46 | ||
|
|
af2b5c2f1c | ||
|
|
961a6d89a4 | ||
|
|
b81d8c4678 | ||
|
|
73f0916fa0 | ||
|
|
6c10d77721 | ||
|
|
d9a3f303e7 | ||
|
|
1894d493f3 | ||
|
|
88140dd3aa | ||
|
|
fb1d13bc58 | ||
|
|
b71031f6d3 | ||
|
|
d03f4a515e | ||
|
|
0668f12e62 | ||
|
|
0083e95019 | ||
|
|
c7fcfe04be | ||
|
|
e11455c964 | ||
|
|
4d0226e0d5 | ||
|
|
7cfa0531dc | ||
|
|
5bd008f468 | ||
|
|
f36db9f77b | ||
|
|
4640519438 | ||
|
|
597a070383 | ||
|
|
07d3b1b3a5 | ||
|
|
665832f0cc | ||
|
|
0d60375a56 | ||
|
|
d4eeb666e0 | ||
|
|
593fa4239f | ||
|
|
3c1b5385ba | ||
|
|
ea22f5db79 | ||
|
|
e32bb6dbbf | ||
|
|
f897591d32 | ||
|
|
cf8f690d7a | ||
|
|
e3dc31cca5 | ||
|
|
ddc6ccbf15 | ||
|
|
18773bc665 | ||
|
|
91c71ed6a0 | ||
|
|
f3b5d9a1d6 | ||
|
|
83deba1c99 | ||
|
|
9787cf6cdd | ||
|
|
7433e89467 | ||
|
|
0aa6066a6f | ||
|
|
3dd14c72c8 | ||
|
|
0d85c7435c | ||
|
|
a3c0f4cb3f | ||
|
|
3f2da1441f | ||
|
|
f49d68ad6a | ||
|
|
f138d4f677 | ||
|
|
aa977eb2d5 | ||
|
|
e0f72e4853 | ||
|
|
83560ad937 | ||
|
|
5cace1d857 | ||
|
|
39322cbbca | ||
|
|
46daa11c46 | ||
|
|
98e2bd00ab | ||
|
|
0f2234bcdc | ||
|
|
3f05ef810e | ||
|
|
aab425ee5b | ||
|
|
f7bc889723 | ||
|
|
cc4fb5a40b | ||
|
|
bbb4880ba4 | ||
|
|
a2098a5797 | ||
|
|
93bdac31ea | ||
|
|
92a588751a | ||
|
|
272db9d483 | ||
|
|
9d75fc18a1 | ||
|
|
d8d60c6bb0 | ||
|
|
8c656626d6 | ||
|
|
b773119193 | ||
|
|
bdc0db3357 | ||
|
|
f3b3c9ff6a | ||
|
|
7d394dcff2 | ||
|
|
ff11388009 | ||
|
|
b492fece6c | ||
|
|
5394f1dee9 | ||
|
|
e742371d15 | ||
|
|
d03ee006fc | ||
|
|
897d76c4a2 | ||
|
|
349dd12161 | ||
|
|
d84e6c84f5 | ||
|
|
dfcdf8871c | ||
|
|
7122962dc8 | ||
|
|
6432928b7d | ||
|
|
ed1d6e59b5 | ||
|
|
8b2d85aee5 | ||
|
|
392d63fe57 | ||
|
|
1c086b057a | ||
|
|
6bbe55a46c | ||
|
|
7a269efcbc | ||
|
|
06bd6db601 | ||
|
|
3dc9d3a420 | ||
|
|
91ba503700 | ||
|
|
28d27dca5c | ||
|
|
e33265b58d | ||
|
|
22fcb04773 | ||
|
|
f9f67873ad | ||
|
|
b1d345f165 | ||
|
|
1c6a32b684 | ||
|
|
55ac2dd1bb | ||
|
|
997dce288d | ||
|
|
4d745d3600 | ||
|
|
dbd1080f5c | ||
|
|
76963d8109 | ||
|
|
6b106c1b38 | ||
|
|
0016cc59af | ||
|
|
8b9d0f7b19 | ||
|
|
3a4b01cf6f | ||
|
|
15acb9d204 | ||
|
|
21fa96f78f | ||
|
|
fe4e11d9c1 | ||
|
|
d22d5fcfc3 | ||
|
|
cdca4a8585 | ||
|
|
46552785f5 | ||
|
|
816c62979a | ||
|
|
ca164c2a24 | ||
|
|
bf3c6f95eb | ||
|
|
f07f2e77f6 | ||
|
|
50fdbd896c | ||
|
|
bab7bd20cd | ||
|
|
0678908fd9 | ||
|
|
9d29776e8e | ||
|
|
140a220340 | ||
|
|
731e607666 | ||
|
|
97ee66465d | ||
|
|
a0050fedd3 | ||
|
|
89e5001bad | ||
|
|
056fb154a8 | ||
|
|
3edc2b80cf | ||
|
|
a1745cd02e | ||
|
|
1c0f9b64ca | ||
|
|
7d6a518f30 | ||
|
|
9f2fcebc24 | ||
|
|
91295f50b0 | ||
|
|
68bf97f52c | ||
|
|
363048e68e | ||
|
|
9c20c0b889 | ||
|
|
50891e5dd7 | ||
|
|
f393a95501 | ||
|
|
a68dd6d2f7 | ||
|
|
dadf6708ab | ||
|
|
7a86c78896 | ||
|
|
81688399c0 | ||
|
|
1e28a2e5d4 | ||
|
|
c5bb259555 | ||
|
|
0d5d75d6ea | ||
|
|
5bae9bbbcc | ||
|
|
a3e681078f | ||
|
|
758228e159 | ||
|
|
1b900a006f | ||
|
|
9b5c5169ef | ||
|
|
e78a55ac6e | ||
|
|
e82cf70399 | ||
|
|
e7d65ee4ae | ||
|
|
1db3669afa | ||
|
|
93e55b7575 | ||
|
|
f850c65b56 | ||
|
|
297348fffe | ||
|
|
07ff6558d1 | ||
|
|
85843efcb0 | ||
|
|
3d4b1c3be5 | ||
|
|
a3f389af5e | ||
|
|
1aeb3c6fd6 | ||
|
|
6ab6c016c0 | ||
|
|
a1961603d7 | ||
|
|
50ac95dec5 | ||
|
|
a16e46cf38 | ||
|
|
ea33b75764 | ||
|
|
31e657d052 | ||
|
|
fe0dfef83c | ||
|
|
bc1a47ff5a | ||
|
|
4e8089dd42 | ||
|
|
6dc9f90a8b | ||
|
|
1aae3ae2b5 | ||
|
|
75436bcce4 | ||
|
|
61df3ef40e | ||
|
|
f45aab27d1 | ||
|
|
f477c46406 | ||
|
|
2af07d7e0d | ||
|
|
df691488a9 | ||
|
|
800e7ae508 | ||
|
|
fcf156293e | ||
|
|
94f44a0eb7 | ||
|
|
1e2c28f67a | ||
|
|
62b45f7ea7 | ||
|
|
f577590ad6 | ||
|
|
0941247f63 | ||
|
|
3170060f37 | ||
|
|
35b384439f | ||
|
|
0d1150d4d2 | ||
|
|
1f68b46575 | ||
|
|
32c5c4d741 | ||
|
|
0cb15121e5 | ||
|
|
808033a01c | ||
|
|
736e0d2e70 | ||
|
|
96741570c5 | ||
|
|
8feb3fee98 | ||
|
|
07e3e44a68 | ||
|
|
d67d405024 | ||
|
|
520836f475 | ||
|
|
6d6bf1044b | ||
|
|
195866f3aa | ||
|
|
10f0be0708 | ||
|
|
721773ef68 | ||
|
|
0d647ffb9a | ||
|
|
b6235e99c8 | ||
|
|
1d0a6af7d7 | ||
|
|
efd7af165c | ||
|
|
3f4ee6d841 | ||
|
|
55c437d980 | ||
|
|
ecfe103c50 | ||
|
|
a282ad7809 | ||
|
|
64176b8d26 | ||
|
|
278fb298b6 | ||
|
|
1d1b88cf05 | ||
|
|
0c50aa7872 | ||
|
|
0bfa01f072 | ||
|
|
3e9594f069 | ||
|
|
a07138680b | ||
|
|
5f6f2f2859 | ||
|
|
e185ba0191 | ||
|
|
3ab0b17379 | ||
|
|
942d97931e | ||
|
|
40809f1d91 | ||
|
|
f6a37186aa | ||
|
|
9522bf3095 | ||
|
|
c3c7387390 | ||
|
|
09fb58c3e9 | ||
|
|
3d33e630ec | ||
|
|
b51916fb2b | ||
|
|
c9ee92cc30 | ||
|
|
0e81416c2f | ||
|
|
6cd7d46208 | ||
|
|
6af6da16b4 | ||
|
|
4c5900373d | ||
|
|
2fd167c446 | ||
|
|
31149aeed9 | ||
|
|
977b87cbf3 | ||
|
|
42ed4ff48a | ||
|
|
060c71f439 | ||
|
|
63527858e7 | ||
|
|
2f4ea9cac7 | ||
|
|
a1f2369306 | ||
|
|
a35c5f79c1 | ||
|
|
d382e15749 | ||
|
|
5b7d513986 | ||
|
|
be083cfd53 | ||
|
|
f9844c284a | ||
|
|
e8065d07b3 | ||
|
|
8a0820ad1e | ||
|
|
8274cc016f | ||
|
|
b88281b458 | ||
|
|
a1cb5eb420 | ||
|
|
d458c4ecc8 | ||
|
|
b6e4f53597 | ||
|
|
4abbf55ee4 | ||
|
|
1fd909cff6 | ||
|
|
7ca53d1073 | ||
|
|
2bda0f700c | ||
|
|
16b2cc49d4 | ||
|
|
e3e67d1098 | ||
|
|
3276e3ec52 | ||
|
|
5e9a79afe8 | ||
|
|
c6912a193c | ||
|
|
47083e6be1 | ||
|
|
ca78cc5c3c | ||
|
|
76db305ffa | ||
|
|
5d2ef4786b | ||
|
|
9953a5ed06 | ||
|
|
dd194d41be | ||
|
|
8168cf82c5 | ||
|
|
e2d6e39168 | ||
|
|
a340bc4da3 | ||
|
|
4bcb0e17f8 | ||
|
|
25a51df894 | ||
|
|
f9c6ffcdaa | ||
|
|
b76c54ceac | ||
|
|
4be7772d53 | ||
|
|
cbc70a8ff3 | ||
|
|
dd8af0ad8c | ||
|
|
00541e6cc1 | ||
|
|
a8eec60c9d | ||
|
|
7bb319b6d6 | ||
|
|
50a5a2de9b | ||
|
|
dbe5946d10 | ||
|
|
d5caac5d3b | ||
|
|
487c5e22ce | ||
|
|
6efd63a292 | ||
|
|
f31dc3c054 | ||
|
|
c60be3a467 | ||
|
|
44b4e71c05 | ||
|
|
5ebd035b1c | ||
|
|
d50514f8bc | ||
|
|
7da2183080 | ||
|
|
a417ac2716 | ||
|
|
a89e662721 | ||
|
|
72aac6e551 | ||
|
|
4b1e4eecfb | ||
|
|
8e452f8b6d | ||
|
|
7e6db89eff | ||
|
|
16214e666b | ||
|
|
2b25ce237f | ||
|
|
f0a9955447 | ||
|
|
d0439296fe | ||
|
|
e2c2bdb65b | ||
|
|
bc3fdb0f80 | ||
|
|
186b2ada36 | ||
|
|
577125f345 | ||
|
|
687dd8a05f | ||
|
|
81861c6121 | ||
|
|
302462f48c | ||
|
|
d132f55830 | ||
|
|
6bbd64e59a | ||
|
|
290c4e1f2e | ||
|
|
1112616514 | ||
|
|
7fddbca4b7 | ||
|
|
692841478c | ||
|
|
23232b9830 | ||
|
|
b886566b25 | ||
|
|
2c56d60678 | ||
|
|
a0c8127ecf | ||
|
|
05f61df59e | ||
|
|
a0b80ad41a | ||
|
|
9e7cb708bf | ||
|
|
95d97c59d7 | ||
|
|
a75f3e1f8e | ||
|
|
d09d30544f | ||
|
|
1ad4006819 | ||
|
|
43d904d20b | ||
|
|
5339f8efdc | ||
|
|
b273bfb10e | ||
|
|
244e82722d | ||
|
|
e182d8b964 | ||
|
|
02e610a5f2 | ||
|
|
032bc2d5c4 | ||
|
|
e59db74cad | ||
|
|
fbe9ad6582 | ||
|
|
87da542758 | ||
|
|
b2317ada1f | ||
|
|
336aee7fda | ||
|
|
9e7468d723 | ||
|
|
f05ee13206 | ||
|
|
8b3b46b724 | ||
|
|
80e53f209d | ||
|
|
82f29cdc70 | ||
|
|
93d6505f85 | ||
|
|
2b7afd3272 | ||
|
|
6d4e1f6c2e | ||
|
|
2b579eb0d3 | ||
|
|
c0f323b05a | ||
|
|
791121fa06 | ||
|
|
f25d4463f5 | ||
|
|
f0bcb27beb | ||
|
|
00099a5e40 | ||
|
|
7c251157ed | ||
|
|
ec6b389d75 | ||
|
|
f38430d632 | ||
|
|
266f28883a | ||
|
|
cc3c2533fa | ||
|
|
f8162b34f2 | ||
|
|
3ff5b36d29 | ||
|
|
1fa736c6d8 | ||
|
|
309877bf76 | ||
|
|
a50b20a397 | ||
|
|
de5489ae9a | ||
|
|
12e74aa38b | ||
|
|
94eccc6c14 | ||
|
|
80ec66b47c | ||
|
|
9fffcfaea3 | ||
|
|
f481676c81 | ||
|
|
76a42b28f3 | ||
|
|
ad26e48408 | ||
|
|
0bab97e02f | ||
|
|
2413457323 | ||
|
|
585fd87ad6 | ||
|
|
ec5161e848 | ||
|
|
0ec54daaff | ||
|
|
bfcd05206f | ||
|
|
ddf10ed137 | ||
|
|
3ed1bebb7d | ||
|
|
b4d1c0e053 | ||
|
|
68f58fb37d | ||
|
|
f9923f4592 | ||
|
|
29ae088a3d | ||
|
|
dd553b9439 | ||
|
|
451f2d30e4 | ||
|
|
463d85e479 | ||
|
|
2c52795822 | ||
|
|
4f37a36619 | ||
|
|
5aaba98c57 | ||
|
|
a98b69859c | ||
|
|
734a36de06 | ||
|
|
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 | ||
|
|
b02944a3b2 | ||
|
|
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 | ||
|
|
6878abe2a2 | ||
|
|
ec1c81e3ed | ||
|
|
56a5b6ec89 | ||
|
|
af478d3799 | ||
|
|
c2d40051d4 | ||
|
|
47824426c6 | ||
|
|
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 | ||
|
|
4ded288c5d | ||
|
|
a060335bbc | ||
|
|
5a8d944397 | ||
|
|
0b70a5c315 | ||
|
|
91cded3b71 | ||
|
|
84112dc85b | ||
|
|
b1b947ae7f | ||
|
|
1b035f8657 | ||
|
|
9d50f4d651 | ||
|
|
c06a6dc988 | ||
|
|
f198ca2b77 | ||
|
|
9cfc766889 | ||
|
|
5ef1e40403 | ||
|
|
c9e6835d7b | ||
|
|
604cea00f6 | ||
|
|
b4782da1d1 | ||
|
|
d5504043c5 | ||
|
|
81ebbcad70 | ||
|
|
92e9dc6ee1 | ||
|
|
5e8b617625 | ||
|
|
d123ca6063 | ||
|
|
2cbe17151d | ||
|
|
95bd615718 | ||
|
|
8e8c4ff497 | ||
|
|
5eddcc1660 | ||
|
|
0ee8b75b54 | ||
|
|
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 | ||
|
|
cd4863b974 | ||
|
|
d006df8d7c | ||
|
|
1ebd639e36 |
19
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,7 +1,16 @@
|
|||||||
|
**Description:**
|
||||||
|
|
||||||
|
Check first that your problem is not listed in our wiki section:
|
||||||
|
* https://github.com/Radarr/Radarr/wiki/Common-Problems
|
||||||
|
* https://github.com/Radarr/Radarr/wiki/FAQ
|
||||||
|
|
||||||
|
Provide a description of the feature request or bug here, the more details the better.
|
||||||
|
Please also try to include the following if you are reporting a bug
|
||||||
|
|
||||||
|
**Radarr Version:**
|
||||||
|
|
||||||
|
**Logs:**
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
Visit our [Discord server](https://discord.gg/NWYch8M) for support or longer discussions.
|
||||||
When possible include a log!
|
|
||||||
|
|
||||||
Please use our [Discord server](https://discord.gg/NWYch8M) for support or longer discussions.
|
|
||||||
|
|||||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -2,13 +2,11 @@
|
|||||||
YES | NO
|
YES | NO
|
||||||
|
|
||||||
#### Description
|
#### Description
|
||||||
A few sentences describing the overall goals of the pull request's commits.
|
|
||||||
|
|
||||||
#### Todos
|
#### Todos
|
||||||
- [ ] Tests
|
- [ ] Tests
|
||||||
- [ ] Documentation
|
|
||||||
|
|
||||||
|
|
||||||
#### Issues Fixed or Closed by this PR
|
#### Issues Fixed or Closed by this PR
|
||||||
|
|
||||||
*
|
* #
|
||||||
|
|||||||
26
.gitignore
vendored
@@ -101,16 +101,21 @@ App_Data/*.ldf
|
|||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
_TeamCity*
|
_TeamCity*
|
||||||
|
|
||||||
# Sonarr
|
# Radarr
|
||||||
config.xml
|
Backups/
|
||||||
nzbdrone.log*txt
|
logs/
|
||||||
|
MediaCover/
|
||||||
UpdateLogs/
|
UpdateLogs/
|
||||||
|
xdg/
|
||||||
|
config.xml
|
||||||
|
logs.db*
|
||||||
|
nzbdrone.db*
|
||||||
|
nzbdrone.pid
|
||||||
*workspace.xml
|
*workspace.xml
|
||||||
*.test-cache
|
*.test-cache
|
||||||
*.userprefs
|
*.userprefs
|
||||||
*/test-results/*
|
*/test-results/*
|
||||||
src/UI/.idea/*
|
src/UI/.idea/*
|
||||||
*log.txt
|
|
||||||
node_modules/
|
node_modules/
|
||||||
_output*
|
_output*
|
||||||
_rawPackage/
|
_rawPackage/
|
||||||
@@ -122,23 +127,26 @@ setup/Output/
|
|||||||
|
|
||||||
UI.Phantom/
|
UI.Phantom/
|
||||||
|
|
||||||
#VS outout folders
|
# VS outout folders
|
||||||
bin
|
bin
|
||||||
obj
|
obj
|
||||||
output/*
|
output/*
|
||||||
|
|
||||||
#Packages
|
# Packages
|
||||||
Radarr_*/
|
Radarr_*/
|
||||||
Radarr_*.zip
|
Radarr_*.zip
|
||||||
Radarr_*.gz
|
Radarr_*.gz
|
||||||
|
|
||||||
#OS X metadata files
|
# macOS metadata files
|
||||||
._*
|
._*
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
_start
|
_start
|
||||||
_temp_*/**/*
|
_temp_*/**/*
|
||||||
|
|
||||||
#AppVeyor
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# AppVeyor
|
||||||
/tools-cake/
|
/tools-cake/
|
||||||
/_artifacts/
|
/_artifacts/
|
||||||
|
|||||||
1
.idea/Sonarr.iml
generated
@@ -20,6 +20,5 @@
|
|||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="Sonarr node_modules" level="project" />
|
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</module>
|
||||||
2
.idea/jsLibraryMappings.xml
generated
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="JavaScriptLibraryMappings">
|
<component name="JavaScriptLibraryMappings">
|
||||||
<includedPredefinedLibrary name="ECMAScript 6" />
|
<excludedPredefinedLibrary name="Radarr/node_modules" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
14
.idea/libraries/Sonarr_node_modules.xml
generated
@@ -1,14 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Sonarr node_modules" type="javaScript">
|
|
||||||
<properties>
|
|
||||||
<option name="frameworkName" value="node_modules" />
|
|
||||||
<sourceFilesUrls>
|
|
||||||
<item url="file://$PROJECT_DIR$/node_modules" />
|
|
||||||
</sourceFilesUrls>
|
|
||||||
</properties>
|
|
||||||
<CLASSES>
|
|
||||||
<root url="file://$PROJECT_DIR$/node_modules" />
|
|
||||||
</CLASSES>
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
10
.travis.yml
@@ -1,12 +1,14 @@
|
|||||||
language: csharp
|
language: csharp
|
||||||
solution: src/NzbDrone.sln
|
solution: src/NzbDrone.sln
|
||||||
script: # the following commands are just examples, use whatever your build process requires
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- nodejs
|
||||||
|
# - npm apparently not needed anymore.
|
||||||
|
script:
|
||||||
- ./build.sh
|
- ./build.sh
|
||||||
- chmod +x test.sh
|
- chmod +x test.sh
|
||||||
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
# - ./test.sh Linux Unit Takes far too long, maybe even crashes travis :/
|
||||||
install:
|
|
||||||
- sudo apt-get install nodejs
|
|
||||||
- sudo apt-get install npm
|
|
||||||
after_success:
|
after_success:
|
||||||
- chmod +x package.sh
|
- chmod +x package.sh
|
||||||
- ./package.sh
|
- ./package.sh
|
||||||
|
|||||||
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.
|
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. Definitions ##
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# How to Contribute #
|
# 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 ##
|
## Documentation ##
|
||||||
Setup guides, FAQ, the more information we have on the wiki the better.
|
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 ###
|
### 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)*
|
2. Clone (develop branch) *you may need pull in submodules separately if you client doesn't clone them automatically (CurlSharp)*
|
||||||
3. Run `npm install`
|
3. Run `npm install`
|
||||||
4. Run `npm start` - Used to compile the UI components and copy them.
|
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
|
5. Compile in Visual Studio
|
||||||
|
|
||||||
### Contributing Code ###
|
### 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)
|
- 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 Sonarr's develop branch, don't merge
|
- Rebase from Radarr's develop branch, don't merge
|
||||||
- Make meaningful commits, or squash them
|
- 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
|
- 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
|
- Reach out to us on the forums or on IRC if you have any questions
|
||||||
|
|||||||
BIN
Logo/1024.png
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 44 KiB |
BIN
Logo/128.png
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 5.0 KiB |
BIN
Logo/16.png
|
Before Width: | Height: | Size: 811 B After Width: | Height: | Size: 605 B |
BIN
Logo/256.png
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 10 KiB |
BIN
Logo/32.png
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
Logo/400.png
|
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 16 KiB |
BIN
Logo/48.png
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 2.0 KiB |
BIN
Logo/512.png
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 21 KiB |
BIN
Logo/64.png
|
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 2.6 KiB |
BIN
Logo/800.png
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 34 KiB |
597
Logo/Radarr.svg
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 31 KiB |
BIN
Logo/Thumbs.db
BIN
Logo/text256.png
Normal file
|
After Width: | Height: | Size: 28 KiB |
121
README.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="/Logo/text256.png" alt="Radarr">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
Radarr is an __independent__ fork of [Sonarr](https://github.com/Sonarr/Sonarr) reworked for automatically downloading movies via Usenet and BitTorrent.
|
||||||
|
|
||||||
|
The project was inspired by other Usenet/BitTorrent movie downloaders such as CouchPotato.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
[](https://github.com/Radarr/Radarr/wiki/Installation)
|
||||||
|
[](https://github.com/Radarr/Radarr/wiki/Docker)
|
||||||
|
[](https://github.com/Radarr/Radarr/wiki/Setup-Guide)
|
||||||
|
[](https://github.com/Radarr/Radarr/wiki/FAQ)
|
||||||
|
|
||||||
|
* [Install Radarr for your desired OS](https://github.com/Radarr/Radarr/wiki/Installation) *or* use [Docker](https://github.com/Radarr/Radarr/wiki/Docker)
|
||||||
|
* *For Linux users*, run `radarr` and *optionally* have [Radarr start automatically](https://github.com/Radarr/Radarr/wiki/Autostart-on-Linux)
|
||||||
|
* Connect to the UI through <http://localhost:7878> or <http://your-ip:7878> in your web browser
|
||||||
|
* See the [Setup Guide](https://github.com/Radarr/Radarr/wiki/Setup-Guide) for further configuration
|
||||||
|
|
||||||
|
## 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/hotio/radarr)
|
||||||
|
[](https://store.docker.com/community/images/lsioarmhf/radarr)
|
||||||
|
[](https://store.docker.com/community/images/lsioarmhf/radarr-aarch64)
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
[](https://discord.gg/AD3UP37)
|
||||||
|
[](https://www.reddit.com/r/radarr)
|
||||||
|
[](http://feathub.com/Radarr/Radarr)
|
||||||
|
[](https://github.com/Radarr/Radarr/issues)
|
||||||
|
[](https://github.com/Radarr/Radarr/wiki)
|
||||||
|
|
||||||
|
## 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) |
|
||||||
|
|
||||||
|
**This project works independently of Sonarr and will not interfere with it.**
|
||||||
|
|
||||||
|
Radarr is currently undergoing rapid development and pull requests are actively added into the repository.
|
||||||
|
|
||||||
|
## 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
|
||||||
|
* Torznab Indexer now supports Movies (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
||||||
|
* Scanning PreDB to know when a new release is available
|
||||||
|
* Importing movies from various online sources, such as IMDb Watchlists (A complete list can be found [here](https://github.com/Radarr/Radarr/issues/114))
|
||||||
|
* Full integration with Kodi, Plex (notification, library update)
|
||||||
|
* And a beautiful UI
|
||||||
|
|
||||||
|
### Planned Features
|
||||||
|
|
||||||
|
* Downloading Metadata such as trailers or subtitles (\*)
|
||||||
|
* Adding metadata such as posters and information for Kodi and others to use (\*)
|
||||||
|
* Dynamically renaming folders with quality info, etc. (\*)
|
||||||
|
* Supporting custom folder structures, such as all movie files in one folder (\*)
|
||||||
|
* Supporting multiple editions per movies (waiting on The Movie Database to finish their implementation)
|
||||||
|
* Supporting collections of movies, such as James Bond
|
||||||
|
|
||||||
|
**Note:** All features marked with (\*) are set to be in the first release of Radarr.
|
||||||
|
|
||||||
|
#### [Feature Requests](http://feathub.com/Radarr/Radarr)
|
||||||
|
|
||||||
|
## Configuring the 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
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
* [GNU GPL v3](http://www.gnu.org/licenses/gpl.html)
|
||||||
|
* Copyright 2010-2017
|
||||||
41
appveyor.yml
@@ -1,9 +1,5 @@
|
|||||||
version: '0.2.0.{build}'
|
version: '0.2.0.{build}'
|
||||||
|
|
||||||
branches:
|
|
||||||
only:
|
|
||||||
- develop
|
|
||||||
|
|
||||||
assembly_info:
|
assembly_info:
|
||||||
patch: true
|
patch: true
|
||||||
file: 'src\NzbDrone.Common\Properties\SharedAssemblyInfo.cs'
|
file: 'src\NzbDrone.Common\Properties\SharedAssemblyInfo.cs'
|
||||||
@@ -20,19 +16,38 @@ install:
|
|||||||
build_script:
|
build_script:
|
||||||
- ps: ./build-appveyor.ps1
|
- ps: ./build-appveyor.ps1
|
||||||
|
|
||||||
test: off
|
# test: off
|
||||||
# test:
|
test:
|
||||||
# assemblies:
|
assemblies:
|
||||||
# - '_tests\*Test.dll'
|
- '_tests\*Test.dll'
|
||||||
# categories:
|
categories:
|
||||||
# except:
|
except:
|
||||||
# - IntegrationTest
|
- IntegrationTest
|
||||||
# - AutomationTest
|
- AutomationTest
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: '_artifacts\*.zip'
|
- path: '_artifacts\*.zip'
|
||||||
|
- path: '_artifacts\*.exe'
|
||||||
- path: '_artifacts\*.tar.gz'
|
- path: '_artifacts\*.tar.gz'
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
- '%USERPROFILE%\.nuget\packages'
|
- '%USERPROFILE%\.nuget\packages'
|
||||||
- node_modules
|
- node_modules
|
||||||
|
|
||||||
|
pull_requests:
|
||||||
|
do_not_increment_build_number: true
|
||||||
|
|
||||||
|
on_failure:
|
||||||
|
- ps: Get-ChildItem .\_artifacts\*.zip | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
- ps: Get-ChildItem .\_artifacts\*.exe | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
- ps: Get-ChildItem .\_artifacts\*.tar.gz | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
|
||||||
|
only_commits:
|
||||||
|
files:
|
||||||
|
- src/
|
||||||
|
- osx/
|
||||||
|
- gulp/
|
||||||
|
- logo/
|
||||||
|
- setup/
|
||||||
|
- appveyor.yml
|
||||||
|
- build-appveyor.cake
|
||||||
|
|||||||
@@ -104,11 +104,13 @@ Task("Compile").Does(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Task("Gulp").Does(() => {
|
Task("Gulp").Does(() => {
|
||||||
Npm
|
NpmInstall(new NpmInstallSettings {
|
||||||
.WithLogLevel(NpmLogLevel.Silent)
|
LogLevel = NpmLogLevel.Silent,
|
||||||
.FromPath(".")
|
WorkingDirectory = "./",
|
||||||
.Install()
|
Production = true
|
||||||
.RunScript("build");
|
});
|
||||||
|
|
||||||
|
NpmRunScript("build");
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("PackageMono").Does(() => {
|
Task("PackageMono").Does(() => {
|
||||||
@@ -166,8 +168,14 @@ Task("PackageOsx").Does(() => {
|
|||||||
// Adding MediaInfo dylib
|
// Adding MediaInfo dylib
|
||||||
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
|
CopyFiles(sourceFolder + "/Libraries/MediaInfo/*.dylib", outputFolderOsx);
|
||||||
|
|
||||||
|
// Chmod as executable
|
||||||
|
StartProcess(@"C:\cygwin64\bin\chmod.exe", new ProcessSettings()
|
||||||
|
.WithArguments(args => args
|
||||||
|
.Append("+x")
|
||||||
|
.Append(outputFolderOsx + "/Radarr")));
|
||||||
|
|
||||||
// Adding Startup script
|
// Adding Startup script
|
||||||
CopyFile("./osx/Sonarr", outputFolderOsx + "/Sonarr");
|
CopyFile("./osx/Radarr", outputFolderOsx + "/Radarr");
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("PackageOsxApp").Does(() => {
|
Task("PackageOsxApp").Does(() => {
|
||||||
@@ -264,6 +272,13 @@ Task("ArtifactsWindows").Does(() => {
|
|||||||
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
|
CopyDirectory(outputFolder, artifactsFolderWindows + "/Radarr");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Task("ArtifactsWindowsInstaller").Does(() => {
|
||||||
|
InnoSetup("./setup/nzbdrone.iss", new InnoSetupSettings {
|
||||||
|
OutputDirectory = artifactsFolder,
|
||||||
|
ToolPath = "./setup/inno/ISCC.exe"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Task("ArtifactsLinux").Does(() => {
|
Task("ArtifactsLinux").Does(() => {
|
||||||
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
|
CopyDirectory(outputFolderMono, artifactsFolderLinux + "/Radarr");
|
||||||
});
|
});
|
||||||
@@ -280,7 +295,7 @@ Task("CompressArtifacts").Does(() => {
|
|||||||
var prefix = "";
|
var prefix = "";
|
||||||
|
|
||||||
if (AppVeyor.IsRunningOnAppVeyor) {
|
if (AppVeyor.IsRunningOnAppVeyor) {
|
||||||
prefix += AppVeyor.Environment.Repository.Branch + ".";
|
prefix += AppVeyor.Environment.Repository.Branch.Replace("/", "-") + ".";
|
||||||
prefix += AppVeyor.Environment.Build.Version + ".";
|
prefix += AppVeyor.Environment.Build.Version + ".";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,6 +308,7 @@ Task("CompressArtifacts").Does(() => {
|
|||||||
Task("Artifacts")
|
Task("Artifacts")
|
||||||
.IsDependentOn("CleanArtifacts")
|
.IsDependentOn("CleanArtifacts")
|
||||||
.IsDependentOn("ArtifactsWindows")
|
.IsDependentOn("ArtifactsWindows")
|
||||||
|
.IsDependentOn("ArtifactsWindowsInstaller")
|
||||||
.IsDependentOn("ArtifactsLinux")
|
.IsDependentOn("ArtifactsLinux")
|
||||||
.IsDependentOn("ArtifactsOsx")
|
.IsDependentOn("ArtifactsOsx")
|
||||||
.IsDependentOn("ArtifactsOsxApp")
|
.IsDependentOn("ArtifactsOsxApp")
|
||||||
@@ -300,4 +316,4 @@ Task("Artifacts")
|
|||||||
|
|
||||||
// Run
|
// Run
|
||||||
RunTarget("Build");
|
RunTarget("Build");
|
||||||
RunTarget("Artifacts");
|
RunTarget("Artifacts");
|
||||||
|
|||||||
6
build.sh
@@ -181,7 +181,7 @@ PackageOsx()
|
|||||||
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderOsx
|
cp $sourceFolder/Libraries/MediaInfo/*.dylib $outputFolderOsx
|
||||||
|
|
||||||
echo "Adding Startup script"
|
echo "Adding Startup script"
|
||||||
cp ./osx/Sonarr $outputFolderOsx
|
cp ./osx/Radarr $outputFolderOsx
|
||||||
|
|
||||||
echo "##teamcity[progressFinish 'Creating OS X Package']"
|
echo "##teamcity[progressFinish 'Creating OS X Package']"
|
||||||
}
|
}
|
||||||
@@ -208,9 +208,9 @@ PackageTests()
|
|||||||
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
|
find $sourceFolder -path $testSearchPattern -exec cp -r -u -T "{}" $testPackageFolder \;
|
||||||
|
|
||||||
if [ $runtime = "dotnet" ] ; then
|
if [ $runtime = "dotnet" ] ; then
|
||||||
$nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder
|
$nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
|
||||||
else
|
else
|
||||||
mono $nuget install NUnit.ConsoleRunner -Version 3.2.0 -Output $testPackageFolder
|
mono $nuget install NUnit.Runners -Version 3.2.1 -Output $testPackageFolder
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cp $outputFolder/*.dll $testPackageFolder
|
cp $outputFolder/*.dll $testPackageFolder
|
||||||
|
|||||||
44
create_test_cases.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
input1 = """Prometheus.Special.Edition.Fan Edit.2012..BRRip.x264.AAC-m2g
|
||||||
|
Star Wars Episode IV - A New Hope (Despecialized) 1999.mkv
|
||||||
|
Prometheus.(Special.Edition.Remastered).2012.[Bluray-1080p].mkv
|
||||||
|
Prometheus Extended 2012
|
||||||
|
Prometheus Extended Directors Cut Fan Edit 2012
|
||||||
|
Prometheus Director's Cut 2012
|
||||||
|
Prometheus Directors Cut 2012
|
||||||
|
Prometheus.(Extended.Theatrical.Version.IMAX).BluRay.1080p.2012.asdf
|
||||||
|
2001 A Space Odyssey Director's Cut (1968).mkv
|
||||||
|
2001: A Space Odyssey (Extended Directors Cut FanEdit) Bluray 1080p 1968
|
||||||
|
A Fake Movie 2035 Directors 2012.mkv
|
||||||
|
Blade Runner Director's Cut 2049.mkv
|
||||||
|
Prometheus 50th Anniversary Edition 2012.mkv
|
||||||
|
Movie 2in1 2012.mkv
|
||||||
|
Movie IMAX 2012.mkv"""
|
||||||
|
|
||||||
|
output1 = """Special.Edition.Fan Edit BRRip.x264.AAC-m2g
|
||||||
|
Despecialized mkv
|
||||||
|
Special.Edition.Remastered Bluray-1080p].mkv
|
||||||
|
Extended mkv
|
||||||
|
Extended Directors Cut Fan Edit mkv
|
||||||
|
Director's Cut mkv
|
||||||
|
Directors Cut mkv
|
||||||
|
Extended.Theatrical.Version.IMAX asdf
|
||||||
|
Director's Cut mkv
|
||||||
|
Extended Directors Cut FanEdit mkv
|
||||||
|
Directors mkv
|
||||||
|
Director's Cut mkv
|
||||||
|
50th Anniversary Edition mkv
|
||||||
|
2in1 mkv
|
||||||
|
IMAX mkv"""
|
||||||
|
|
||||||
|
inputs = input1.split("\n")
|
||||||
|
outputs = output1.split("\n")
|
||||||
|
real_o = []
|
||||||
|
for output in outputs:
|
||||||
|
real_o.append(output.split(" ")[0].replace(".", " ").strip())
|
||||||
|
|
||||||
|
count = 0
|
||||||
|
|
||||||
|
for inp in inputs:
|
||||||
|
o = real_o[count]
|
||||||
|
print "[TestCase(\"{0}\", \"{1}\")]".format(inp, o)
|
||||||
|
count += 1
|
||||||
@@ -25,7 +25,7 @@ gulp.task('copyHtml', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('copyContent', function () {
|
gulp.task('copyContent', function () {
|
||||||
return gulp.src([paths.src.content + '**/*.*', '!**/*.less'])
|
return gulp.src([paths.src.content + '**/*.*', '!**/*.less', '!**/*.css'])
|
||||||
.pipe(gulp.dest(paths.dest.content))
|
.pipe(gulp.dest(paths.dest.content))
|
||||||
.pipe(livereload());
|
.pipe(livereload());
|
||||||
});
|
});
|
||||||
|
|||||||
11
gulp/less.js
@@ -5,7 +5,7 @@ var postcss = require('gulp-postcss');
|
|||||||
var sourcemaps = require('gulp-sourcemaps');
|
var sourcemaps = require('gulp-sourcemaps');
|
||||||
var autoprefixer = require('autoprefixer-core');
|
var autoprefixer = require('autoprefixer-core');
|
||||||
var livereload = require('gulp-livereload');
|
var livereload = require('gulp-livereload');
|
||||||
|
var cleancss = require('gulp-clean-css');
|
||||||
var print = require('gulp-print');
|
var print = require('gulp-print');
|
||||||
var paths = require('./paths');
|
var paths = require('./paths');
|
||||||
var errorHandler = require('./errorHandler');
|
var errorHandler = require('./errorHandler');
|
||||||
@@ -16,6 +16,10 @@ gulp.task('less', function() {
|
|||||||
paths.src.content + 'bootstrap.less',
|
paths.src.content + 'bootstrap.less',
|
||||||
paths.src.content + 'theme.less',
|
paths.src.content + 'theme.less',
|
||||||
paths.src.content + 'overrides.less',
|
paths.src.content + 'overrides.less',
|
||||||
|
paths.src.content + 'bootstrap.toggle-switch.css',
|
||||||
|
paths.src.content + 'fullcalendar.css',
|
||||||
|
paths.src.content + 'Messenger/messenger.css',
|
||||||
|
paths.src.content + 'Messenger/messenger.flat.css',
|
||||||
paths.src.root + 'Series/series.less',
|
paths.src.root + 'Series/series.less',
|
||||||
paths.src.root + 'Activity/activity.less',
|
paths.src.root + 'Activity/activity.less',
|
||||||
paths.src.root + 'AddSeries/addSeries.less',
|
paths.src.root + 'AddSeries/addSeries.less',
|
||||||
@@ -36,12 +40,13 @@ gulp.task('less', function() {
|
|||||||
.pipe(sourcemaps.init())
|
.pipe(sourcemaps.init())
|
||||||
.pipe(less({
|
.pipe(less({
|
||||||
dumpLineNumbers : 'false',
|
dumpLineNumbers : 'false',
|
||||||
compress : true,
|
compress : false,
|
||||||
yuicompress : true,
|
yuicompress : false,
|
||||||
ieCompat : true,
|
ieCompat : true,
|
||||||
strictImports : true
|
strictImports : true
|
||||||
}))
|
}))
|
||||||
.pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
|
.pipe(postcss([ autoprefixer({ browsers: ['last 2 versions'] }) ]))
|
||||||
|
.pipe(cleancss())
|
||||||
.on('error', errorHandler.onError)
|
.on('error', errorHandler.onError)
|
||||||
.pipe(sourcemaps.write(paths.dest.content))
|
.pipe(sourcemaps.write(paths.dest.content))
|
||||||
.pipe(gulp.dest(paths.dest.content))
|
.pipe(gulp.dest(paths.dest.content))
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ DIR=$(cd "$(dirname "$0")"; pwd)
|
|||||||
|
|
||||||
#change these values to match your app
|
#change these values to match your app
|
||||||
EXE_PATH="$DIR/Radarr.exe"
|
EXE_PATH="$DIR/Radarr.exe"
|
||||||
APPNAME="Sonarr"
|
APPNAME="Radarr"
|
||||||
|
|
||||||
#set up environment
|
#set up environment
|
||||||
if [[ -x '/opt/local/bin/mono' ]]; then
|
if [[ -x '/opt/local/bin/mono' ]]; then
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>Sonarr</string>
|
<string>Radarr</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>radarr.icns</string>
|
<string>radarr.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
"del": "1.2.0",
|
"del": "1.2.0",
|
||||||
"gulp": "3.9.0",
|
"gulp": "3.9.0",
|
||||||
"gulp-cached": "1.1.0",
|
"gulp-cached": "1.1.0",
|
||||||
|
"gulp-clean-css": "^3.0.4",
|
||||||
"gulp-concat": "2.6.0",
|
"gulp-concat": "2.6.0",
|
||||||
"gulp-declare": "0.3.0",
|
"gulp-declare": "0.3.0",
|
||||||
"gulp-handlebars": "3.0.1",
|
"gulp-handlebars": "3.0.1",
|
||||||
@@ -40,6 +41,7 @@
|
|||||||
"run-sequence": "1.1.1",
|
"run-sequence": "1.1.1",
|
||||||
"streamqueue": "1.1.0",
|
"streamqueue": "1.1.0",
|
||||||
"tar.gz": "0.1.1",
|
"tar.gz": "0.1.1",
|
||||||
|
"url-search-params": "^0.6.1",
|
||||||
"webpack": "1.12.0",
|
"webpack": "1.12.0",
|
||||||
"webpack-stream": "2.1.0"
|
"webpack-stream": "2.1.0"
|
||||||
}
|
}
|
||||||
|
|||||||
67
package.sh
@@ -23,20 +23,19 @@ if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then
|
|||||||
DAY="`date +%d`"
|
DAY="`date +%d`"
|
||||||
else
|
else
|
||||||
VERSION=$1
|
VERSION=$1
|
||||||
|
BRANCH=$2
|
||||||
|
BRANCH=${BRANCH#refs\/heads\/}
|
||||||
|
BRANCH=${BRANCH//\//-}
|
||||||
fi
|
fi
|
||||||
outputFolder='./_output'
|
outputFolder='./_output'
|
||||||
outputFolderMono='./_output_mono'
|
outputFolderMono='./_output_mono'
|
||||||
outputFolderOsx='./_output_osx'
|
outputFolderOsx='./_output_osx'
|
||||||
outputFolderOsxApp='./_output_osx_app'
|
outputFolderOsxApp='./_output_osx_app'
|
||||||
|
|
||||||
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
tr -d "\r" < $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr > $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2
|
||||||
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr
|
rm $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr
|
||||||
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2
|
chmod +x $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2
|
||||||
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Sonarr >& error.log
|
mv $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr2 $outputFolderOsxApp/Radarr.app/Contents/MacOS/Radarr >& error.log
|
||||||
|
|
||||||
cp -r $outputFolder/ Radarr_Windows_$VERSION
|
|
||||||
cp -r $outputFolderMono/ Radarr_Mono_$VERSION
|
|
||||||
cp -r $outputFolderOsxApp/ Radarr_OSX_$VERSION
|
|
||||||
|
|
||||||
if [ $runtime = "dotnet" ] ; then
|
if [ $runtime = "dotnet" ] ; then
|
||||||
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
|
./7za.exe a Radarr_Windows_$VERSION.zip ./Radarr_Windows_$VERSION/*
|
||||||
@@ -44,25 +43,35 @@ if [ $runtime = "dotnet" ] ; then
|
|||||||
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
|
./7za.exe a -ttar -so Radarr_OSX_$VERSION.tar ./_output_osx/* | ./7za.exe a -si Radarr_OSX_$VERSION.tar.gz
|
||||||
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
|
./7za.exe a -ttar -so Radarr_OSX_App_$VERSION.tar ./_output_osx_app/* | ./7za.exe a -si Radarr_OSX_App_$VERSION.tar.gz
|
||||||
else
|
else
|
||||||
zip -r Radarr_Windows_$VERSION.zip Radarr_Windows_$VERSION/* >& /dev/null
|
cp -r $outputFolder/ Radarr
|
||||||
zip -r Radarr_Mono_$VERSION.zip Radarr_Mono_$VERSION/* >& /dev/null #TODO update for tar.gz
|
zip -r Radarr.$BRANCH.$VERSION.windows.zip Radarr
|
||||||
zip -r Radarr_OSX_$VERSION_App.zip Radarr_OSX_$VERSION/* >& /dev/null
|
rm -rf Radarr
|
||||||
|
cp -r $outputFolderMono/ Radarr
|
||||||
|
tar -zcvf Radarr.$BRANCH.$VERSION.linux.tar.gz Radarr
|
||||||
|
rm -rf Radarr
|
||||||
|
cp -r $outputFolderOsx/ Radarr
|
||||||
|
tar -zcvf Radarr.$BRANCH.$VERSION.osx.tar.gz Radarr
|
||||||
|
rm -rf Radarr
|
||||||
|
#TODO update for tar.gz
|
||||||
|
|
||||||
|
cd _output_osx_app/
|
||||||
|
zip -r ../Radarr.$BRANCH.$VERSION.osx-app.zip *
|
||||||
fi
|
fi
|
||||||
ftp -n ftp.leonardogalli.ch << END_SCRIPT
|
# ftp -n ftp.leonardogalli.ch << END_SCRIPT
|
||||||
passive
|
# passive
|
||||||
quote USER $FTP_USER
|
# quote USER $FTP_USER
|
||||||
quote PASS $FTP_PASS
|
# quote PASS $FTP_PASS
|
||||||
mkdir builds
|
# mkdir builds
|
||||||
cd builds
|
# cd builds
|
||||||
mkdir $YEAR
|
# mkdir $YEAR
|
||||||
cd $YEAR
|
# cd $YEAR
|
||||||
mkdir $MONTH
|
# mkdir $MONTH
|
||||||
cd $MONTH
|
# cd $MONTH
|
||||||
mkdir $DAY
|
# mkdir $DAY
|
||||||
cd $DAY
|
# cd $DAY
|
||||||
binary
|
# binary
|
||||||
put Radarr_Windows_$VERSION.zip
|
# put Radarr_Windows_$VERSION.zip
|
||||||
put Radarr_Mono_$VERSION.zip
|
# put Radarr_Mono_$VERSION.zip
|
||||||
put Radarr_OSX_$VERSION.zip
|
# put Radarr_OSX_$VERSION.zip
|
||||||
quit
|
# quit
|
||||||
END_SCRIPT
|
# END_SCRIPT
|
||||||
|
|||||||
76
readme.md
@@ -1,76 +0,0 @@
|
|||||||
# Radarr
|
|
||||||
|
|
||||||
| Service | Master | Develop |
|
|
||||||
|----------|:---------------------------:|:----------------------------:|
|
|
||||||
| AppVeyor | [](https://ci.appveyor.com/project/galli-leo/Radarr) | [](https://ci.appveyor.com/project/galli-leo/Radarr) |
|
|
||||||
| Travis | [](https://travis-ci.org/galli-leo/Radarr) | [](https://travis-ci.org/galli-leo/Radarr) |
|
|
||||||
|
|
||||||
This fork of Sonarr aims to turn it into something like Couchpotato.
|
|
||||||
|
|
||||||
## Currently working:
|
|
||||||
* Adding new movies
|
|
||||||
* Manually searching for releases of movies.
|
|
||||||
* Automatically searching for releases.
|
|
||||||
* Automatically importing downloaded movies.
|
|
||||||
* Recognizing Special Editions, Director's Cut, etc.
|
|
||||||
* Identifying releases with hardcoded subs.
|
|
||||||
* Rarbg.to, Torznab and Newznab Indexer.
|
|
||||||
* QBittorrent and Deluge download client (Other clients are coming)
|
|
||||||
* New TorrentPotato Indexer (Works well with [Jackett](https://github.com/Jackett/Jackett))
|
|
||||||
|
|
||||||
## Planned Features:
|
|
||||||
* Scanning PreDB to know when a new release is available.
|
|
||||||
* Fixing the other Indexers and download clients.
|
|
||||||
* Importing of Sonarr config.
|
|
||||||
|
|
||||||
## Download
|
|
||||||
The latest precompiled binary versions can be found here: https://github.com/galli-leo/Radarr/releases.
|
|
||||||
|
|
||||||
For more up to date versions (but also sometimes broken), daily builds can be found here:
|
|
||||||
* [OSX](https://leonardogalli.ch/radarr/builds/latest.php?os=osx)
|
|
||||||
* [Windows](https://leonardogalli.ch/radarr/builds/latest.php?os=windows)
|
|
||||||
* [Linux](https://leonardogalli.ch/radarr/builds/latest.php?os=mono)
|
|
||||||
|
|
||||||
## Major Features Include: ##
|
|
||||||
|
|
||||||
* Support for major platforms: Windows, Linux, OSX, Raspberry Pi, etc.
|
|
||||||
* Can watch for better quality of the movies you have and do an upgrade.
|
|
||||||
* 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.
|
|
||||||
* Full integration with XBMC, Plex (notification, library update, metadata).
|
|
||||||
* 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) or Mono
|
|
||||||
- [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 or run the build.sh script, if Mono is installed.
|
|
||||||
- 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/)
|
|
||||||
@@ -1,35 +1,35 @@
|
|||||||
; Script generated by the Inno Setup Script Wizard.
|
; Script generated by the Inno Setup Script Wizard.
|
||||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||||
|
|
||||||
#define AppName "Sonarr"
|
#define AppName "Radarr"
|
||||||
#define AppPublisher "Team Sonarr"
|
#define AppPublisher "Team Radarr"
|
||||||
#define AppURL "https://sonarr.tv/"
|
#define AppURL "https://radarr.video/"
|
||||||
#define ForumsURL "https://forums.sonarr.tv/"
|
#define ForumsURL "https://github.com/Radarr/Radarr/issues"
|
||||||
#define AppExeName "NzbDrone.exe"
|
#define AppExeName "Radarr.exe"
|
||||||
#define BuildNumber "2.0"
|
#define BuildNumber "2.0"
|
||||||
#define BuildNumber GetEnv('BUILD_NUMBER')
|
#define BuildVersion GetEnv('APPVEYOR_BUILD_VERSION')
|
||||||
#define BranchName GetEnv('branch')
|
#define BranchName GetEnv('APPVEYOR_REPO_BRANCH')
|
||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
; NOTE: The value of AppId uniquely identifies this application.
|
; NOTE: The value of AppId uniquely identifies this application.
|
||||||
; Do not use the same AppId value in installers for other applications.
|
; Do not use the same AppId value in installers for other applications.
|
||||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||||
AppId={{56C1065D-3523-4025-B76D-6F73F67F7F71}
|
AppId={{56C1065D-3523-4025-B76D-6F73F67F7F82}
|
||||||
AppName={#AppName}
|
AppName={#AppName}
|
||||||
AppVersion=2.0
|
AppVersion=0.2
|
||||||
AppPublisher={#AppPublisher}
|
AppPublisher={#AppPublisher}
|
||||||
AppPublisherURL={#AppURL}
|
AppPublisherURL={#AppURL}
|
||||||
AppSupportURL={#ForumsURL}
|
AppSupportURL={#ForumsURL}
|
||||||
AppUpdatesURL={#AppURL}
|
AppUpdatesURL={#AppURL}
|
||||||
DefaultDirName={commonappdata}\NzbDrone\bin
|
DefaultDirName={commonappdata}\Radarr\bin
|
||||||
DisableDirPage=yes
|
DisableDirPage=yes
|
||||||
DefaultGroupName={#AppName}
|
DefaultGroupName={#AppName}
|
||||||
DisableProgramGroupPage=yes
|
DisableProgramGroupPage=yes
|
||||||
OutputBaseFilename=NzbDrone.{#BranchName}.{#BuildNumber}
|
OutputBaseFilename=Radarr.{#BranchName}.{#BuildVersion}.installer
|
||||||
SolidCompression=yes
|
SolidCompression=yes
|
||||||
AppCopyright=Creative Commons 3.0 License
|
AppCopyright=Creative Commons 3.0 License
|
||||||
AllowUNCPath=False
|
AllowUNCPath=False
|
||||||
UninstallDisplayIcon={app}\NzbDrone.exe
|
UninstallDisplayIcon={app}\Radarr.exe
|
||||||
DisableReadyPage=True
|
DisableReadyPage=True
|
||||||
CompressionThreads=2
|
CompressionThreads=2
|
||||||
Compression=lzma2/normal
|
Compression=lzma2/normal
|
||||||
@@ -44,7 +44,7 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
|
|||||||
Name: "windowsService"; Description: "Install as a Windows Service"
|
Name: "windowsService"; Description: "Install as a Windows Service"
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
Source: "..\_output\NzbDrone.exe"; DestDir: "{app}"; Flags: ignoreversion
|
Source: "..\_output\Radarr.exe"; DestDir: "{app}"; Flags: ignoreversion
|
||||||
Source: "..\_output\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
Source: "..\_output\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
|
||||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||||
|
|
||||||
@@ -53,8 +53,8 @@ Name: "{group}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
|||||||
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
Name: "{commondesktop}\{#AppName}"; Filename: "{app}\{#AppExeName}"; Parameters: "/icon"
|
||||||
|
|
||||||
[Run]
|
[Run]
|
||||||
Filename: "{app}\nzbdrone.console.exe"; Parameters: "/u"; Flags: waituntilterminated;
|
Filename: "{app}\radarr.console.exe"; Parameters: "/u"; Flags: waituntilterminated;
|
||||||
Filename: "{app}\nzbdrone.console.exe"; Parameters: "/i"; Flags: waituntilterminated; Tasks: windowsService
|
Filename: "{app}\radarr.console.exe"; Parameters: "/i"; Flags: waituntilterminated; Tasks: windowsService
|
||||||
|
|
||||||
[UninstallRun]
|
[UninstallRun]
|
||||||
Filename: "{app}\nzbdrone.console.exe"; Parameters: "/u"; Flags: waituntilterminated skipifdoesntexist
|
Filename: "{app}\radarr.console.exe"; Parameters: "/u"; Flags: waituntilterminated skipifdoesntexist
|
||||||
|
|||||||
1
src/.idea/.idea.NzbDrone/.idea/.name
generated
Normal file
@@ -0,0 +1 @@
|
|||||||
|
NzbDrone
|
||||||
6
src/.idea/.idea.NzbDrone/.idea/contentModel.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="RiderRiderContentModelStore">
|
||||||
|
<excludedPaths />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
8
src/.idea/.idea.NzbDrone/.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.NzbDrone/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.NzbDrone/riderModule.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
103
src/.idea/.idea.NzbDrone/riderModule.iml
generated
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="RIDER_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$/../../../Logo/1024.png">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../Logo/1024.png" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<content url="file://$MODULE_DIR$/../../../Logo/64.png">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../../Logo/64.png" isTestSource="false" />
|
||||||
|
</content>
|
||||||
|
<content url="file://$MODULE_DIR$/../..">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../.nuget/NuGet.exe" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Common/CommonAssemblyInfo.cs" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Common/CommonVersionInfo.cs" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Common/GlobalSuppressions.cs" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/MediaInfo/libmediainfo.0.dylib" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/MediaInfo/MediaInfo.dll" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/Sqlite/libsqlite3.0.dylib" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Libraries/Sqlite/sqlite3.dll" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../LogentriesCore" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../LogentriesNLog" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Marr.Data" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../MonoTorrent" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Api" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Common" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Console" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Core" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Host" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.SignalR" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Update" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceInstall" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceUninstall" isTestSource="false" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../ExternalModules/CurlSharp/CurlSharp/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesCore/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesCore/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesNLog/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../LogentriesNLog/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../Marr.Data/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Core/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../Microsoft.AspNet.SignalR.Owin/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../MonoTorrent/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Api/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.App.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Automation.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Common/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Console/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Core/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Host/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Integration.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Libraries.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Mono/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.SignalR/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Common/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Test.Dummy/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Update/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test/bin" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows.Test/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone.Windows/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../NzbDrone/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceInstall/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../ServiceHelpers/ServiceUninstall/obj" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../_ReSharper.Caches/ReSharperHost8.NzbDrone.00" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/../../packages" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
@@ -33,12 +33,12 @@ namespace NzbDrone.Api.Authentication
|
|||||||
{
|
{
|
||||||
if (_configFileProvider.AuthenticationMethod == AuthenticationType.Forms)
|
if (_configFileProvider.AuthenticationMethod == AuthenticationType.Forms)
|
||||||
{
|
{
|
||||||
RegisterFormsAuth(pipelines);
|
RegisterFormsAuth(pipelines);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (_configFileProvider.AuthenticationMethod == AuthenticationType.Basic)
|
else if (_configFileProvider.AuthenticationMethod == AuthenticationType.Basic)
|
||||||
{
|
{
|
||||||
pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(_authenticationService, "Sonarr"));
|
pipelines.EnableBasicAuthentication(new BasicAuthenticationConfiguration(_authenticationService, "Radarr"));
|
||||||
}
|
}
|
||||||
|
|
||||||
pipelines.BeforeRequest.AddItemToEndOfPipeline((Func<NancyContext, Response>) RequiresAuthentication);
|
pipelines.BeforeRequest.AddItemToEndOfPipeline((Func<NancyContext, Response>) RequiresAuthentication);
|
||||||
@@ -64,10 +64,13 @@ namespace NzbDrone.Api.Authentication
|
|||||||
new DefaultHmacProvider(new PassphraseKeyGenerator(_configService.HmacPassphrase, Encoding.ASCII.GetBytes(_configService.HmacSalt)))
|
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
|
FormsAuthentication.Enable(pipelines, new FormsAuthenticationConfiguration
|
||||||
{
|
{
|
||||||
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
RedirectUrl = _configFileProvider.UrlBase + "/login",
|
||||||
UserMapper = _authenticationService,
|
UserMapper = _authenticationService,
|
||||||
|
Path = _configFileProvider.UrlBase,
|
||||||
CryptographyConfiguration = cryptographyConfiguration
|
CryptographyConfiguration = cryptographyConfiguration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
@@ -11,13 +12,14 @@ namespace NzbDrone.Api.Blacklist
|
|||||||
{
|
{
|
||||||
public int SeriesId { get; set; }
|
public int SeriesId { get; set; }
|
||||||
public List<int> EpisodeIds { get; set; }
|
public List<int> EpisodeIds { get; set; }
|
||||||
|
public int MovieId { get; set; }
|
||||||
public string SourceTitle { get; set; }
|
public string SourceTitle { get; set; }
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
public DateTime Date { get; set; }
|
public DateTime Date { get; set; }
|
||||||
public DownloadProtocol Protocol { get; set; }
|
public DownloadProtocol Protocol { get; set; }
|
||||||
public string Indexer { get; set; }
|
public string Indexer { get; set; }
|
||||||
public string Message { get; set; }
|
public string Message { get; set; }
|
||||||
|
public MovieResource Movie { get; set; }
|
||||||
public SeriesResource Series { get; set; }
|
public SeriesResource Series { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +32,7 @@ namespace NzbDrone.Api.Blacklist
|
|||||||
return new BlacklistResource
|
return new BlacklistResource
|
||||||
{
|
{
|
||||||
Id = model.Id,
|
Id = model.Id,
|
||||||
|
MovieId = model.MovieId,
|
||||||
SeriesId = model.SeriesId,
|
SeriesId = model.SeriesId,
|
||||||
EpisodeIds = model.EpisodeIds,
|
EpisodeIds = model.EpisodeIds,
|
||||||
SourceTitle = model.SourceTitle,
|
SourceTitle = model.SourceTitle,
|
||||||
@@ -39,7 +41,7 @@ namespace NzbDrone.Api.Blacklist
|
|||||||
Protocol = model.Protocol,
|
Protocol = model.Protocol,
|
||||||
Indexer = model.Indexer,
|
Indexer = model.Indexer,
|
||||||
Message = model.Message,
|
Message = model.Message,
|
||||||
|
Movie = model.Movie.ToResource(),
|
||||||
Series = model.Series.ToResource()
|
Series = model.Series.ToResource()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,17 +16,18 @@ namespace NzbDrone.Api.Calendar
|
|||||||
{
|
{
|
||||||
public class CalendarFeedModule : NzbDroneFeedModule
|
public class CalendarFeedModule : NzbDroneFeedModule
|
||||||
{
|
{
|
||||||
private readonly IEpisodeService _episodeService;
|
private readonly IMovieService _movieService;
|
||||||
private readonly ITagService _tagService;
|
private readonly ITagService _tagService;
|
||||||
|
|
||||||
public CalendarFeedModule(IEpisodeService episodeService, ITagService tagService)
|
public CalendarFeedModule(IMovieService movieService, ITagService tagService)
|
||||||
: base("calendar")
|
: base("calendar")
|
||||||
{
|
{
|
||||||
_episodeService = episodeService;
|
_movieService = movieService;
|
||||||
_tagService = tagService;
|
_tagService = tagService;
|
||||||
|
|
||||||
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
|
Get["/NzbDrone.ics"] = options => GetCalendarFeed();
|
||||||
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
Get["/Sonarr.ics"] = options => GetCalendarFeed();
|
||||||
|
Get["/Radarr.ics"] = options => GetCalendarFeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Response GetCalendarFeed()
|
private Response GetCalendarFeed()
|
||||||
@@ -36,7 +37,7 @@ namespace NzbDrone.Api.Calendar
|
|||||||
var start = DateTime.Today.AddDays(-pastDays);
|
var start = DateTime.Today.AddDays(-pastDays);
|
||||||
var end = DateTime.Today.AddDays(futureDays);
|
var end = DateTime.Today.AddDays(futureDays);
|
||||||
var unmonitored = false;
|
var unmonitored = false;
|
||||||
var premiersOnly = false;
|
//var premiersOnly = false;
|
||||||
var tags = new List<int>();
|
var tags = new List<int>();
|
||||||
|
|
||||||
// TODO: Remove start/end parameters in v3, they don't work well for iCal
|
// TODO: Remove start/end parameters in v3, they don't work well for iCal
|
||||||
@@ -45,7 +46,7 @@ namespace NzbDrone.Api.Calendar
|
|||||||
var queryPastDays = Request.Query.PastDays;
|
var queryPastDays = Request.Query.PastDays;
|
||||||
var queryFutureDays = Request.Query.FutureDays;
|
var queryFutureDays = Request.Query.FutureDays;
|
||||||
var queryUnmonitored = Request.Query.Unmonitored;
|
var queryUnmonitored = Request.Query.Unmonitored;
|
||||||
var queryPremiersOnly = Request.Query.PremiersOnly;
|
// var queryPremiersOnly = Request.Query.PremiersOnly;
|
||||||
var queryTags = Request.Query.Tags;
|
var queryTags = Request.Query.Tags;
|
||||||
|
|
||||||
if (queryStart.HasValue) start = DateTime.Parse(queryStart.Value);
|
if (queryStart.HasValue) start = DateTime.Parse(queryStart.Value);
|
||||||
@@ -68,10 +69,10 @@ namespace NzbDrone.Api.Calendar
|
|||||||
unmonitored = bool.Parse(queryUnmonitored.Value);
|
unmonitored = bool.Parse(queryUnmonitored.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (queryPremiersOnly.HasValue)
|
//if (queryPremiersOnly.HasValue)
|
||||||
{
|
//{
|
||||||
premiersOnly = bool.Parse(queryPremiersOnly.Value);
|
// premiersOnly = bool.Parse(queryPremiersOnly.Value);
|
||||||
}
|
//}
|
||||||
|
|
||||||
if (queryTags.HasValue)
|
if (queryTags.HasValue)
|
||||||
{
|
{
|
||||||
@@ -79,43 +80,56 @@ namespace NzbDrone.Api.Calendar
|
|||||||
tags.AddRange(tagInput.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
|
tags.AddRange(tagInput.Split(',').Select(_tagService.GetTag).Select(t => t.Id));
|
||||||
}
|
}
|
||||||
|
|
||||||
var episodes = _episodeService.EpisodesBetweenDates(start, end, unmonitored);
|
var movies = _movieService.GetMoviesBetweenDates(start, end, unmonitored);
|
||||||
var calendar = new Ical.Net.Calendar
|
var calendar = new Ical.Net.Calendar
|
||||||
{
|
{
|
||||||
ProductId = "-//sonarr.tv//Sonarr//EN"
|
ProductId = "-//radarr.video//Radarr//EN"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
foreach (var movie in movies.OrderBy(v => v.Added))
|
||||||
|
|
||||||
foreach (var episode in episodes.OrderBy(v => v.AirDateUtc.Value))
|
|
||||||
{
|
{
|
||||||
if (premiersOnly && (episode.SeasonNumber == 0 || episode.EpisodeNumber != 1))
|
if (tags.Any() && tags.None(movie.Tags.Contains))
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tags.Any() && tags.None(episode.Series.Tags.Contains))
|
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var occurrence = calendar.Create<Event>();
|
var occurrence = calendar.Create<Event>();
|
||||||
occurrence.Uid = "NzbDrone_episode_" + episode.Id;
|
occurrence.Uid = "NzbDrone_movie_" + movie.Id;
|
||||||
occurrence.Status = episode.HasFile ? EventStatus.Confirmed : EventStatus.Tentative;
|
occurrence.Status = movie.HasFile ? EventStatus.Confirmed : EventStatus.Tentative;
|
||||||
occurrence.Start = new CalDateTime(episode.AirDateUtc.Value) { HasTime = true };
|
|
||||||
occurrence.End = new CalDateTime(episode.AirDateUtc.Value.AddMinutes(episode.Series.Runtime)) { HasTime = true };
|
|
||||||
occurrence.Description = episode.Overview;
|
|
||||||
occurrence.Categories = new List<string>() { episode.Series.Network };
|
|
||||||
|
|
||||||
switch (episode.Series.SeriesType)
|
switch (movie.Status)
|
||||||
{
|
{
|
||||||
case SeriesTypes.Daily:
|
case MovieStatusType.PreDB:
|
||||||
occurrence.Summary = $"{episode.Series.Title} - {episode.Title}";
|
if (movie.PhysicalRelease != null)
|
||||||
|
{
|
||||||
|
occurrence.Start = new CalDateTime(movie.PhysicalRelease.Value) { HasTime = true };
|
||||||
|
occurrence.End = new CalDateTime(movie.PhysicalRelease.Value.AddMinutes(movie.Runtime)) { HasTime = true };
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case MovieStatusType.InCinemas:
|
||||||
|
if (movie.InCinemas != null)
|
||||||
|
{
|
||||||
|
occurrence.Start = new CalDateTime(movie.InCinemas.Value) { HasTime = true };
|
||||||
|
occurrence.End = new CalDateTime(movie.InCinemas.Value.AddMinutes(movie.Runtime)) { HasTime = true };
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MovieStatusType.Announced:
|
||||||
|
continue; // no date
|
||||||
default:
|
default:
|
||||||
occurrence.Summary =$"{episode.Series.Title} - {episode.SeasonNumber}x{episode.EpisodeNumber:00} - {episode.Title}";
|
if (movie.PhysicalRelease != null)
|
||||||
|
{
|
||||||
|
occurrence.Start = new CalDateTime(movie.PhysicalRelease.Value) { HasTime = true };
|
||||||
|
occurrence.End = new CalDateTime(movie.PhysicalRelease.Value.AddMinutes(movie.Runtime)) { HasTime = true };
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
occurrence.Description = movie.Overview;
|
||||||
|
occurrence.Categories = new List<string>() { movie.Studio };
|
||||||
|
|
||||||
|
occurrence.Summary = $"{movie.Title}";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var serializer = (IStringSerializer) new SerializerFactory().Build(calendar.GetType(), new SerializationContext());
|
var serializer = (IStringSerializer) new SerializerFactory().Build(calendar.GetType(), new SerializationContext());
|
||||||
|
|||||||
@@ -1,25 +1,41 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Nancy;
|
||||||
using NzbDrone.Api.Episodes;
|
using NzbDrone.Api.Episodes;
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
|
using NzbDrone.Api.Series;
|
||||||
|
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.DecisionEngine;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Calendar
|
namespace NzbDrone.Api.Calendar
|
||||||
{
|
{
|
||||||
public class CalendarModule : EpisodeModuleWithSignalR
|
public class CalendarModule : MovieModule
|
||||||
{
|
{
|
||||||
public CalendarModule(IEpisodeService episodeService,
|
public CalendarModule(IBroadcastSignalRMessage signalR,
|
||||||
ISeriesService seriesService,
|
IMovieService moviesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IMovieStatisticsService moviesStatisticsService,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
ISceneMappingService sceneMappingService,
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "calendar")
|
IMapCoversToLocal coverMapper)
|
||||||
|
: base(signalR, moviesService, moviesStatisticsService, sceneMappingService, coverMapper, "calendar")
|
||||||
{
|
{
|
||||||
|
|
||||||
GetResourceAll = GetCalendar;
|
GetResourceAll = GetCalendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<EpisodeResource> GetCalendar()
|
private List<MovieResource> GetCalendar()
|
||||||
{
|
{
|
||||||
var start = DateTime.Today;
|
var start = DateTime.Today;
|
||||||
var end = DateTime.Today.AddDays(2);
|
var end = DateTime.Today.AddDays(2);
|
||||||
@@ -33,9 +49,9 @@ namespace NzbDrone.Api.Calendar
|
|||||||
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
|
if (queryEnd.HasValue) end = DateTime.Parse(queryEnd.Value);
|
||||||
if (queryIncludeUnmonitored.HasValue) includeUnmonitored = Convert.ToBoolean(queryIncludeUnmonitored.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NzbDrone.Common.EnsureThat;
|
using NzbDrone.Common.EnsureThat;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
using NzbDrone.Common.Reflection;
|
using NzbDrone.Common.Reflection;
|
||||||
using NzbDrone.Core.Annotations;
|
using NzbDrone.Core.Annotations;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Profiles;
|
||||||
|
|
||||||
namespace NzbDrone.Api.ClientSchema
|
namespace NzbDrone.Api.ClientSchema
|
||||||
{
|
{
|
||||||
@@ -43,7 +46,7 @@ namespace NzbDrone.Api.ClientSchema
|
|||||||
field.Value = value;
|
field.Value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fieldAttribute.Type == FieldType.Select)
|
if (fieldAttribute.Type == FieldType.Select || fieldAttribute.Type == FieldType.Tag)
|
||||||
{
|
{
|
||||||
field.SelectOptions = GetSelectOptions(fieldAttribute.SelectOptions);
|
field.SelectOptions = GetSelectOptions(fieldAttribute.SelectOptions);
|
||||||
}
|
}
|
||||||
@@ -73,14 +76,14 @@ namespace NzbDrone.Api.ClientSchema
|
|||||||
|
|
||||||
if (propertyInfo.PropertyType == typeof(int))
|
if (propertyInfo.PropertyType == typeof(int))
|
||||||
{
|
{
|
||||||
var value = Convert.ToInt32(field.Value);
|
var value = field.Value.ToString().ParseInt32();
|
||||||
propertyInfo.SetValue(target, value, null);
|
propertyInfo.SetValue(target, value ?? 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (propertyInfo.PropertyType == typeof(long))
|
else if (propertyInfo.PropertyType == typeof(long))
|
||||||
{
|
{
|
||||||
var value = Convert.ToInt64(field.Value);
|
var value = field.Value.ToString().ParseInt64();
|
||||||
propertyInfo.SetValue(target, value, null);
|
propertyInfo.SetValue(target, value ?? 0, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (propertyInfo.PropertyType == typeof(int?))
|
else if (propertyInfo.PropertyType == typeof(int?))
|
||||||
@@ -147,10 +150,22 @@ namespace NzbDrone.Api.ClientSchema
|
|||||||
|
|
||||||
private static List<SelectOption> GetSelectOptions(Type selectOptions)
|
private static List<SelectOption> GetSelectOptions(Type selectOptions)
|
||||||
{
|
{
|
||||||
|
if (selectOptions == null || selectOptions == typeof(Profile))
|
||||||
|
{
|
||||||
|
return new List<SelectOption>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectOptions == typeof(Quality))
|
||||||
|
{
|
||||||
|
var qOptions = from Quality q in selectOptions.GetProperties(BindingFlags.Static | BindingFlags.Public)
|
||||||
|
select new SelectOption {Name = q.Name, Value = q.Id};
|
||||||
|
return qOptions.OrderBy(o => o.Value).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
var options = from Enum e in Enum.GetValues(selectOptions)
|
var options = from Enum e in Enum.GetValues(selectOptions)
|
||||||
select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() };
|
select new SelectOption { Value = Convert.ToInt32(e), Name = e.ToString() };
|
||||||
|
|
||||||
return options.OrderBy(o => o.Value).ToList();
|
return options.OrderBy(o => o.Name).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
using NzbDrone.Api.Validation;
|
using NzbDrone.Api.Validation;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
@@ -17,14 +18,17 @@ namespace NzbDrone.Api.Commands
|
|||||||
{
|
{
|
||||||
private readonly IManageCommandQueue _commandQueueManager;
|
private readonly IManageCommandQueue _commandQueueManager;
|
||||||
private readonly IServiceFactory _serviceFactory;
|
private readonly IServiceFactory _serviceFactory;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public CommandModule(IManageCommandQueue commandQueueManager,
|
public CommandModule(IManageCommandQueue commandQueueManager,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster,
|
IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
IServiceFactory serviceFactory)
|
IServiceFactory serviceFactory,
|
||||||
|
Logger logger)
|
||||||
: base(signalRBroadcaster)
|
: base(signalRBroadcaster)
|
||||||
{
|
{
|
||||||
_commandQueueManager = commandQueueManager;
|
_commandQueueManager = commandQueueManager;
|
||||||
_serviceFactory = serviceFactory;
|
_serviceFactory = serviceFactory;
|
||||||
|
_logger = logger;
|
||||||
|
|
||||||
GetResourceById = GetCommand;
|
GetResourceById = GetCommand;
|
||||||
CreateResource = StartCommand;
|
CreateResource = StartCommand;
|
||||||
@@ -41,7 +45,13 @@ namespace NzbDrone.Api.Commands
|
|||||||
private int StartCommand(CommandResource commandResource)
|
private int StartCommand(CommandResource commandResource)
|
||||||
{
|
{
|
||||||
var commandType = _serviceFactory.GetImplementations(typeof(Command))
|
var commandType = _serviceFactory.GetImplementations(typeof(Command))
|
||||||
.Single(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
|
.SingleOrDefault(c => c.Name.Replace("Command", "").Equals(commandResource.Name, StringComparison.InvariantCultureIgnoreCase));
|
||||||
|
|
||||||
|
if (commandType == null)
|
||||||
|
{
|
||||||
|
_logger.Error("Found no matching command for {0}", commandResource.Name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
dynamic command = Request.Body.FromJson(commandType);
|
dynamic command = Request.Body.FromJson(commandType);
|
||||||
command.Trigger = CommandTrigger.Manual;
|
command.Trigger = CommandTrigger.Manual;
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ namespace NzbDrone.Api.Config
|
|||||||
MappedNetworkDriveValidator mappedNetworkDriveValidator)
|
MappedNetworkDriveValidator mappedNetworkDriveValidator)
|
||||||
: base(configService)
|
: base(configService)
|
||||||
{
|
{
|
||||||
SharedValidator.RuleFor(c => c.DownloadedEpisodesFolder)
|
SharedValidator.RuleFor(c => c.DownloadedMoviesFolder)
|
||||||
.Cascade(CascadeMode.StopOnFirstFailure)
|
.Cascade(CascadeMode.StopOnFirstFailure)
|
||||||
.IsValidPath()
|
.IsValidPath()
|
||||||
.SetValidator(rootFolderValidator)
|
.SetValidator(rootFolderValidator)
|
||||||
.SetValidator(mappedNetworkDriveValidator)
|
.SetValidator(mappedNetworkDriveValidator)
|
||||||
.SetValidator(pathExistsValidator)
|
.SetValidator(pathExistsValidator)
|
||||||
.When(c => !string.IsNullOrWhiteSpace(c.DownloadedEpisodesFolder));
|
.When(c => !string.IsNullOrWhiteSpace(c.DownloadedMoviesFolder));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override DownloadClientConfigResource ToResource(IConfigService model)
|
protected override DownloadClientConfigResource ToResource(IConfigService model)
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ namespace NzbDrone.Api.Config
|
|||||||
{
|
{
|
||||||
public class DownloadClientConfigResource : RestResource
|
public class DownloadClientConfigResource : RestResource
|
||||||
{
|
{
|
||||||
public string DownloadedEpisodesFolder { get; set; }
|
public string DownloadedMoviesFolder { get; set; }
|
||||||
public string DownloadClientWorkingFolders { get; set; }
|
public string DownloadClientWorkingFolders { get; set; }
|
||||||
public int DownloadedEpisodesScanInterval { get; set; }
|
public int DownloadedMoviesScanInterval { get; set; }
|
||||||
|
|
||||||
public bool EnableCompletedDownloadHandling { get; set; }
|
public bool EnableCompletedDownloadHandling { get; set; }
|
||||||
public bool RemoveCompletedDownloads { get; set; }
|
public bool RemoveCompletedDownloads { get; set; }
|
||||||
@@ -22,9 +22,9 @@ namespace NzbDrone.Api.Config
|
|||||||
{
|
{
|
||||||
return new DownloadClientConfigResource
|
return new DownloadClientConfigResource
|
||||||
{
|
{
|
||||||
DownloadedEpisodesFolder = model.DownloadedEpisodesFolder,
|
DownloadedMoviesFolder = model.DownloadedMoviesFolder,
|
||||||
DownloadClientWorkingFolders = model.DownloadClientWorkingFolders,
|
DownloadClientWorkingFolders = model.DownloadClientWorkingFolders,
|
||||||
DownloadedEpisodesScanInterval = model.DownloadedEpisodesScanInterval,
|
DownloadedMoviesScanInterval = model.DownloadedMoviesScanInterval,
|
||||||
|
|
||||||
EnableCompletedDownloadHandling = model.EnableCompletedDownloadHandling,
|
EnableCompletedDownloadHandling = model.EnableCompletedDownloadHandling,
|
||||||
RemoveCompletedDownloads = model.RemoveCompletedDownloads,
|
RemoveCompletedDownloads = model.RemoveCompletedDownloads,
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Config
|
namespace NzbDrone.Api.Config
|
||||||
{
|
{
|
||||||
@@ -8,6 +9,11 @@ namespace NzbDrone.Api.Config
|
|||||||
public int MinimumAge { get; set; }
|
public int MinimumAge { get; set; }
|
||||||
public int Retention { get; set; }
|
public int Retention { get; set; }
|
||||||
public int RssSyncInterval { get; set; }
|
public int RssSyncInterval { get; set; }
|
||||||
|
public bool PreferIndexerFlags { get; set; }
|
||||||
|
public int AvailabilityDelay { get; set; }
|
||||||
|
public bool AllowHardcodedSubs { get; set; }
|
||||||
|
public string WhitelistedHardcodedSubs { get; set; }
|
||||||
|
public ParsingLeniencyType ParsingLeniency { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class IndexerConfigResourceMapper
|
public static class IndexerConfigResourceMapper
|
||||||
@@ -19,6 +25,11 @@ namespace NzbDrone.Api.Config
|
|||||||
MinimumAge = model.MinimumAge,
|
MinimumAge = model.MinimumAge,
|
||||||
Retention = model.Retention,
|
Retention = model.Retention,
|
||||||
RssSyncInterval = model.RssSyncInterval,
|
RssSyncInterval = model.RssSyncInterval,
|
||||||
|
PreferIndexerFlags = model.PreferIndexerFlags,
|
||||||
|
AvailabilityDelay = model.AvailabilityDelay,
|
||||||
|
AllowHardcodedSubs = model.AllowHardcodedSubs,
|
||||||
|
WhitelistedHardcodedSubs = model.WhitelistedHardcodedSubs,
|
||||||
|
ParsingLeniency = model.ParsingLeniency,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ namespace NzbDrone.Api.Config
|
|||||||
public bool AutoDownloadPropers { get; set; }
|
public bool AutoDownloadPropers { get; set; }
|
||||||
public bool CreateEmptySeriesFolders { get; set; }
|
public bool CreateEmptySeriesFolders { get; set; }
|
||||||
public FileDateType FileDate { get; set; }
|
public FileDateType FileDate { get; set; }
|
||||||
|
public bool AutoRenameFolders { get; set; }
|
||||||
|
public bool PathsDefaultStatic { get; set; }
|
||||||
|
|
||||||
public bool SetPermissionsLinux { get; set; }
|
public bool SetPermissionsLinux { get; set; }
|
||||||
public string FileChmod { get; set; }
|
public string FileChmod { get; set; }
|
||||||
@@ -35,6 +37,8 @@ namespace NzbDrone.Api.Config
|
|||||||
AutoDownloadPropers = model.AutoDownloadPropers,
|
AutoDownloadPropers = model.AutoDownloadPropers,
|
||||||
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
|
CreateEmptySeriesFolders = model.CreateEmptySeriesFolders,
|
||||||
FileDate = model.FileDate,
|
FileDate = model.FileDate,
|
||||||
|
AutoRenameFolders = model.AutoRenameFolders,
|
||||||
|
PathsDefaultStatic = model.PathsDefaultStatic,
|
||||||
|
|
||||||
SetPermissionsLinux = model.SetPermissionsLinux,
|
SetPermissionsLinux = model.SetPermissionsLinux,
|
||||||
FileChmod = model.FileChmod,
|
FileChmod = model.FileChmod,
|
||||||
|
|||||||
@@ -34,11 +34,11 @@ namespace NzbDrone.Api.Config
|
|||||||
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
Get["/samples"] = x => GetExamples(this.Bind<NamingConfigResource>());
|
||||||
|
|
||||||
SharedValidator.RuleFor(c => c.MultiEpisodeStyle).InclusiveBetween(0, 5);
|
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.DailyEpisodeFormat).ValidDailyEpisodeFormat();
|
||||||
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
SharedValidator.RuleFor(c => c.AnimeEpisodeFormat).ValidAnimeEpisodeFormat();
|
||||||
SharedValidator.RuleFor(c => c.SeriesFolderFormat).ValidSeriesFolderFormat();
|
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.StandardMovieFormat).ValidMovieFormat();
|
||||||
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
|
SharedValidator.RuleFor(c => c.MovieFolderFormat).ValidMovieFolderFormat();
|
||||||
}
|
}
|
||||||
|
|||||||
22
src/NzbDrone.Api/Config/NetImportConfigModule.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Api.Validation;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Config
|
||||||
|
{
|
||||||
|
public class NetImportConfigModule : NzbDroneConfigModule<NetImportConfigResource>
|
||||||
|
{
|
||||||
|
|
||||||
|
public NetImportConfigModule(IConfigService configService)
|
||||||
|
: base(configService)
|
||||||
|
{
|
||||||
|
SharedValidator.RuleFor(c => c.NetImportSyncInterval)
|
||||||
|
.IsValidNetImportSyncInterval();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override NetImportConfigResource ToResource(IConfigService model)
|
||||||
|
{
|
||||||
|
return NetImportConfigResourceMapper.ToResource(model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/NzbDrone.Api/Config/NetImportConfigResource.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Config
|
||||||
|
{
|
||||||
|
public class NetImportConfigResource : RestResource
|
||||||
|
{
|
||||||
|
public int NetImportSyncInterval { get; set; }
|
||||||
|
public string ListSyncLevel { get; set; }
|
||||||
|
public string ImportExclusions { get; set; }
|
||||||
|
public string TraktAuthToken { get; set; }
|
||||||
|
public string TraktRefreshToken { get; set; }
|
||||||
|
public int TraktTokenExpiry { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class NetImportConfigResourceMapper
|
||||||
|
{
|
||||||
|
public static NetImportConfigResource ToResource(IConfigService model)
|
||||||
|
{
|
||||||
|
return new NetImportConfigResource
|
||||||
|
{
|
||||||
|
NetImportSyncInterval = model.NetImportSyncInterval,
|
||||||
|
ListSyncLevel = model.ListSyncLevel,
|
||||||
|
ImportExclusions = model.ImportExclusions,
|
||||||
|
TraktAuthToken = model.TraktAuthToken,
|
||||||
|
TraktRefreshToken = model.TraktRefreshToken,
|
||||||
|
TraktTokenExpiry = model.TraktTokenExpiry,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -71,7 +71,7 @@ namespace NzbDrone.Api.EpisodeFiles
|
|||||||
|
|
||||||
private void DeleteEpisodeFile(int id)
|
private void DeleteEpisodeFile(int id)
|
||||||
{
|
{
|
||||||
var episodeFile = _mediaFileService.Get(id);
|
var episodeFile = _mediaFileService.Get(id);
|
||||||
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
var series = _seriesService.GetSeries(episodeFile.SeriesId);
|
||||||
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
var fullPath = Path.Combine(series.Path, episodeFile.RelativePath);
|
||||||
|
|
||||||
|
|||||||
@@ -66,13 +66,9 @@ namespace NzbDrone.Api.Extensions.Pipelines
|
|||||||
private Response LogError(NancyContext context, Exception exception)
|
private Response LogError(NancyContext context, Exception exception)
|
||||||
{
|
{
|
||||||
var response = _errorPipeline.HandleException(context, exception);
|
var response = _errorPipeline.HandleException(context, exception);
|
||||||
|
|
||||||
context.Response = response;
|
context.Response = response;
|
||||||
|
|
||||||
LogEnd(context);
|
LogEnd(context);
|
||||||
|
|
||||||
context.Response = null;
|
context.Response = null;
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,12 +76,9 @@ namespace NzbDrone.Api.Extensions.Pipelines
|
|||||||
{
|
{
|
||||||
if (request.Url.Query.IsNotNullOrWhiteSpace())
|
if (request.Url.Query.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
return string.Concat(request.Url.Path, "?", request.Url.Query);
|
return string.Concat(request.Url.Path, request.Url.Query);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return request.Url.Path;
|
|
||||||
}
|
}
|
||||||
|
return request.Url.Path;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
46
src/NzbDrone.Api/Extensions/Pipelines/UrlBasePipeline.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using Nancy;
|
||||||
|
using Nancy.Bootstrapper;
|
||||||
|
using Nancy.Responses;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Configuration;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Extensions.Pipelines
|
||||||
|
{
|
||||||
|
public class UrlBasePipeline : IRegisterNancyPipeline
|
||||||
|
{
|
||||||
|
private readonly string _urlBase;
|
||||||
|
|
||||||
|
public UrlBasePipeline(IConfigFileProvider configFileProvider)
|
||||||
|
{
|
||||||
|
_urlBase = configFileProvider.UrlBase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Order => 99;
|
||||||
|
|
||||||
|
public void Register(IPipelines pipelines)
|
||||||
|
{
|
||||||
|
if (_urlBase.IsNotNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
pipelines.BeforeRequest.AddItemToStartOfPipeline((Func<NancyContext, Response>) Handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response Handle(NancyContext context)
|
||||||
|
{
|
||||||
|
var basePath = context.Request.Url.BasePath;
|
||||||
|
|
||||||
|
if (basePath.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return new RedirectResponse($"{_urlBase}{context.Request.Path}{context.Request.Url.Query}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_urlBase != basePath)
|
||||||
|
{
|
||||||
|
return new NotFoundResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ namespace NzbDrone.Api.Frontend.Mappers
|
|||||||
|
|
||||||
public override bool CanHandle(string resourceUrl)
|
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy.Responses;
|
using Nancy.Responses;
|
||||||
@@ -38,20 +38,6 @@ namespace NzbDrone.Api.Frontend
|
|||||||
return new NotFoundResponse();
|
return new NotFoundResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Redirect to the subfolder if the request went to the base URL
|
|
||||||
if (path.Equals("/"))
|
|
||||||
{
|
|
||||||
var urlBase = _configFileProvider.UrlBase;
|
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(urlBase))
|
|
||||||
{
|
|
||||||
if (Request.Url.BasePath != urlBase)
|
|
||||||
{
|
|
||||||
return new RedirectResponse(urlBase + "/");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mapper = _requestMappers.SingleOrDefault(m => m.CanHandle(path));
|
var mapper = _requestMappers.SingleOrDefault(m => m.CanHandle(path));
|
||||||
|
|
||||||
if (mapper != null)
|
if (mapper != null)
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using Nancy;
|
using Nancy;
|
||||||
using NzbDrone.Api.Episodes;
|
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
using NzbDrone.Api.Series;
|
|
||||||
using NzbDrone.Api.Movie;
|
using NzbDrone.Api.Movie;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
@@ -32,16 +30,8 @@ namespace NzbDrone.Api.History
|
|||||||
protected HistoryResource MapToResource(Core.History.History model)
|
protected HistoryResource MapToResource(Core.History.History model)
|
||||||
{
|
{
|
||||||
var resource = model.ToResource();
|
var resource = model.ToResource();
|
||||||
|
|
||||||
resource.Series = model.Series.ToResource();
|
|
||||||
resource.Episode = model.Episode.ToResource();
|
|
||||||
resource.Movie = model.Movie.ToResource();
|
resource.Movie = model.Movie.ToResource();
|
||||||
|
|
||||||
if (model.Series != null)
|
|
||||||
{
|
|
||||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Series.Profile.Value, model.Quality);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (model.Movie != null)
|
if (model.Movie != null)
|
||||||
{
|
{
|
||||||
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Movie.Profile.Value, model.Quality);
|
resource.QualityCutoffNotMet = _qualityUpgradableSpecification.CutoffNotMet(model.Movie.Profile.Value, model.Quality);
|
||||||
@@ -52,8 +42,6 @@ namespace NzbDrone.Api.History
|
|||||||
|
|
||||||
private PagingResource<HistoryResource> GetHistory(PagingResource<HistoryResource> pagingResource)
|
private PagingResource<HistoryResource> GetHistory(PagingResource<HistoryResource> pagingResource)
|
||||||
{
|
{
|
||||||
var episodeId = Request.Query.EpisodeId;
|
|
||||||
|
|
||||||
var movieId = Request.Query.MovieId;
|
var movieId = Request.Query.MovieId;
|
||||||
|
|
||||||
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, Core.History.History>("date", SortDirection.Descending);
|
var pagingSpec = pagingResource.MapToPagingSpec<HistoryResource, Core.History.History>("date", SortDirection.Descending);
|
||||||
@@ -64,12 +52,6 @@ namespace NzbDrone.Api.History
|
|||||||
pagingSpec.FilterExpression = v => v.EventType == filterValue;
|
pagingSpec.FilterExpression = v => v.EventType == filterValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (episodeId.HasValue)
|
|
||||||
{
|
|
||||||
int i = (int)episodeId;
|
|
||||||
pagingSpec.FilterExpression = h => h.EpisodeId == i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (movieId.HasValue)
|
if (movieId.HasValue)
|
||||||
{
|
{
|
||||||
int i = (int)movieId;
|
int i = (int)movieId;
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ namespace NzbDrone.Api.Indexers
|
|||||||
|
|
||||||
release.ReleaseWeight = initialWeight;
|
release.ReleaseWeight = initialWeight;
|
||||||
|
|
||||||
if (decision.RemoteEpisode.Series != null)
|
if (decision.RemoteMovie.Movie != null)
|
||||||
{
|
{
|
||||||
release.QualityWeight = decision.RemoteEpisode.Series
|
release.QualityWeight = decision.RemoteMovie.Movie
|
||||||
.Profile.Value
|
.Profile.Value
|
||||||
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 100;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ namespace NzbDrone.Api.Indexers
|
|||||||
public bool DownloadAllowed { get; set; }
|
public bool DownloadAllowed { get; set; }
|
||||||
public int ReleaseWeight { get; set; }
|
public int ReleaseWeight { get; set; }
|
||||||
|
|
||||||
|
public IEnumerable<string> IndexerFlags { get; set; }
|
||||||
|
|
||||||
public string MagnetUrl { get; set; }
|
public string MagnetUrl { get; set; }
|
||||||
public string InfoHash { get; set; }
|
public string InfoHash { get; set; }
|
||||||
@@ -97,7 +98,7 @@ namespace NzbDrone.Api.Indexers
|
|||||||
{
|
{
|
||||||
Guid = releaseInfo.Guid,
|
Guid = releaseInfo.Guid,
|
||||||
Quality = parsedMovieInfo.Quality,
|
Quality = parsedMovieInfo.Quality,
|
||||||
//QualityWeight
|
QualityWeight = parsedMovieInfo.Quality.Quality.Id, //Id kinda hacky for wheight, but what you gonna do? TODO: Fix this shit!
|
||||||
Age = releaseInfo.Age,
|
Age = releaseInfo.Age,
|
||||||
AgeHours = releaseInfo.AgeHours,
|
AgeHours = releaseInfo.AgeHours,
|
||||||
AgeMinutes = releaseInfo.AgeMinutes,
|
AgeMinutes = releaseInfo.AgeMinutes,
|
||||||
@@ -107,8 +108,8 @@ namespace NzbDrone.Api.Indexers
|
|||||||
ReleaseGroup = parsedMovieInfo.ReleaseGroup,
|
ReleaseGroup = parsedMovieInfo.ReleaseGroup,
|
||||||
ReleaseHash = parsedMovieInfo.ReleaseHash,
|
ReleaseHash = parsedMovieInfo.ReleaseHash,
|
||||||
Title = releaseInfo.Title,
|
Title = releaseInfo.Title,
|
||||||
FullSeason = parsedMovieInfo.FullSeason,
|
//FullSeason = parsedMovieInfo.FullSeason,
|
||||||
SeasonNumber = parsedMovieInfo.SeasonNumber,
|
//SeasonNumber = parsedMovieInfo.SeasonNumber,
|
||||||
Language = parsedMovieInfo.Language,
|
Language = parsedMovieInfo.Language,
|
||||||
AirDate = "",
|
AirDate = "",
|
||||||
SeriesTitle = parsedMovieInfo.MovieTitle,
|
SeriesTitle = parsedMovieInfo.MovieTitle,
|
||||||
@@ -132,13 +133,13 @@ namespace NzbDrone.Api.Indexers
|
|||||||
Seeders = torrentInfo.Seeders,
|
Seeders = torrentInfo.Seeders,
|
||||||
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
Leechers = (torrentInfo.Peers.HasValue && torrentInfo.Seeders.HasValue) ? (torrentInfo.Peers.Value - torrentInfo.Seeders.Value) : (int?)null,
|
||||||
Protocol = releaseInfo.DownloadProtocol,
|
Protocol = releaseInfo.DownloadProtocol,
|
||||||
|
IndexerFlags = torrentInfo.IndexerFlags.ToString().Split(new string[] { ", " }, StringSplitOptions.None),
|
||||||
Edition = parsedMovieInfo.Edition,
|
Edition = parsedMovieInfo.Edition,
|
||||||
|
|
||||||
IsDaily = false,
|
IsDaily = false,
|
||||||
IsAbsoluteNumbering = false,
|
IsAbsoluteNumbering = false,
|
||||||
IsPossibleSpecialEpisode = false,
|
IsPossibleSpecialEpisode = false,
|
||||||
Special = parsedMovieInfo.Special,
|
//Special = parsedMovieInfo.Special,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
175
src/NzbDrone.Api/Movies/MovieBulkImportModule.cs
Normal file
@@ -0,0 +1,175 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using NzbDrone.Core.Parser;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using Marr.Data;
|
||||||
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
|
using NzbDrone.Core.RootFolders;
|
||||||
|
using NzbDrone.Common.Cache;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
|
||||||
|
public class UnmappedComparer : IComparer<UnmappedFolder>
|
||||||
|
{
|
||||||
|
public int Compare(UnmappedFolder a, UnmappedFolder b)
|
||||||
|
{
|
||||||
|
return a.Name.CompareTo(b.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MovieBulkImportModule : NzbDroneRestModule<MovieResource>
|
||||||
|
{
|
||||||
|
private readonly ISearchForNewMovie _searchProxy;
|
||||||
|
private readonly IRootFolderService _rootFolderService;
|
||||||
|
private readonly IMakeImportDecision _importDecisionMaker;
|
||||||
|
private readonly IDiskScanService _diskScanService;
|
||||||
|
private readonly ICached<Core.Tv.Movie> _mappedMovies;
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
|
|
||||||
|
public MovieBulkImportModule(ISearchForNewMovie searchProxy, IRootFolderService rootFolderService, IMakeImportDecision importDecisionMaker,
|
||||||
|
IDiskScanService diskScanService, ICacheManager cacheManager, IMovieService movieService)
|
||||||
|
: base("/movies/bulkimport")
|
||||||
|
{
|
||||||
|
_searchProxy = searchProxy;
|
||||||
|
_rootFolderService = rootFolderService;
|
||||||
|
_importDecisionMaker = importDecisionMaker;
|
||||||
|
_diskScanService = diskScanService;
|
||||||
|
_mappedMovies = cacheManager.GetCache<Core.Tv.Movie>(GetType(), "mappedMoviesCache");
|
||||||
|
_movieService = movieService;
|
||||||
|
Get["/"] = x => Search();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Response Search()
|
||||||
|
{
|
||||||
|
if (Request.Query.Id == 0)
|
||||||
|
{
|
||||||
|
//Todo error handling
|
||||||
|
}
|
||||||
|
|
||||||
|
RootFolder rootFolder = _rootFolderService.Get(Request.Query.Id);
|
||||||
|
|
||||||
|
int page = Request.Query.page;
|
||||||
|
int per_page = Request.Query.per_page;
|
||||||
|
|
||||||
|
int min = (page - 1) * per_page;
|
||||||
|
|
||||||
|
int max = page * per_page;
|
||||||
|
|
||||||
|
var unmapped = rootFolder.UnmappedFolders.OrderBy(f => f.Name).ToList();
|
||||||
|
|
||||||
|
int total_count = unmapped.Count;
|
||||||
|
|
||||||
|
if (Request.Query.total_entries.HasValue)
|
||||||
|
{
|
||||||
|
total_count = Request.Query.total_entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
max = total_count >= max ? max : total_count;
|
||||||
|
|
||||||
|
var paged = unmapped.GetRange(min, max-min);
|
||||||
|
|
||||||
|
var mapped = paged.Select(f =>
|
||||||
|
{
|
||||||
|
Core.Tv.Movie m = null;
|
||||||
|
|
||||||
|
var mappedMovie = _mappedMovies.Find(f.Name);
|
||||||
|
|
||||||
|
if (mappedMovie != null)
|
||||||
|
{
|
||||||
|
return mappedMovie;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parsedTitle = Parser.ParseMoviePath(f.Name, false);
|
||||||
|
if (parsedTitle == null)
|
||||||
|
{
|
||||||
|
m = new Core.Tv.Movie
|
||||||
|
{
|
||||||
|
Title = f.Name.Replace(".", " ").Replace("-", " "),
|
||||||
|
Path = f.Path,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m = new Core.Tv.Movie
|
||||||
|
{
|
||||||
|
Title = parsedTitle.MovieTitle,
|
||||||
|
Year = parsedTitle.Year,
|
||||||
|
ImdbId = parsedTitle.ImdbId,
|
||||||
|
Path = f.Path
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var files = _diskScanService.GetVideoFiles(f.Path);
|
||||||
|
|
||||||
|
var decisions = _importDecisionMaker.GetImportDecisions(files.ToList(), m, true);
|
||||||
|
|
||||||
|
var decision = decisions.Where(d => d.Approved && !d.Rejections.Any()).FirstOrDefault();
|
||||||
|
|
||||||
|
if (decision != null)
|
||||||
|
{
|
||||||
|
var local = decision.LocalMovie;
|
||||||
|
|
||||||
|
m.MovieFile = new LazyLoaded<MovieFile>(new MovieFile
|
||||||
|
{
|
||||||
|
Path = local.Path,
|
||||||
|
Edition = local.ParsedMovieInfo.Edition,
|
||||||
|
Quality = local.Quality,
|
||||||
|
MediaInfo = local.MediaInfo,
|
||||||
|
ReleaseGroup = local.ParsedMovieInfo.ReleaseGroup,
|
||||||
|
RelativePath = f.Path.GetRelativePath(local.Path)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
mappedMovie = _searchProxy.MapMovieToTmdbMovie(m);
|
||||||
|
|
||||||
|
if (mappedMovie != null)
|
||||||
|
{
|
||||||
|
mappedMovie.Monitored = true;
|
||||||
|
|
||||||
|
_mappedMovies.Set(f.Name, mappedMovie, TimeSpan.FromDays(2));
|
||||||
|
|
||||||
|
return mappedMovie;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return new PagingResource<MovieResource>
|
||||||
|
{
|
||||||
|
Page = page,
|
||||||
|
PageSize = per_page,
|
||||||
|
SortDirection = SortDirection.Ascending,
|
||||||
|
SortKey = Request.Query.sort_by,
|
||||||
|
TotalRecords = total_count - mapped.Where(m => m == null).Count(),
|
||||||
|
Records = MapToResource(mapped.Where(m => m != null)).ToList()
|
||||||
|
}.AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||||
|
{
|
||||||
|
foreach (var currentMovie in movies)
|
||||||
|
{
|
||||||
|
var resource = currentMovie.ToResource();
|
||||||
|
var poster = currentMovie.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||||
|
if (poster != null)
|
||||||
|
{
|
||||||
|
resource.RemotePoster = poster.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
75
src/NzbDrone.Api/Movies/MovieFileModule.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
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<MovieFileAddedEvent>
|
||||||
|
{
|
||||||
|
private readonly IMediaFileService _mediaFileService;
|
||||||
|
private readonly IRecycleBinProvider _recycleBinProvider;
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public MovieFileModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
|
IMediaFileService mediaFileService,
|
||||||
|
IRecycleBinProvider recycleBinProvider,
|
||||||
|
IMovieService movieService,
|
||||||
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
Logger logger)
|
||||||
|
: base(signalRBroadcaster)
|
||||||
|
{
|
||||||
|
_mediaFileService = mediaFileService;
|
||||||
|
_recycleBinProvider = recycleBinProvider;
|
||||||
|
_movieService = movieService;
|
||||||
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||||
|
_logger = logger;
|
||||||
|
GetResourceById = GetMovieFile;
|
||||||
|
UpdateResource = SetQuality;
|
||||||
|
DeleteResource = DeleteMovieFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private MovieFileResource GetMovieFile(int id)
|
||||||
|
{
|
||||||
|
var movie = _mediaFileService.GetMovie(id);
|
||||||
|
|
||||||
|
return movie.ToResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void SetQuality(MovieFileResource movieFileResource)
|
||||||
|
{
|
||||||
|
var movieFile = _mediaFileService.GetMovie(movieFileResource.Id);
|
||||||
|
movieFile.Quality = movieFileResource.Quality;
|
||||||
|
_mediaFileService.Update(movieFile);
|
||||||
|
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, movieFile.Id);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void DeleteMovieFile(int id)
|
||||||
|
{
|
||||||
|
var movieFile = _mediaFileService.GetMovie(id);
|
||||||
|
var movie = _movieService.GetMovie(movieFile.MovieId);
|
||||||
|
var fullPath = Path.Combine(movie.Path, movieFile.RelativePath);
|
||||||
|
|
||||||
|
_logger.Info("Deleting movie file: {0}", fullPath);
|
||||||
|
_recycleBinProvider.DeleteFile(fullPath);
|
||||||
|
_mediaFileService.Delete(movieFile, DeleteMediaFileReason.Manual);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(MovieFileAddedEvent message)
|
||||||
|
{
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, message.MovieFile.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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
78
src/NzbDrone.Api/Movies/MovieModuleWithSignalR.cs
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
using NzbDrone.Api.Movie;
|
||||||
|
using NzbDrone.Core.Datastore.Events;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.SignalR;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movies
|
||||||
|
{
|
||||||
|
public abstract class MovieModuleWithSignalR : NzbDroneRestModuleWithSignalR<MovieResource, Core.Tv.Movie>,
|
||||||
|
IHandle<MovieGrabbedEvent>,
|
||||||
|
IHandle<MovieDownloadedEvent>
|
||||||
|
{
|
||||||
|
protected readonly IMovieService _movieService;
|
||||||
|
protected readonly IQualityUpgradableSpecification _qualityUpgradableSpecification;
|
||||||
|
|
||||||
|
protected MovieModuleWithSignalR(IMovieService movieService,
|
||||||
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
|
: base(signalRBroadcaster)
|
||||||
|
{
|
||||||
|
_movieService = movieService;
|
||||||
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||||
|
|
||||||
|
GetResourceById = GetMovie;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MovieModuleWithSignalR(IMovieService movieService,
|
||||||
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
|
string resource)
|
||||||
|
: base(signalRBroadcaster, resource)
|
||||||
|
{
|
||||||
|
_movieService = movieService;
|
||||||
|
_qualityUpgradableSpecification = qualityUpgradableSpecification;
|
||||||
|
|
||||||
|
GetResourceById = GetMovie;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MovieResource GetMovie(int id)
|
||||||
|
{
|
||||||
|
var movie = _movieService.GetMovie(id);
|
||||||
|
var resource = MapToResource(movie, true);
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MovieResource MapToResource(Core.Tv.Movie episode, bool includeSeries)
|
||||||
|
{
|
||||||
|
var resource = episode.ToResource();
|
||||||
|
|
||||||
|
if (includeSeries)
|
||||||
|
{
|
||||||
|
var series = episode ?? _movieService.GetMovie(episode.Id);
|
||||||
|
resource = series.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)
|
||||||
|
{
|
||||||
|
var resource = message.Movie.Movie.ToResource();
|
||||||
|
BroadcastResourceChange(ModelAction.Updated, resource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
45
src/NzbDrone.Api/NetImport/ImportExclusionsModule.cs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Api.ClientSchema;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.NetImport.ImportExclusions;
|
||||||
|
using NzbDrone.Core.Validation.Paths;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class ImportExclusionsModule : NzbDroneRestModule<ImportExclusionsResource>
|
||||||
|
{
|
||||||
|
private readonly IImportExclusionsService _exclusionService;
|
||||||
|
|
||||||
|
public ImportExclusionsModule(NetImportFactory netImportFactory, IImportExclusionsService exclusionService) : base("exclusions")
|
||||||
|
{
|
||||||
|
_exclusionService = exclusionService;
|
||||||
|
GetResourceAll = GetAll;
|
||||||
|
CreateResource = AddExclusion;
|
||||||
|
DeleteResource = RemoveExclusion;
|
||||||
|
GetResourceById = GetById;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<ImportExclusionsResource> GetAll()
|
||||||
|
{
|
||||||
|
return _exclusionService.GetAllExclusions().ToResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImportExclusionsResource GetById(int id)
|
||||||
|
{
|
||||||
|
return _exclusionService.GetById(id).ToResource();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int AddExclusion(ImportExclusionsResource exclusionResource)
|
||||||
|
{
|
||||||
|
var model = exclusionResource.ToModel();
|
||||||
|
|
||||||
|
return _exclusionService.AddExclusion(model).Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveExclusion (int id)
|
||||||
|
{
|
||||||
|
_exclusionService.RemoveExclusion(new ImportExclusion { Id = id });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
46
src/NzbDrone.Api/NetImport/ImportExclusionsResource.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class ImportExclusionsResource : ProviderResource
|
||||||
|
{
|
||||||
|
//public int Id { get; set; }
|
||||||
|
public int TmdbId { get; set; }
|
||||||
|
public string MovieTitle { get; set; }
|
||||||
|
public int MovieYear { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ImportExclusionsResourceMapper
|
||||||
|
{
|
||||||
|
public static ImportExclusionsResource ToResource(this Core.NetImport.ImportExclusions.ImportExclusion model)
|
||||||
|
{
|
||||||
|
if (model == null) return null;
|
||||||
|
|
||||||
|
return new ImportExclusionsResource
|
||||||
|
{
|
||||||
|
Id = model.Id,
|
||||||
|
TmdbId = model.TmdbId,
|
||||||
|
MovieTitle = model.MovieTitle,
|
||||||
|
MovieYear = model.MovieYear
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<ImportExclusionsResource> ToResource(this IEnumerable<Core.NetImport.ImportExclusions.ImportExclusion> exclusions)
|
||||||
|
{
|
||||||
|
return exclusions.Select(ToResource).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Core.NetImport.ImportExclusions.ImportExclusion ToModel(this ImportExclusionsResource resource)
|
||||||
|
{
|
||||||
|
return new Core.NetImport.ImportExclusions.ImportExclusion
|
||||||
|
{
|
||||||
|
TmdbId = resource.TmdbId,
|
||||||
|
MovieTitle = resource.MovieTitle,
|
||||||
|
MovieYear = resource.MovieYear
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
src/NzbDrone.Api/NetImport/ListImportModule.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using Nancy;
|
||||||
|
using Nancy.Extensions;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Api.Movie;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class ListImportModule : NzbDroneApiModule
|
||||||
|
{
|
||||||
|
private readonly IMovieService _movieService;
|
||||||
|
private readonly ISearchForNewMovie _movieSearch;
|
||||||
|
|
||||||
|
public ListImportModule(IMovieService movieService, ISearchForNewMovie movieSearch)
|
||||||
|
: base("/movie/import")
|
||||||
|
{
|
||||||
|
_movieService = movieService;
|
||||||
|
_movieSearch = movieSearch;
|
||||||
|
Put["/"] = Movie => SaveAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response SaveAll()
|
||||||
|
{
|
||||||
|
var resources = Request.Body.FromJson<List<MovieResource>>();
|
||||||
|
|
||||||
|
var Movies = resources.Select(MovieResource => _movieSearch.MapMovieToTmdbMovie(MovieResource.ToModel())).Where(m => m != null).DistinctBy(m => m.TmdbId).ToList();
|
||||||
|
|
||||||
|
return _movieService.AddMovies(Movies).ToResource().AsResponse(HttpStatusCode.Accepted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
src/NzbDrone.Api/NetImport/NetImportModule.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using FluentValidation;
|
||||||
|
using NzbDrone.Api.ClientSchema;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.Validation.Paths;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class NetImportModule : ProviderModuleBase<NetImportResource, INetImport, NetImportDefinition>
|
||||||
|
{
|
||||||
|
public NetImportModule(NetImportFactory netImportFactory) : base(netImportFactory, "netimport")
|
||||||
|
{
|
||||||
|
PostValidator.RuleFor(c => c.RootFolderPath).NotNull();
|
||||||
|
PostValidator.RuleFor(c => c.MinimumAvailability).NotNull();
|
||||||
|
PostValidator.RuleFor(c => c.ProfileId).NotNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void MapToResource(NetImportResource resource, NetImportDefinition definition)
|
||||||
|
{
|
||||||
|
base.MapToResource(resource, definition);
|
||||||
|
|
||||||
|
resource.Enabled = definition.Enabled;
|
||||||
|
resource.EnableAuto = definition.EnableAuto;
|
||||||
|
resource.ProfileId = definition.ProfileId;
|
||||||
|
resource.RootFolderPath = definition.RootFolderPath;
|
||||||
|
resource.ShouldMonitor = definition.ShouldMonitor;
|
||||||
|
resource.MinimumAvailability = definition.MinimumAvailability;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void MapToModel(NetImportDefinition definition, NetImportResource resource)
|
||||||
|
{
|
||||||
|
base.MapToModel(definition, resource);
|
||||||
|
|
||||||
|
definition.Enabled = resource.Enabled;
|
||||||
|
definition.EnableAuto = resource.EnableAuto;
|
||||||
|
definition.ProfileId = resource.ProfileId;
|
||||||
|
definition.RootFolderPath = resource.RootFolderPath;
|
||||||
|
definition.ShouldMonitor = resource.ShouldMonitor;
|
||||||
|
definition.MinimumAvailability = resource.MinimumAvailability;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Validate(NetImportDefinition definition, bool includeWarnings)
|
||||||
|
{
|
||||||
|
if (!definition.Enable) return;
|
||||||
|
base.Validate(definition, includeWarnings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/NzbDrone.Api/NetImport/NetImportResource.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.NetImport
|
||||||
|
{
|
||||||
|
public class NetImportResource : ProviderResource
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public bool EnableAuto { get; set; }
|
||||||
|
public bool ShouldMonitor { get; set; }
|
||||||
|
public string RootFolderPath { get; set; }
|
||||||
|
public int ProfileId { get; set; }
|
||||||
|
public MovieStatusType MinimumAvailability { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -109,13 +109,26 @@
|
|||||||
<Compile Include="ClientSchema\SelectOption.cs" />
|
<Compile Include="ClientSchema\SelectOption.cs" />
|
||||||
<Compile Include="Commands\CommandModule.cs" />
|
<Compile Include="Commands\CommandModule.cs" />
|
||||||
<Compile Include="Commands\CommandResource.cs" />
|
<Compile Include="Commands\CommandResource.cs" />
|
||||||
|
<Compile Include="Config\NetImportConfigModule.cs" />
|
||||||
|
<Compile Include="Config\NetImportConfigResource.cs" />
|
||||||
<Compile Include="Extensions\AccessControlHeaders.cs" />
|
<Compile Include="Extensions\AccessControlHeaders.cs" />
|
||||||
<Compile Include="Extensions\Pipelines\CorsPipeline.cs" />
|
<Compile Include="Extensions\Pipelines\CorsPipeline.cs" />
|
||||||
|
<Compile Include="Extensions\Pipelines\UrlBasePipeline.cs" />
|
||||||
<Compile Include="Extensions\Pipelines\RequestLoggingPipeline.cs" />
|
<Compile Include="Extensions\Pipelines\RequestLoggingPipeline.cs" />
|
||||||
<Compile Include="Frontend\Mappers\LoginHtmlMapper.cs" />
|
<Compile Include="Frontend\Mappers\LoginHtmlMapper.cs" />
|
||||||
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
<Compile Include="Frontend\Mappers\RobotsTxtMapper.cs" />
|
||||||
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
<Compile Include="Indexers\ReleaseModuleBase.cs" />
|
||||||
<Compile Include="Indexers\ReleasePushModule.cs" />
|
<Compile Include="Indexers\ReleasePushModule.cs" />
|
||||||
|
<Compile Include="Movies\MovieModuleWithSignalR.cs" />
|
||||||
|
<Compile Include="Movies\MovieBulkImportModule.cs" />
|
||||||
|
<Compile Include="Movies\MovieFileModule.cs" />
|
||||||
|
<Compile Include="Series\MovieModule.cs" />
|
||||||
|
<Compile Include="Movies\RenameMovieModule.cs" />
|
||||||
|
<Compile Include="Movies\RenameMovieResource.cs" />
|
||||||
|
<Compile Include="Movies\MovieEditorModule.cs" />
|
||||||
|
<Compile Include="NetImport\ListImportModule.cs" />
|
||||||
|
<Compile Include="NetImport\NetImportModule.cs" />
|
||||||
|
<Compile Include="NetImport\NetImportResource.cs" />
|
||||||
<Compile Include="Parse\ParseModule.cs" />
|
<Compile Include="Parse\ParseModule.cs" />
|
||||||
<Compile Include="Parse\ParseResource.cs" />
|
<Compile Include="Parse\ParseResource.cs" />
|
||||||
<Compile Include="ManualImport\ManualImportModule.cs" />
|
<Compile Include="ManualImport\ManualImportModule.cs" />
|
||||||
@@ -228,12 +241,13 @@
|
|||||||
<Compile Include="RootFolders\RootFolderResource.cs" />
|
<Compile Include="RootFolders\RootFolderResource.cs" />
|
||||||
<Compile Include="SeasonPass\SeasonPassResource.cs" />
|
<Compile Include="SeasonPass\SeasonPassResource.cs" />
|
||||||
<Compile Include="Series\AlternateTitleResource.cs" />
|
<Compile Include="Series\AlternateTitleResource.cs" />
|
||||||
|
<Compile Include="Series\MovieFileResource.cs" />
|
||||||
|
<Compile Include="Series\FetchMovieListModule.cs" />
|
||||||
<Compile Include="Series\SeasonResource.cs" />
|
<Compile Include="Series\SeasonResource.cs" />
|
||||||
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
<Compile Include="SeasonPass\SeasonPassModule.cs" />
|
||||||
<Compile Include="Series\SeriesEditorModule.cs" />
|
<Compile Include="Series\SeriesEditorModule.cs" />
|
||||||
<Compile Include="Series\MovieLookupModule.cs" />
|
<Compile Include="Series\MovieLookupModule.cs" />
|
||||||
<Compile Include="Series\SeriesLookupModule.cs" />
|
<Compile Include="Series\SeriesLookupModule.cs" />
|
||||||
<Compile Include="Series\MovieModule.cs" />
|
|
||||||
<Compile Include="Series\SeriesModule.cs" />
|
<Compile Include="Series\SeriesModule.cs" />
|
||||||
<Compile Include="Series\MovieResource.cs" />
|
<Compile Include="Series\MovieResource.cs" />
|
||||||
<Compile Include="Series\SeriesResource.cs" />
|
<Compile Include="Series\SeriesResource.cs" />
|
||||||
@@ -248,12 +262,18 @@
|
|||||||
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
<Compile Include="TinyIoCNancyBootstrapper.cs" />
|
||||||
<Compile Include="Update\UpdateModule.cs" />
|
<Compile Include="Update\UpdateModule.cs" />
|
||||||
<Compile Include="Update\UpdateResource.cs" />
|
<Compile Include="Update\UpdateResource.cs" />
|
||||||
|
<Compile Include="Validation\NetImportSyncIntervalValidator.cs" />
|
||||||
<Compile Include="Validation\RssSyncIntervalValidator.cs" />
|
<Compile Include="Validation\RssSyncIntervalValidator.cs" />
|
||||||
<Compile Include="Validation\EmptyCollectionValidator.cs" />
|
<Compile Include="Validation\EmptyCollectionValidator.cs" />
|
||||||
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
<Compile Include="Validation\RuleBuilderExtensions.cs" />
|
||||||
<Compile Include="Wanted\CutoffModule.cs" />
|
<Compile Include="Wanted\CutoffModule.cs" />
|
||||||
<Compile Include="Wanted\LegacyMissingModule.cs" />
|
<Compile Include="Wanted\LegacyMissingModule.cs" />
|
||||||
<Compile Include="Wanted\MissingModule.cs" />
|
<Compile Include="Wanted\MissingModule.cs" />
|
||||||
|
<Compile Include="Wanted\MovieCutoffModule.cs" />
|
||||||
|
<Compile Include="Wanted\MovieMissingModule.cs" />
|
||||||
|
<Compile Include="Series\MovieDiscoverModule.cs" />
|
||||||
|
<Compile Include="NetImport\ImportExclusionsModule.cs" />
|
||||||
|
<Compile Include="NetImport\ImportExclusionsResource.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="app.config" />
|
<None Include="app.config" />
|
||||||
@@ -281,11 +301,11 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup />
|
<ItemGroup />
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||||
Other similar extension points exist, see Microsoft.Common.targets.
|
Other similar extension points exist, see Microsoft.Common.targets.
|
||||||
<Target Name="BeforeBuild">
|
<Target Name="BeforeBuild">
|
||||||
</Target>
|
</Target>
|
||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</Target>
|
||||||
-->
|
-->
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq.Expressions;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
namespace NzbDrone.Api
|
namespace NzbDrone.Api
|
||||||
@@ -11,6 +13,7 @@ namespace NzbDrone.Api
|
|||||||
public SortDirection SortDirection { get; set; }
|
public SortDirection SortDirection { get; set; }
|
||||||
public string FilterKey { get; set; }
|
public string FilterKey { get; set; }
|
||||||
public string FilterValue { get; set; }
|
public string FilterValue { get; set; }
|
||||||
|
public string FilterType { get; set; }
|
||||||
public int TotalRecords { get; set; }
|
public int TotalRecords { get; set; }
|
||||||
public List<TResource> Records { get; set; }
|
public List<TResource> Records { get; set; }
|
||||||
}
|
}
|
||||||
@@ -38,5 +41,14 @@ namespace NzbDrone.Api
|
|||||||
|
|
||||||
return pagingSpec;
|
return pagingSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*public static Expression<Func<TModel, object>> CreateFilterExpression<TModel>(string filterKey, string filterValue)
|
||||||
|
{
|
||||||
|
Type type = typeof(TModel);
|
||||||
|
ParameterExpression parameterExpression = Expression.Parameter(type, "x");
|
||||||
|
Expression expressionBody = parameterExpression;
|
||||||
|
|
||||||
|
return expressionBody;
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace NzbDrone.Api.Profiles
|
|||||||
{
|
{
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public Quality Cutoff { get; set; }
|
public Quality Cutoff { get; set; }
|
||||||
|
public string PreferredTags { get; set; }
|
||||||
public List<ProfileQualityItemResource> Items { get; set; }
|
public List<ProfileQualityItemResource> Items { get; set; }
|
||||||
public Language Language { get; set; }
|
public Language Language { get; set; }
|
||||||
}
|
}
|
||||||
@@ -33,6 +34,7 @@ namespace NzbDrone.Api.Profiles
|
|||||||
|
|
||||||
Name = model.Name,
|
Name = model.Name,
|
||||||
Cutoff = model.Cutoff,
|
Cutoff = model.Cutoff,
|
||||||
|
PreferredTags = model.PreferredTags != null ? string.Join(",", model.PreferredTags) : "",
|
||||||
Items = model.Items.ConvertAll(ToResource),
|
Items = model.Items.ConvertAll(ToResource),
|
||||||
Language = model.Language
|
Language = model.Language
|
||||||
};
|
};
|
||||||
@@ -59,6 +61,7 @@ namespace NzbDrone.Api.Profiles
|
|||||||
|
|
||||||
Name = resource.Name,
|
Name = resource.Name,
|
||||||
Cutoff = (Quality)resource.Cutoff.Id,
|
Cutoff = (Quality)resource.Cutoff.Id,
|
||||||
|
PreferredTags = resource.PreferredTags.Split(',').ToList(),
|
||||||
Items = resource.Items.ConvertAll(ToModel),
|
Items = resource.Items.ConvertAll(ToModel),
|
||||||
Language = resource.Language
|
Language = resource.Language
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ namespace NzbDrone.Api
|
|||||||
|
|
||||||
resource.Fields = SchemaBuilder.ToSchema(definition.Settings);
|
resource.Fields = SchemaBuilder.ToSchema(definition.Settings);
|
||||||
|
|
||||||
resource.InfoLink = string.Format("https://github.com/Sonarr/Sonarr/wiki/Supported-{0}#{1}",
|
resource.InfoLink = string.Format("https://github.com/Radarr/Radarr/wiki/Supported-{0}#{1}",
|
||||||
typeof(TProviderResource).Name.Replace("Resource", "s"),
|
typeof(TProviderResource).Name.Replace("Resource", "s"),
|
||||||
definition.Implementation.ToLower());
|
definition.Implementation.ToLower());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ namespace NzbDrone.Api.Queue
|
|||||||
throw new NotFoundException();
|
throw new NotFoundException();
|
||||||
}
|
}
|
||||||
|
|
||||||
_downloadService.DownloadReport(pendingRelease.RemoteEpisode);
|
_downloadService.DownloadReport(pendingRelease.RemoteMovie);
|
||||||
|
|
||||||
return resource.AsResponse();
|
return resource.AsResponse();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,7 +123,13 @@ namespace NzbDrone.Api.REST
|
|||||||
|
|
||||||
Get[ROOT_ROUTE] = options =>
|
Get[ROOT_ROUTE] = options =>
|
||||||
{
|
{
|
||||||
var resource = GetResourcePaged(ReadPagingResourceFromRequest());
|
var pagingSpec = ReadPagingResourceFromRequest();
|
||||||
|
if (pagingSpec.Page == 0 && pagingSpec.PageSize == 0)
|
||||||
|
{
|
||||||
|
var all = GetResourceAll();
|
||||||
|
return all.AsResponse();
|
||||||
|
}
|
||||||
|
var resource = GetResourcePaged(pagingSpec);
|
||||||
return resource.AsResponse();
|
return resource.AsResponse();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -214,12 +220,10 @@ namespace NzbDrone.Api.REST
|
|||||||
private PagingResource<TResource> ReadPagingResourceFromRequest()
|
private PagingResource<TResource> ReadPagingResourceFromRequest()
|
||||||
{
|
{
|
||||||
int pageSize;
|
int pageSize;
|
||||||
int.TryParse(Request.Query.PageSize.ToString(), out pageSize);
|
int.TryParse(Request.Query.PageSize.ToString(), out pageSize);
|
||||||
if (pageSize == 0) pageSize = 10;
|
|
||||||
|
|
||||||
int page;
|
int page;
|
||||||
int.TryParse(Request.Query.Page.ToString(), out page);
|
int.TryParse(Request.Query.Page.ToString(), out page);
|
||||||
if (page == 0) page = 1;
|
|
||||||
|
|
||||||
|
|
||||||
var pagingResource = new PagingResource<TResource>
|
var pagingResource = new PagingResource<TResource>
|
||||||
@@ -249,9 +253,16 @@ namespace NzbDrone.Api.REST
|
|||||||
{
|
{
|
||||||
pagingResource.FilterValue = Request.Query.FilterValue.ToString();
|
pagingResource.FilterValue = Request.Query.FilterValue.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Request.Query.FilterType != null)
|
||||||
|
{
|
||||||
|
pagingResource.FilterType = Request.Query.FilterType.ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return pagingResource;
|
return pagingResource;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,8 +38,8 @@ namespace NzbDrone.Api.RootFolders
|
|||||||
Id = resource.Id,
|
Id = resource.Id,
|
||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
//FreeSpace
|
FreeSpace = resource.FreeSpace,
|
||||||
//UnmappedFolders
|
UnmappedFolders = resource.UnmappedFolders
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
60
src/NzbDrone.Api/Series/FetchMovieListModule.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class FetchMovieListModule : NzbDroneRestModule<MovieResource>
|
||||||
|
{
|
||||||
|
private readonly IFetchNetImport _fetchNetImport;
|
||||||
|
private readonly ISearchForNewMovie _movieSearch;
|
||||||
|
|
||||||
|
public FetchMovieListModule(IFetchNetImport netImport, ISearchForNewMovie movieSearch)
|
||||||
|
: base("/netimport/movies")
|
||||||
|
{
|
||||||
|
_fetchNetImport = netImport;
|
||||||
|
_movieSearch = movieSearch;
|
||||||
|
Get["/"] = x => Search();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private Response Search()
|
||||||
|
{
|
||||||
|
var results = _fetchNetImport.FetchAndFilter((int) Request.Query.listId, false);
|
||||||
|
|
||||||
|
List<Core.Tv.Movie> realResults = new List<Core.Tv.Movie>();
|
||||||
|
|
||||||
|
/*foreach (var movie in results)
|
||||||
|
{
|
||||||
|
var mapped = _movieSearch.MapMovieToTmdbMovie(movie);
|
||||||
|
|
||||||
|
if (mapped != null)
|
||||||
|
{
|
||||||
|
realResults.Add(mapped);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return MapToResource(results).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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
63
src/NzbDrone.Api/Series/MovieDiscoverModule.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Nancy;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.MediaCover;
|
||||||
|
using NzbDrone.Core.MetadataSource;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.NetImport;
|
||||||
|
using NzbDrone.Api.NetImport;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Movie
|
||||||
|
{
|
||||||
|
public class MovieDiscoverModule : NzbDroneRestModule<MovieResource>
|
||||||
|
{
|
||||||
|
private readonly IDiscoverNewMovies _searchProxy;
|
||||||
|
private readonly INetImportFactory _netImportFactory;
|
||||||
|
|
||||||
|
public MovieDiscoverModule(IDiscoverNewMovies searchProxy, INetImportFactory netImportFactory)
|
||||||
|
: base("/movies/discover")
|
||||||
|
{
|
||||||
|
_searchProxy = searchProxy;
|
||||||
|
_netImportFactory = netImportFactory;
|
||||||
|
Get["/lists"] = x => GetLists();
|
||||||
|
Get["/{action?recommendations}"] = x => Search(x.action);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response Search(string action)
|
||||||
|
{
|
||||||
|
var imdbResults = _searchProxy.DiscoverNewMovies(action);
|
||||||
|
return MapToResource(imdbResults).AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response GetLists()
|
||||||
|
{
|
||||||
|
var lists = _netImportFactory.Discoverable();
|
||||||
|
|
||||||
|
return lists.Select(definition => {
|
||||||
|
var resource = new NetImportResource();
|
||||||
|
resource.Id = definition.Definition.Id;
|
||||||
|
|
||||||
|
resource.Name = definition.Definition.Name;
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}).AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||||
|
{
|
||||||
|
foreach (var currentSeries in movies)
|
||||||
|
{
|
||||||
|
var resource = currentSeries.ToResource();
|
||||||
|
var poster = currentSeries.Images.FirstOrDefault(c => c.CoverType == MediaCoverTypes.Poster);
|
||||||
|
if (poster != null)
|
||||||
|
{
|
||||||
|
resource.RemotePoster = poster.Url;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,20 +4,44 @@ using NzbDrone.Api.Extensions;
|
|||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.MetadataSource;
|
using NzbDrone.Core.MetadataSource;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Movie
|
namespace NzbDrone.Api.Movie
|
||||||
{
|
{
|
||||||
public class MovieLookupModule : NzbDroneRestModule<MovieResource>
|
public class MovieLookupModule : NzbDroneRestModule<MovieResource>
|
||||||
{
|
{
|
||||||
private readonly ISearchForNewMovie _searchProxy;
|
private readonly ISearchForNewMovie _searchProxy;
|
||||||
|
private readonly IProvideMovieInfo _movieInfo;
|
||||||
|
|
||||||
public MovieLookupModule(ISearchForNewMovie searchProxy)
|
public MovieLookupModule(ISearchForNewMovie searchProxy, IProvideMovieInfo movieInfo)
|
||||||
: base("/movies/lookup")
|
: base("/movies/lookup")
|
||||||
{
|
{
|
||||||
|
_movieInfo = movieInfo;
|
||||||
_searchProxy = searchProxy;
|
_searchProxy = searchProxy;
|
||||||
Get["/"] = x => Search();
|
Get["/"] = x => Search();
|
||||||
|
Get["/tmdb"] = x => SearchByTmdbId();
|
||||||
|
Get["/imdb"] = x => SearchByImdbId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response SearchByTmdbId()
|
||||||
|
{
|
||||||
|
int tmdbId = -1;
|
||||||
|
if(Int32.TryParse(Request.Query.tmdbId, out tmdbId))
|
||||||
|
{
|
||||||
|
var result = _movieInfo.GetMovieInfo(tmdbId, null, true);
|
||||||
|
return result.ToResource().AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new BadRequestException("Tmdb Id was not valid");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Response SearchByImdbId()
|
||||||
|
{
|
||||||
|
string imdbId = Request.Query.imdbId;
|
||||||
|
var result = _movieInfo.GetMovieInfo(imdbId);
|
||||||
|
return result.ToResource().AsResponse();
|
||||||
|
}
|
||||||
|
|
||||||
private Response Search()
|
private Response Search()
|
||||||
{
|
{
|
||||||
@@ -25,7 +49,6 @@ namespace NzbDrone.Api.Movie
|
|||||||
return MapToResource(imdbResults).AsResponse();
|
return MapToResource(imdbResults).AsResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
private static IEnumerable<MovieResource> MapToResource(IEnumerable<Core.Tv.Movie> movies)
|
||||||
{
|
{
|
||||||
foreach (var currentSeries in movies)
|
foreach (var currentSeries in movies)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentValidation;
|
using FluentValidation;
|
||||||
using NzbDrone.Common.Extensions;
|
using NzbDrone.Common.Extensions;
|
||||||
|
using NzbDrone.Api.Extensions;
|
||||||
using NzbDrone.Core.Datastore.Events;
|
using NzbDrone.Core.Datastore.Events;
|
||||||
using NzbDrone.Core.MediaCover;
|
using NzbDrone.Core.MediaCover;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
@@ -15,6 +16,9 @@ using NzbDrone.Core.Validation.Paths;
|
|||||||
using NzbDrone.Core.DataAugmentation.Scene;
|
using NzbDrone.Core.DataAugmentation.Scene;
|
||||||
using NzbDrone.Core.Validation;
|
using NzbDrone.Core.Validation;
|
||||||
using NzbDrone.SignalR;
|
using NzbDrone.SignalR;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using Microsoft.CSharp.RuntimeBinder;
|
||||||
|
using Nancy;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Movie
|
namespace NzbDrone.Api.Movie
|
||||||
{
|
{
|
||||||
@@ -28,10 +32,12 @@ namespace NzbDrone.Api.Movie
|
|||||||
IHandle<MediaCoversUpdatedEvent>
|
IHandle<MediaCoversUpdatedEvent>
|
||||||
|
|
||||||
{
|
{
|
||||||
private readonly IMovieService _moviesService;
|
protected readonly IMovieService _moviesService;
|
||||||
private readonly IMovieStatisticsService _moviesStatisticsService;
|
private readonly IMovieStatisticsService _moviesStatisticsService;
|
||||||
private readonly IMapCoversToLocal _coverMapper;
|
private readonly IMapCoversToLocal _coverMapper;
|
||||||
|
|
||||||
|
private const string TITLE_SLUG_ROUTE = "/titleslug/(?<slug>[^/]+)";
|
||||||
|
|
||||||
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
public MovieModule(IBroadcastSignalRMessage signalRBroadcaster,
|
||||||
IMovieService moviesService,
|
IMovieService moviesService,
|
||||||
IMovieStatisticsService moviesStatisticsService,
|
IMovieStatisticsService moviesStatisticsService,
|
||||||
@@ -52,7 +58,14 @@ namespace NzbDrone.Api.Movie
|
|||||||
_coverMapper = coverMapper;
|
_coverMapper = coverMapper;
|
||||||
|
|
||||||
GetResourceAll = AllMovie;
|
GetResourceAll = AllMovie;
|
||||||
|
GetResourcePaged = GetMoviePaged;
|
||||||
GetResourceById = GetMovie;
|
GetResourceById = GetMovie;
|
||||||
|
Get[TITLE_SLUG_ROUTE] = GetByTitleSlug; /*(options) => {
|
||||||
|
return ReqResExtensions.AsResponse(GetByTitleSlug(options.slug), Nancy.HttpStatusCode.OK);
|
||||||
|
};*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
CreateResource = AddMovie;
|
CreateResource = AddMovie;
|
||||||
UpdateResource = UpdateMovie;
|
UpdateResource = UpdateMovie;
|
||||||
DeleteResource = DeleteMovie;
|
DeleteResource = DeleteMovie;
|
||||||
@@ -78,13 +91,42 @@ namespace NzbDrone.Api.Movie
|
|||||||
PutValidator.RuleFor(s => s.Path).IsValidPath();
|
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)
|
private MovieResource GetMovie(int id)
|
||||||
{
|
{
|
||||||
var movies = _moviesService.GetMovie(id);
|
var movies = _moviesService.GetMovie(id);
|
||||||
return MapToResource(movies);
|
return MapToResource(movies);
|
||||||
}
|
}
|
||||||
|
|
||||||
private MovieResource MapToResource(Core.Tv.Movie movies)
|
private PagingResource<MovieResource> GetMoviePaged(PagingResource<MovieResource> pagingResource)
|
||||||
|
{
|
||||||
|
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>();
|
||||||
|
|
||||||
|
pagingSpec.FilterExpression = _moviesService.ConstructFilterExpression(pagingResource.FilterKey, pagingResource.FilterValue, pagingResource.FilterType);
|
||||||
|
|
||||||
|
return ApplyToPage(_moviesService.Paged, pagingSpec, MapToResource);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected MovieResource MapToResource(Core.Tv.Movie movies)
|
||||||
{
|
{
|
||||||
if (movies == null) return null;
|
if (movies == null) return null;
|
||||||
|
|
||||||
@@ -108,6 +150,29 @@ namespace NzbDrone.Api.Movie
|
|||||||
return moviesResources;
|
return moviesResources;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Response GetByTitleSlug(dynamic options)
|
||||||
|
{
|
||||||
|
var slug = "";
|
||||||
|
try
|
||||||
|
{
|
||||||
|
slug = options.slug;
|
||||||
|
// do stuff with x
|
||||||
|
}
|
||||||
|
catch (RuntimeBinderException)
|
||||||
|
{
|
||||||
|
return new NotFoundResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return MapToResource(_moviesService.FindByTitleSlug(slug)).AsResponse(Nancy.HttpStatusCode.OK);
|
||||||
|
}
|
||||||
|
catch (ModelNotFoundException)
|
||||||
|
{
|
||||||
|
return new NotFoundResponse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private int AddMovie(MovieResource moviesResource)
|
private int AddMovie(MovieResource moviesResource)
|
||||||
{
|
{
|
||||||
var model = moviesResource.ToModel();
|
var model = moviesResource.ToModel();
|
||||||
@@ -127,14 +192,20 @@ namespace NzbDrone.Api.Movie
|
|||||||
private void DeleteMovie(int id)
|
private void DeleteMovie(int id)
|
||||||
{
|
{
|
||||||
var deleteFiles = false;
|
var deleteFiles = false;
|
||||||
|
var addExclusion = false;
|
||||||
var deleteFilesQuery = Request.Query.deleteFiles;
|
var deleteFilesQuery = Request.Query.deleteFiles;
|
||||||
|
var addExclusionQuery = Request.Query.addExclusion;
|
||||||
|
|
||||||
if (deleteFilesQuery.HasValue)
|
if (deleteFilesQuery.HasValue)
|
||||||
{
|
{
|
||||||
deleteFiles = Convert.ToBoolean(deleteFilesQuery.Value);
|
deleteFiles = Convert.ToBoolean(deleteFilesQuery.Value);
|
||||||
}
|
}
|
||||||
|
if (addExclusionQuery.HasValue)
|
||||||
|
{
|
||||||
|
addExclusion = Convert.ToBoolean(addExclusionQuery.Value);
|
||||||
|
}
|
||||||
|
|
||||||
_moviesService.DeleteMovie(id, deleteFiles);
|
_moviesService.DeleteMovie(id, deleteFiles, addExclusion);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapCoversToLocal(params MovieResource[] movies)
|
private void MapCoversToLocal(params MovieResource[] movies)
|
||||||
@@ -165,7 +236,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
|
private void LinkMovieStatistics(MovieResource resource, MovieStatistics moviesStatistics)
|
||||||
{
|
{
|
||||||
resource.SizeOnDisk = moviesStatistics.SizeOnDisk;
|
//resource.SizeOnDisk = 0;//TODO: incorporate movie statistics moviesStatistics.SizeOnDisk;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void PopulateAlternateTitles(List<MovieResource> resources)
|
private void PopulateAlternateTitles(List<MovieResource> resources)
|
||||||
@@ -181,6 +252,8 @@ namespace NzbDrone.Api.Movie
|
|||||||
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
//var mappings = null;//_sceneMappingService.FindByTvdbId(resource.TvdbId);
|
||||||
|
|
||||||
//if (mappings == null) return;
|
//if (mappings == null) return;
|
||||||
|
|
||||||
|
//Not necessary anymore
|
||||||
|
|
||||||
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
//resource.AlternateTitles = mappings.Select(v => new AlternateTitleResource { Title = v.Title, SeasonNumber = v.SeasonNumber, SceneSeasonNumber = v.SceneSeasonNumber }).ToList();
|
||||||
}
|
}
|
||||||
@@ -219,7 +292,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
public void Handle(MediaCoversUpdatedEvent message)
|
public void Handle(MediaCoversUpdatedEvent message)
|
||||||
{
|
{
|
||||||
//BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
BroadcastResourceChange(ModelAction.Updated, message.Movie.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
//Todo: Sorters should be done completely on the client
|
//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: 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
|
//Todo: We should get the entire Profile instead of ID and Name separately
|
||||||
|
|
||||||
//View Only
|
//View Only
|
||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public List<AlternateTitleResource> AlternateTitles { get; set; }
|
public List<AlternateTitleResource> AlternateTitles { get; set; }
|
||||||
@@ -28,18 +28,27 @@ namespace NzbDrone.Api.Movie
|
|||||||
public string Overview { get; set; }
|
public string Overview { get; set; }
|
||||||
public DateTime? InCinemas { get; set; }
|
public DateTime? InCinemas { get; set; }
|
||||||
public DateTime? PhysicalRelease { get; set; }
|
public DateTime? PhysicalRelease { get; set; }
|
||||||
|
public string PhysicalReleaseNote { get; set; }
|
||||||
public List<MediaCover> Images { get; set; }
|
public List<MediaCover> Images { get; set; }
|
||||||
public string Website { get; set; }
|
public string Website { get; set; }
|
||||||
public bool Downloaded { get; set; }
|
public bool Downloaded { get; set; }
|
||||||
public string RemotePoster { get; set; }
|
public string RemotePoster { get; set; }
|
||||||
public int Year { get; set; }
|
public int Year { get; set; }
|
||||||
|
public bool HasFile { get; set; }
|
||||||
|
public string YouTubeTrailerId { get; set; }
|
||||||
|
public string Studio { get; set; }
|
||||||
|
|
||||||
//View & Edit
|
//View & Edit
|
||||||
public string Path { get; set; }
|
public string Path { get; set; }
|
||||||
public int ProfileId { get; set; }
|
public int ProfileId { get; set; }
|
||||||
|
public MoviePathState PathState { get; set; }
|
||||||
|
|
||||||
//Editing Only
|
//Editing Only
|
||||||
public bool Monitored { get; set; }
|
public bool Monitored { get; set; }
|
||||||
|
public MovieStatusType MinimumAvailability { get; set; }
|
||||||
|
public bool IsAvailable { get; set; }
|
||||||
|
public string FolderName { get; set; }
|
||||||
|
|
||||||
public int Runtime { get; set; }
|
public int Runtime { get; set; }
|
||||||
public DateTime? LastInfoSync { get; set; }
|
public DateTime? LastInfoSync { get; set; }
|
||||||
public string CleanTitle { get; set; }
|
public string CleanTitle { get; set; }
|
||||||
@@ -54,6 +63,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
public AddMovieOptions AddOptions { get; set; }
|
public AddMovieOptions AddOptions { get; set; }
|
||||||
public Ratings Ratings { get; set; }
|
public Ratings Ratings { get; set; }
|
||||||
public List<string> AlternativeTitles { get; set; }
|
public List<string> AlternativeTitles { get; set; }
|
||||||
|
public MovieFileResource MovieFile { get; set; }
|
||||||
|
|
||||||
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
//TODO: Add series statistics as a property of the series (instead of individual properties)
|
||||||
|
|
||||||
@@ -80,7 +90,23 @@ namespace NzbDrone.Api.Movie
|
|||||||
{
|
{
|
||||||
if (model == null) return null;
|
if (model == null) return null;
|
||||||
|
|
||||||
long Size = model.MovieFile.Value != null ? model.MovieFile.Value.Size : 0;
|
|
||||||
|
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
|
return new MovieResource
|
||||||
{
|
{
|
||||||
@@ -91,12 +117,13 @@ namespace NzbDrone.Api.Movie
|
|||||||
SortTitle = model.SortTitle,
|
SortTitle = model.SortTitle,
|
||||||
InCinemas = model.InCinemas,
|
InCinemas = model.InCinemas,
|
||||||
PhysicalRelease = model.PhysicalRelease,
|
PhysicalRelease = model.PhysicalRelease,
|
||||||
|
PhysicalReleaseNote = model.PhysicalReleaseNote,
|
||||||
Downloaded = model.MovieFile.Value != null,
|
HasFile = model.HasFile,
|
||||||
|
Downloaded = downloaded,
|
||||||
//TotalEpisodeCount
|
//TotalEpisodeCount
|
||||||
//EpisodeCount
|
//EpisodeCount
|
||||||
//EpisodeFileCount
|
//EpisodeFileCount
|
||||||
//SizeOnDisk
|
SizeOnDisk = size,
|
||||||
Status = model.Status,
|
Status = model.Status,
|
||||||
Overview = model.Overview,
|
Overview = model.Overview,
|
||||||
//NextAiring
|
//NextAiring
|
||||||
@@ -107,10 +134,15 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
Path = model.Path,
|
Path = model.Path,
|
||||||
ProfileId = model.ProfileId,
|
ProfileId = model.ProfileId,
|
||||||
|
PathState = model.PathState,
|
||||||
|
|
||||||
Monitored = model.Monitored,
|
Monitored = model.Monitored,
|
||||||
|
MinimumAvailability = model.MinimumAvailability,
|
||||||
|
|
||||||
|
IsAvailable = model.IsAvailable(),
|
||||||
|
FolderName = model.FolderName(),
|
||||||
|
|
||||||
SizeOnDisk = Size,
|
//SizeOnDisk = size,
|
||||||
|
|
||||||
Runtime = model.Runtime,
|
Runtime = model.Runtime,
|
||||||
LastInfoSync = model.LastInfoSync,
|
LastInfoSync = model.LastInfoSync,
|
||||||
@@ -125,7 +157,10 @@ namespace NzbDrone.Api.Movie
|
|||||||
Added = model.Added,
|
Added = model.Added,
|
||||||
AddOptions = model.AddOptions,
|
AddOptions = model.AddOptions,
|
||||||
AlternativeTitles = model.AlternativeTitles,
|
AlternativeTitles = model.AlternativeTitles,
|
||||||
Ratings = model.Ratings
|
Ratings = model.Ratings,
|
||||||
|
MovieFile = movieFile,
|
||||||
|
YouTubeTrailerId = model.YouTubeTrailerId,
|
||||||
|
Studio = model.Studio
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +178,7 @@ namespace NzbDrone.Api.Movie
|
|||||||
SortTitle = resource.SortTitle,
|
SortTitle = resource.SortTitle,
|
||||||
InCinemas = resource.InCinemas,
|
InCinemas = resource.InCinemas,
|
||||||
PhysicalRelease = resource.PhysicalRelease,
|
PhysicalRelease = resource.PhysicalRelease,
|
||||||
|
PhysicalReleaseNote = resource.PhysicalReleaseNote,
|
||||||
//TotalEpisodeCount
|
//TotalEpisodeCount
|
||||||
//EpisodeCount
|
//EpisodeCount
|
||||||
//EpisodeFileCount
|
//EpisodeFileCount
|
||||||
@@ -156,9 +192,11 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
Path = resource.Path,
|
Path = resource.Path,
|
||||||
ProfileId = resource.ProfileId,
|
ProfileId = resource.ProfileId,
|
||||||
|
PathState = resource.PathState,
|
||||||
|
|
||||||
Monitored = resource.Monitored,
|
Monitored = resource.Monitored,
|
||||||
|
MinimumAvailability = resource.MinimumAvailability,
|
||||||
|
|
||||||
Runtime = resource.Runtime,
|
Runtime = resource.Runtime,
|
||||||
LastInfoSync = resource.LastInfoSync,
|
LastInfoSync = resource.LastInfoSync,
|
||||||
CleanTitle = resource.CleanTitle,
|
CleanTitle = resource.CleanTitle,
|
||||||
@@ -172,7 +210,9 @@ namespace NzbDrone.Api.Movie
|
|||||||
Added = resource.Added,
|
Added = resource.Added,
|
||||||
AddOptions = resource.AddOptions,
|
AddOptions = resource.AddOptions,
|
||||||
AlternativeTitles = resource.AlternativeTitles,
|
AlternativeTitles = resource.AlternativeTitles,
|
||||||
Ratings = resource.Ratings
|
Ratings = resource.Ratings,
|
||||||
|
YouTubeTrailerId = resource.YouTubeTrailerId,
|
||||||
|
Studio = resource.Studio
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,9 +223,11 @@ namespace NzbDrone.Api.Movie
|
|||||||
|
|
||||||
movie.Path = resource.Path;
|
movie.Path = resource.Path;
|
||||||
movie.ProfileId = resource.ProfileId;
|
movie.ProfileId = resource.ProfileId;
|
||||||
|
movie.PathState = resource.PathState;
|
||||||
|
|
||||||
movie.Monitored = resource.Monitored;
|
movie.Monitored = resource.Monitored;
|
||||||
|
movie.MinimumAvailability = resource.MinimumAvailability;
|
||||||
|
|
||||||
movie.RootFolderPath = resource.RootFolderPath;
|
movie.RootFolderPath = resource.RootFolderPath;
|
||||||
movie.Tags = resource.Tags;
|
movie.Tags = resource.Tags;
|
||||||
movie.AddOptions = resource.AddOptions;
|
movie.AddOptions = resource.AddOptions;
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ namespace NzbDrone.Api.Series
|
|||||||
|
|
||||||
public void Handle(MediaCoversUpdatedEvent message)
|
public void Handle(MediaCoversUpdatedEvent message)
|
||||||
{
|
{
|
||||||
BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
//BroadcastResourceChange(ModelAction.Updated, message.Series.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using FluentValidation.Validators;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Validation
|
||||||
|
{
|
||||||
|
public class NetImportSyncIntervalValidator : PropertyValidator
|
||||||
|
{
|
||||||
|
public NetImportSyncIntervalValidator()
|
||||||
|
: base("Must be between 10 and 1440 or 0 to disable")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override bool IsValid(PropertyValidatorContext context)
|
||||||
|
{
|
||||||
|
if (context.PropertyValue == null)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var value = (int)context.PropertyValue;
|
||||||
|
|
||||||
|
if (value == 0)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= 10 && value <= 1440)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@ namespace NzbDrone.Api.Validation
|
|||||||
public class RssSyncIntervalValidator : PropertyValidator
|
public class RssSyncIntervalValidator : PropertyValidator
|
||||||
{
|
{
|
||||||
public RssSyncIntervalValidator()
|
public RssSyncIntervalValidator()
|
||||||
: base("Must be between 10 and 120 or 0 to disable")
|
: base("Must be between 10 and 720 or 0 to disable")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ namespace NzbDrone.Api.Validation
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value >= 10 && value <= 120)
|
if (value >= 10 && value <= 720)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,5 +36,10 @@ namespace NzbDrone.Api.Validation
|
|||||||
{
|
{
|
||||||
return ruleBuilder.SetValidator(new RssSyncIntervalValidator());
|
return ruleBuilder.SetValidator(new RssSyncIntervalValidator());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IRuleBuilderOptions<T, int> IsValidNetImportSyncInterval<T>(this IRuleBuilder<T, int> ruleBuilder)
|
||||||
|
{
|
||||||
|
return ruleBuilder.SetValidator(new NetImportSyncIntervalValidator());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace NzbDrone.Api.Wanted
|
|||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff-old")
|
||||||
{
|
{
|
||||||
_episodeCutoffService = episodeCutoffService;
|
_episodeCutoffService = episodeCutoffService;
|
||||||
GetResourcePaged = GetCutoffUnmetEpisodes;
|
GetResourcePaged = GetCutoffUnmetEpisodes;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace NzbDrone.Api.Wanted
|
|||||||
ISeriesService seriesService,
|
ISeriesService seriesService,
|
||||||
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
IBroadcastSignalRMessage signalRBroadcaster)
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
: base(episodeService, seriesService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing_episodes")
|
||||||
{
|
{
|
||||||
GetResourcePaged = GetMissingEpisodes;
|
GetResourcePaged = GetMissingEpisodes;
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/NzbDrone.Api/Wanted/MovieCutoffModule.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using NzbDrone.Api.Movie;
|
||||||
|
using NzbDrone.Api.Movies;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.SignalR;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Wanted
|
||||||
|
{
|
||||||
|
public class MovieCutoffModule : MovieModuleWithSignalR
|
||||||
|
{
|
||||||
|
private readonly IMovieCutoffService _movieCutoffService;
|
||||||
|
|
||||||
|
public MovieCutoffModule(IMovieCutoffService movieCutoffService,
|
||||||
|
IMovieService movieService,
|
||||||
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
|
: base(movieService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/cutoff")
|
||||||
|
{
|
||||||
|
_movieCutoffService = movieCutoffService;
|
||||||
|
GetResourcePaged = GetCutoffUnmetMovies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PagingResource<MovieResource> GetCutoffUnmetMovies(PagingResource<MovieResource> pagingResource)
|
||||||
|
{
|
||||||
|
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("title", SortDirection.Ascending);
|
||||||
|
|
||||||
|
pagingSpec.FilterExpression = _movieService.ConstructFilterExpression(pagingResource.FilterKey, pagingResource.FilterValue);
|
||||||
|
|
||||||
|
var resource = ApplyToPage(_movieCutoffService.MoviesWhereCutoffUnmet, pagingSpec, v => MapToResource(v, true));
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
40
src/NzbDrone.Api/Wanted/MovieMissingModule.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
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 : MovieModuleWithSignalR
|
||||||
|
{
|
||||||
|
protected readonly IMovieService _movieService;
|
||||||
|
|
||||||
|
public MovieMissingModule(IMovieService movieService,
|
||||||
|
IQualityUpgradableSpecification qualityUpgradableSpecification,
|
||||||
|
IBroadcastSignalRMessage signalRBroadcaster)
|
||||||
|
: base(movieService, qualityUpgradableSpecification, signalRBroadcaster, "wanted/missing")
|
||||||
|
{
|
||||||
|
|
||||||
|
_movieService = movieService;
|
||||||
|
GetResourcePaged = GetMissingMovies;
|
||||||
|
}
|
||||||
|
|
||||||
|
private PagingResource<MovieResource> GetMissingMovies(PagingResource<MovieResource> pagingResource)
|
||||||
|
{
|
||||||
|
var pagingSpec = pagingResource.MapToPagingSpec<MovieResource, Core.Tv.Movie>("title", SortDirection.Descending);
|
||||||
|
|
||||||
|
pagingSpec.FilterExpression = _movieService.ConstructFilterExpression(pagingResource.FilterKey, pagingResource.FilterValue);
|
||||||
|
|
||||||
|
var resource = ApplyToPage(_movieService.MoviesWithoutFiles, pagingSpec, v => MapToResource(v, true));
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,6 +65,7 @@ namespace NzbDrone.App.Test
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
[Ignore("Shit appveyor")]
|
||||||
public void should_return_same_instance_of_singletons()
|
public void should_return_same_instance_of_singletons()
|
||||||
{
|
{
|
||||||
var first = _container.ResolveAll<IHandle<ApplicationShutdownRequested>>().OfType<Scheduler>().Single();
|
var first = _container.ResolveAll<IHandle<ApplicationShutdownRequested>>().OfType<Scheduler>().Single();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ namespace NzbDrone.Common.Test.DiskTests
|
|||||||
public void should_be_able_to_check_space_on_ramdrive()
|
public void should_be_able_to_check_space_on_ramdrive()
|
||||||
{
|
{
|
||||||
MonoOnly();
|
MonoOnly();
|
||||||
Subject.GetAvailableSpace("/run/").Should().NotBe(0);
|
Subject.GetAvailableSpace("/").Should().NotBe(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ namespace NzbDrone.Common.Test.Http
|
|||||||
|
|
||||||
var userAgent = response.Resource.Headers["User-Agent"].ToString();
|
var userAgent = response.Resource.Headers["User-Agent"].ToString();
|
||||||
|
|
||||||
userAgent.Should().Contain("Sonarr");
|
userAgent.Should().Contain("Radarr");
|
||||||
}
|
}
|
||||||
|
|
||||||
[TestCase("Accept", "text/xml, text/rss+xml, application/rss+xml")]
|
[TestCase("Accept", "text/xml, text/rss+xml, application/rss+xml")]
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using NzbDrone.Common.Http;
|
using NzbDrone.Common.Http;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace NzbDrone.Common.Test.Http
|
namespace NzbDrone.Common.Test.Http
|
||||||
{
|
{
|
||||||
@@ -36,5 +37,17 @@ namespace NzbDrone.Common.Test.Http
|
|||||||
Action action = () => httpheader.GetEncodingFromContentType();
|
Action action = () => httpheader.GetEncodingFromContentType();
|
||||||
action.ShouldThrow<ArgumentException>();
|
action.ShouldThrow<ArgumentException>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_parse_cookie_with_trailing_semi_colon()
|
||||||
|
{
|
||||||
|
var cookies = HttpHeader.ParseCookies("uid=123456; pass=123456b2f3abcde42ac3a123f3f1fc9f;");
|
||||||
|
|
||||||
|
cookies.Count.Should().Be(2);
|
||||||
|
cookies.First().Key.Should().Be("uid");
|
||||||
|
cookies.First().Value.Should().Be("123456");
|
||||||
|
cookies.Last().Key.Should().Be("pass");
|
||||||
|
cookies.Last().Value.Should().Be("123456b2f3abcde42ac3a123f3f1fc9f");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ namespace NzbDrone.Common.Test
|
|||||||
{
|
{
|
||||||
var fakeEnvironment = new Mock<IAppFolderInfo>();
|
var fakeEnvironment = new Mock<IAppFolderInfo>();
|
||||||
|
|
||||||
fakeEnvironment.SetupGet(c => c.AppDataFolder).Returns(@"C:\NzbDrone\".AsOsAgnostic());
|
fakeEnvironment.SetupGet(c => c.AppDataFolder).Returns(@"C:\Radarr\".AsOsAgnostic());
|
||||||
|
|
||||||
fakeEnvironment.SetupGet(c => c.TempFolder).Returns(@"C:\Temp\".AsOsAgnostic());
|
fakeEnvironment.SetupGet(c => c.TempFolder).Returns(@"C:\Temp\".AsOsAgnostic());
|
||||||
|
|
||||||
@@ -233,43 +233,43 @@ namespace NzbDrone.Common.Test
|
|||||||
[Test]
|
[Test]
|
||||||
public void AppDataDirectory_path_test()
|
public void AppDataDirectory_path_test()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetAppDataPath().Should().BeEquivalentTo(@"C:\NzbDrone\".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetAppDataPath().Should().BeEquivalentTo(@"C:\Radarr\".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Config_path_test()
|
public void Config_path_test()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetConfigPath().Should().BeEquivalentTo(@"C:\NzbDrone\Config.xml".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetConfigPath().Should().BeEquivalentTo(@"C:\Radarr\Config.xml".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void Sandbox()
|
public void Sandbox()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetUpdateSandboxFolder().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetUpdateSandboxFolder().Should().BeEquivalentTo(@"C:\Temp\radarr_update\".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetUpdatePackageFolder()
|
public void GetUpdatePackageFolder()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetUpdatePackageFolder().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\NzbDrone\".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetUpdatePackageFolder().Should().BeEquivalentTo(@"C:\Temp\radarr_update\Radarr\".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetUpdateClientFolder()
|
public void GetUpdateClientFolder()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetUpdateClientFolder().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\NzbDrone\NzbDrone.Update\".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetUpdateClientFolder().Should().BeEquivalentTo(@"C:\Temp\radarr_update\Radarr\NzbDrone.Update\".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetUpdateClientExePath()
|
public void GetUpdateClientExePath()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\nzbdrone_update\Radarr.Update.exe".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetUpdateClientExePath().Should().BeEquivalentTo(@"C:\Temp\radarr_update\Radarr.Update.exe".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void GetUpdateLogFolder()
|
public void GetUpdateLogFolder()
|
||||||
{
|
{
|
||||||
GetIAppDirectoryInfo().GetUpdateLogFolder().Should().BeEquivalentTo(@"C:\NzbDrone\UpdateLogs\".AsOsAgnostic());
|
GetIAppDirectoryInfo().GetUpdateLogFolder().Should().BeEquivalentTo(@"C:\Radarr\UpdateLogs\".AsOsAgnostic());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
|||||||