mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-05 05:58:35 -05:00
Compare commits
456 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
daf9f50ac8 | ||
|
|
6b11013c1a | ||
|
|
0dd1f647d8 | ||
|
|
6999872ec3 | ||
|
|
83ccc0a765 | ||
|
|
bf4b06f620 | ||
|
|
8f290a11ce | ||
|
|
72fda0117f | ||
|
|
d1cfa51a46 | ||
|
|
d6a5f4c0dc | ||
|
|
124701c118 | ||
|
|
d1adc8abc1 | ||
|
|
0c2cfd6225 | ||
|
|
f280363df5 | ||
|
|
6ed9dcfc95 | ||
|
|
4008bd004f | ||
|
|
cbbdccca81 | ||
|
|
0168d8870c | ||
|
|
d6269099aa | ||
|
|
5548bd9c7e | ||
|
|
5c8483f393 | ||
|
|
b9a344992b | ||
|
|
a85a988b22 | ||
|
|
d9808a7550 | ||
|
|
92894e9301 | ||
|
|
e59a28b617 | ||
|
|
27429a1415 | ||
|
|
8f9e1b2eb7 | ||
|
|
663330e251 | ||
|
|
4432e5684a | ||
|
|
92ecc2d0d4 | ||
|
|
7ea897ef39 | ||
|
|
7a8df5ee91 | ||
|
|
4c851b458a | ||
|
|
43ad83cee4 | ||
|
|
6f69bfd9ce | ||
|
|
f2423fd8a1 | ||
|
|
845d5cbaf2 | ||
|
|
d1052ca7e0 | ||
|
|
d7c76a3b43 | ||
|
|
4c7f74b356 | ||
|
|
b3dc74a07b | ||
|
|
e9fa56a635 | ||
|
|
6729e94f14 | ||
|
|
71dc1b5310 | ||
|
|
fe8065a7ef | ||
|
|
60afb7f444 | ||
|
|
3945eafb76 | ||
|
|
763088e6a6 | ||
|
|
a6ac88d5da | ||
|
|
d35ebec8f9 | ||
|
|
aee2747220 | ||
|
|
eae68bd6ba | ||
|
|
1875cbcb52 | ||
|
|
92410fc1ef | ||
|
|
ee7e209a8b | ||
|
|
9bc1601939 | ||
|
|
190ec0a472 | ||
|
|
468f01d839 | ||
|
|
5bbbf602f9 | ||
|
|
b03d68b434 | ||
|
|
0298beac15 | ||
|
|
be6f047e31 | ||
|
|
e8206371e4 | ||
|
|
6609248fce | ||
|
|
0ae5c7f8aa | ||
|
|
02b6f63156 | ||
|
|
8ab3ebd5f6 | ||
|
|
2b665667af | ||
|
|
ad7fc240c7 | ||
|
|
aef878a0f2 | ||
|
|
2a967b62d9 | ||
|
|
19946684d5 | ||
|
|
4c5ca149ba | ||
|
|
54d6e0dc21 | ||
|
|
ecb1403776 | ||
|
|
7e5c6d1c04 | ||
|
|
96b140dee0 | ||
|
|
2e098b641f | ||
|
|
6678cb9d56 | ||
|
|
4b67405d16 | ||
|
|
7463a4abdc | ||
|
|
163523048b | ||
|
|
4892bc18f3 | ||
|
|
217b2436f2 | ||
|
|
a9247ba934 | ||
|
|
8b2a6ef825 | ||
|
|
320495671b | ||
|
|
5ab872afa0 | ||
|
|
7ecb31805e | ||
|
|
e8ebeb843c | ||
|
|
3840678913 | ||
|
|
da7082b17e | ||
|
|
6198f95e1e | ||
|
|
4075b1accb | ||
|
|
6d8a774443 | ||
|
|
76c7a6ce95 | ||
|
|
01bd0bdce0 | ||
|
|
fa908de6e9 | ||
|
|
f05a6c6f76 | ||
|
|
d86fb42d28 | ||
|
|
7a7ce47769 | ||
|
|
40e57845a7 | ||
|
|
884dedc9d1 | ||
|
|
8e1f4e14a2 | ||
|
|
1190742127 | ||
|
|
e6d481a2ba | ||
|
|
0958caf5ed | ||
|
|
e2761d967e | ||
|
|
b4f36be170 | ||
|
|
5e722b27f3 | ||
|
|
367a73ef29 | ||
|
|
9228bc28ff | ||
|
|
02e18be5e1 | ||
|
|
531ef59e0a | ||
|
|
54e03fb40a | ||
|
|
904bb9f85a | ||
|
|
b011e1a518 | ||
|
|
f83f71a950 | ||
|
|
4dbf5266ef | ||
|
|
05aac4e01e | ||
|
|
267c48f9a7 | ||
|
|
5168915a65 | ||
|
|
71017d0d55 | ||
|
|
a5db51a2c5 | ||
|
|
0bf2968e6a | ||
|
|
2ec5918f5e | ||
|
|
04f5a63cd7 | ||
|
|
43d8283f5b | ||
|
|
f8111121c4 | ||
|
|
b53b73c135 | ||
|
|
bd7b8a975b | ||
|
|
7ca765f276 | ||
|
|
b918a53af5 | ||
|
|
525809afc9 | ||
|
|
a7048cdc8e | ||
|
|
02888568bd | ||
|
|
203409f02f | ||
|
|
ecc8e6ac0e | ||
|
|
852636acda | ||
|
|
bc18369552 | ||
|
|
8f248a2219 | ||
|
|
0d8d5daff6 | ||
|
|
82857afed6 | ||
|
|
4e7f0a6a1e | ||
|
|
2a113f7f58 | ||
|
|
6b8b9e0238 | ||
|
|
1e3e4b4118 | ||
|
|
87dfbe34d4 | ||
|
|
c56bcfaf61 | ||
|
|
a947a1d88b | ||
|
|
ad0d5726ec | ||
|
|
c52ce58b6d | ||
|
|
a90356c6e7 | ||
|
|
5c78c7855b | ||
|
|
915ee650ee | ||
|
|
58bd12b083 | ||
|
|
ecc334360a | ||
|
|
309f8e0044 | ||
|
|
730652e3e1 | ||
|
|
1aed59d52e | ||
|
|
1f04343a4d | ||
|
|
70f8509f6e | ||
|
|
74a97296a5 | ||
|
|
45d3440443 | ||
|
|
c872ee16ab | ||
|
|
da473424f2 | ||
|
|
e0dc988f94 | ||
|
|
4021e6098c | ||
|
|
f521037669 | ||
|
|
246e9e421b | ||
|
|
8aaee09652 | ||
|
|
e36450a666 | ||
|
|
d84f31c116 | ||
|
|
e5fc51e9d7 | ||
|
|
291a72ec63 | ||
|
|
4dd5115b03 | ||
|
|
3bdb8407d2 | ||
|
|
a88055c491 | ||
|
|
8a676aeab4 | ||
|
|
d41276aa82 | ||
|
|
96cb0aa8db | ||
|
|
03e7889d5c | ||
|
|
5c161b884c | ||
|
|
f77cc43b7d | ||
|
|
bd709a7bdd | ||
|
|
c3832a85f7 | ||
|
|
52aa7a08d7 | ||
|
|
ee0358cf06 | ||
|
|
2344a50f6c | ||
|
|
a2774ce762 | ||
|
|
2cdf284578 | ||
|
|
3fd9e85236 | ||
|
|
f08eaa4e53 | ||
|
|
f47a6a889e | ||
|
|
14b32f30f0 | ||
|
|
902f67ef02 | ||
|
|
20fbea6e31 | ||
|
|
53261ad311 | ||
|
|
4686bc1fa6 | ||
|
|
0d806305c2 | ||
|
|
ee0623d68b | ||
|
|
0b9b28112d | ||
|
|
3ebe7dff45 | ||
|
|
7d4b665cd9 | ||
|
|
5b7224bf4c | ||
|
|
1b67c9c13d | ||
|
|
fe849d8805 | ||
|
|
07c3ff9710 | ||
|
|
f3e18ac355 | ||
|
|
2bafefa795 | ||
|
|
c9fcd4cecc | ||
|
|
343d9b10cf | ||
|
|
3d219c9382 | ||
|
|
031ed3f01e | ||
|
|
f20a30cfc2 | ||
|
|
b5dcfe0238 | ||
|
|
d169bb5e28 | ||
|
|
25429b5b19 | ||
|
|
9638eab564 | ||
|
|
c6b84660e3 | ||
|
|
cc61e669ef | ||
|
|
3a19741edb | ||
|
|
3c87fd45c3 | ||
|
|
d0a258ce28 | ||
|
|
1cac5799eb | ||
|
|
a56e4f3650 | ||
|
|
9970d2ee6f | ||
|
|
f2695e9305 | ||
|
|
d333f1b56b | ||
|
|
00f5b29caa | ||
|
|
16aa43c120 | ||
|
|
b2179d5b3e | ||
|
|
8e2e9fd5c9 | ||
|
|
2e3181779a | ||
|
|
8a270e49be | ||
|
|
32e26c804b | ||
|
|
5cf87be51e | ||
|
|
5c54b873bf | ||
|
|
5ca4811689 | ||
|
|
043e5966ff | ||
|
|
d69796d351 | ||
|
|
a2d5713477 | ||
|
|
29ec4d9a23 | ||
|
|
22517a7cd7 | ||
|
|
bcc4dd75cf | ||
|
|
97711ca82e | ||
|
|
e782237f27 | ||
|
|
52bb156c08 | ||
|
|
4361d82ddd | ||
|
|
017cf8f285 | ||
|
|
03cdf6ed5d | ||
|
|
cf347a8e90 | ||
|
|
f06afe43e1 | ||
|
|
fb301eb5c8 | ||
|
|
1562c3560b | ||
|
|
9813bc237f | ||
|
|
b39fe059c6 | ||
|
|
a56c770a8b | ||
|
|
e3bf0edad8 | ||
|
|
e35d9e4db3 | ||
|
|
c617d4321a | ||
|
|
0fd3a2881f | ||
|
|
0c1f7633de | ||
|
|
b7d5d49c84 | ||
|
|
9911b93ece | ||
|
|
eeaad00968 | ||
|
|
e1bb8459e3 | ||
|
|
65c3ac0cc0 | ||
|
|
413c02a80f | ||
|
|
80f118f304 | ||
|
|
5c0a10e16b | ||
|
|
d9b32261e7 | ||
|
|
8d8ce52193 | ||
|
|
1cc2e25cda | ||
|
|
4605c3fd30 | ||
|
|
ed7dc3f827 | ||
|
|
e69eeebdd8 | ||
|
|
5da5f1adc1 | ||
|
|
f47e92dec0 | ||
|
|
a894ca5171 | ||
|
|
5abe1140ae | ||
|
|
d34e14370c | ||
|
|
c4f4a3131c | ||
|
|
dcbd9b57f3 | ||
|
|
aad3b54a17 | ||
|
|
cde142a371 | ||
|
|
8bfc98ffc6 | ||
|
|
e46f21d566 | ||
|
|
0e45fdcdfd | ||
|
|
eec7af16d7 | ||
|
|
6532425902 | ||
|
|
44b896522c | ||
|
|
1b16ee44cb | ||
|
|
d5f608c28c | ||
|
|
555d8418e7 | ||
|
|
8c22e35da4 | ||
|
|
95a7924b31 | ||
|
|
5830bebd95 | ||
|
|
d32cf57c75 | ||
|
|
6d9242ebc5 | ||
|
|
cbc4f6a964 | ||
|
|
2a3b2b9556 | ||
|
|
53a219f12b | ||
|
|
48519dcfa0 | ||
|
|
92542c58fe | ||
|
|
7eafe730f9 | ||
|
|
494e72a996 | ||
|
|
84cc86f1d3 | ||
|
|
64479e2e5d | ||
|
|
13b523d9bd | ||
|
|
181881a21b | ||
|
|
86d11095ac | ||
|
|
927ba3cd9d | ||
|
|
6296fc1762 | ||
|
|
60fbe44724 | ||
|
|
29e45da431 | ||
|
|
d82e69eef4 | ||
|
|
8c7d557252 | ||
|
|
a56d6e5517 | ||
|
|
7548d9e975 | ||
|
|
b7e2bd9684 | ||
|
|
f0a243e3d3 | ||
|
|
6e108c9ef2 | ||
|
|
89edcc1924 | ||
|
|
8a6aca47a1 | ||
|
|
d03e5780b8 | ||
|
|
209d8f9b40 | ||
|
|
c257b1be3d | ||
|
|
2c48c8de2e | ||
|
|
a767ef6aed | ||
|
|
ad61d1dd03 | ||
|
|
33c3d187a0 | ||
|
|
4eb486d4e2 | ||
|
|
bfb6c167a4 | ||
|
|
44abf3bdf6 | ||
|
|
c950572592 | ||
|
|
3999cb13fd | ||
|
|
af65075f0c | ||
|
|
de2a2b465b | ||
|
|
cd7a77f02d | ||
|
|
f4a5394b63 | ||
|
|
3fb6a8dedb | ||
|
|
50c8f84eba | ||
|
|
2c7ecdee92 | ||
|
|
72390a793a | ||
|
|
04ad4e5d3e | ||
|
|
5ef9c6a433 | ||
|
|
e6baffc839 | ||
|
|
e361eb25a5 | ||
|
|
9b420e91c9 | ||
|
|
3a4bf971b2 | ||
|
|
1128691c5d | ||
|
|
15043aef3f | ||
|
|
2a3b4afa03 | ||
|
|
00a98efa81 | ||
|
|
f013dd7f0d | ||
|
|
7b91b1c769 | ||
|
|
5583cce322 | ||
|
|
b995c5f992 | ||
|
|
214ac4a53d | ||
|
|
fc7e87f0df | ||
|
|
c0f2f59fc1 | ||
|
|
b90a847a6f | ||
|
|
a58bb385f5 | ||
|
|
9754baeb1c | ||
|
|
ffcd154966 | ||
|
|
97cfe9488c | ||
|
|
374b6f616a | ||
|
|
e2f51595b6 | ||
|
|
04091a16aa | ||
|
|
9d9d2fd9a2 | ||
|
|
5746115331 | ||
|
|
42f1a4926c | ||
|
|
7d87fd461b | ||
|
|
1ba9976979 | ||
|
|
659c199043 | ||
|
|
81a3f53226 | ||
|
|
1cbff28f67 | ||
|
|
8e15acbf30 | ||
|
|
e07be60db6 | ||
|
|
539c9662ff | ||
|
|
b396014f8d | ||
|
|
1db32415b6 | ||
|
|
b24629db6b | ||
|
|
9b5cdcf8fb | ||
|
|
4831415d14 | ||
|
|
a4c51f0b20 | ||
|
|
ec3ba1fb93 | ||
|
|
61966f7036 | ||
|
|
4f69e81841 | ||
|
|
d0d90581df | ||
|
|
8ea5c27633 | ||
|
|
517500fdf3 | ||
|
|
c4c1c9b6ab | ||
|
|
2388889ede | ||
|
|
55cfe878d7 | ||
|
|
a2daaee468 | ||
|
|
2c360e395e | ||
|
|
399cfee594 | ||
|
|
be646ae6ab | ||
|
|
b470253d9f | ||
|
|
b83c493492 | ||
|
|
991277bb01 | ||
|
|
5626013b81 | ||
|
|
2810d37758 | ||
|
|
c2f08f01e0 | ||
|
|
17ff087e06 | ||
|
|
77de565b7c | ||
|
|
54d238aa4d | ||
|
|
379d09f8cc | ||
|
|
00de72b127 | ||
|
|
f9c84fa7dd | ||
|
|
c8e46691bb | ||
|
|
df1bb636e5 | ||
|
|
ff886fad0d | ||
|
|
6dbee7a413 | ||
|
|
3f8fcd7172 | ||
|
|
d94f7388e6 | ||
|
|
ad8b49fea8 | ||
|
|
ce00270c12 | ||
|
|
8c501f8f58 | ||
|
|
ce313ebc65 | ||
|
|
887ad881a2 | ||
|
|
ce40827552 | ||
|
|
2777d89482 | ||
|
|
727b300a0e | ||
|
|
652b021a8e | ||
|
|
fdf33acfbb | ||
|
|
b001bc9b6f | ||
|
|
8802cb1d8c | ||
|
|
e19a2fbae7 | ||
|
|
53e38f98f9 | ||
|
|
e783e227f6 | ||
|
|
f3dfbe4181 | ||
|
|
bcd8ca8bc4 | ||
|
|
816d6a63cd | ||
|
|
88d3f25700 | ||
|
|
80f69b11db | ||
|
|
81a11f20c8 | ||
|
|
9e2a839953 | ||
|
|
3cefcde270 | ||
|
|
87a1eacfe7 | ||
|
|
7cbc1a8419 | ||
|
|
7b5570eb0b | ||
|
|
1a43a4dcf0 | ||
|
|
2c2a6592c7 | ||
|
|
f31de6ee4e | ||
|
|
8fcd1f6b6c | ||
|
|
d7f3a473d7 | ||
|
|
ab2eb0c94e | ||
|
|
e51f4fc45a | ||
|
|
65278120e2 | ||
|
|
2eed355e9c | ||
|
|
018955f4d5 | ||
|
|
12fd63c1cf |
13
.gitignore
vendored
13
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
#Compiled python
|
||||
# Compiled python
|
||||
*.py[cod]
|
||||
|
||||
# Working folders for Win build
|
||||
@@ -7,6 +7,13 @@ dist/
|
||||
locale/
|
||||
srcdist/
|
||||
|
||||
# Snapcraft
|
||||
parts/
|
||||
prime/
|
||||
stage/
|
||||
snap/.snapcraft/
|
||||
*.snap
|
||||
|
||||
# Generated email templates
|
||||
email/*.tmpl
|
||||
|
||||
@@ -16,12 +23,14 @@ SABnzbd*.exe
|
||||
SABnzbd*.gz
|
||||
SABnzbd*.dmg
|
||||
|
||||
# WingIDE project files
|
||||
# WingIDE/PyCharm project files
|
||||
*.wp[ru]
|
||||
.idea
|
||||
|
||||
# Testing folders
|
||||
.cache
|
||||
.xprocess
|
||||
tests/cache
|
||||
|
||||
# General junk
|
||||
*.keep
|
||||
|
||||
10
.lgtm.yml
Normal file
10
.lgtm.yml
Normal file
@@ -0,0 +1,10 @@
|
||||
path_classifiers:
|
||||
oldinterfaces:
|
||||
- interfaces/smpl
|
||||
- interfaces/Plush
|
||||
library:
|
||||
- cherrypy
|
||||
- gntp
|
||||
- six
|
||||
- "*knockout*"
|
||||
- "**/*min*"
|
||||
41
.travis.yml
41
.travis.yml
@@ -1,15 +1,38 @@
|
||||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
before_install:
|
||||
- sudo add-apt-repository ppa:jcfp -y
|
||||
- sudo apt-get update -q
|
||||
- sudo apt-get install sabnzbdplus -y
|
||||
# Include the host/username/password for the test-servers
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
language: python
|
||||
env:
|
||||
- secure: iMXx74c2eUhDPJrukvAFxCFNWYDk8JB2alQ89Hc3T1ckXfDS37vgUplTze1aGo+AefUkDSFmTreFk9hVJvd4SQTHz4wS+qp7HQJFWECjR16jZwobIbukNPNU1JamozZoOa2igoVIJ8/tVIdIpfcsGfzj9WogwUlpChWHIiI8SM/Fc0WK+M9rDPKBpgjEN2yom73jbC2ETxuQ/HMdMNnNS9S1vS7MY+2W69+xi5Kl9hP0HUBIG/JtVXu1a4SO5NgqL5aW4cgKtgg0IjpedBRMcC0rpyEz+lDtl2jXYR+mXQEO8uNZOwzV7SLrq/ROGwW+DMtfiiySKxmuYoL/JOm4kcLyEup51dgnTQc1RdEcaYfk0twDry67prnQ/sXAQphzjl0StrTpLfzWUsCvgXRp7+XWhX9ElHN4KelOcAc7YeTSXoPY6bENk8LSy1woJ2HbH5TkSvtVJ6xrmssV3bEMp7aGx7qv1D/uvyAEMulB79WwdLyoDxmG9eIgXfp3nICko4p9kisrzK0hVCGDRCHSYgTnDBGTMJU/SlRRNUepmXHXQUrqWyTWvy2HTMUTjuYBaaNcUqZvyHyyaDq0MNBotwDCmes5o8fZu456lB/B26LwUu7cOSbCw19ePlGBNnbjA9NmNoQGOo66era3NEVJLYv+H91PAPQyWpzOt0X53Gk=
|
||||
- secure: Cryq31K8wxt+q212/q7IHlLf4flH4riaiHssxR0/VfGACtMp3jOAVZ5RAOvX03LPYp+BuX2KAHFXDHeGHGzYmESkpzPCToZ3GpaOwP3ymc3RNeU6bd98yEQyQtM/wtY4uxPUWdwz5Uw5kkeynxw3y/QFsYceipB3u3oCvfB9n8SqWShjWpBFyFhSKS/SJjUqgNcAaA0pTP8l/crquZNhkug/J8Nlc/nC0H6ZSJKGu8UhkhZ0VSEY8dofZZkGG6YCIIEAqGasQqkra6x/D0uECfQnnDrTqekvklUG31/zy+awQXl+0NjLTIKyl2rHp5AUpSTlbPO2mDYdbWEWcRYmNsEEiGfvy3R9kGGbNijB5b57jvgsJapH8DkGRWseISdCBWqLH7C/OafNuMGzQ4s3UCN1aazqqN/IAJplVjSWiKA76Nbh385x88E8RaH7Gnvx1ZK88Lgf7Bz8Ar/O1dMviyP8WbM/vQQkVMdOk89y5O6G8ZwHFoj/v8w383irWMN2iU0Mf7GKW91ughpKrrKbXCmkT1bR9+tNYpKWU1O+1jgnGk65149GNC0K+9exWt0TK3pNSUa7b2nVzxeAqdCJjCoKBi2pLiRxYVI50V80M2p5Xw+5iiSiOhTLzFLT3YRi2VBjjBFa8BHJHBS9Pua4DaFc1w06XNej6K8rRV5We0s=
|
||||
- secure: O/8jVULQmqOLHkvIW21IsVuL7/B+3MhgRFaT4wltxk/x7TarEsQyahXdStsQ+I53mMRbSfsArdCHXwgIm13wROXfcEdt7iM0f2tGWUsm32q73RrjBsKzb8SRTKZNkL1dOjpgkdEHejZdVckKlg0GlpJTTowOdfi+SYinj4Hj52vrV9waHk296njKw98W5Y35lEtSH3DcAU2NHrDi7YqQvjiBzj9MviG1qpJZJ1RMxKrTXXCqjlYcxr8FwO2kGpMnkTFIDywi4OspLQ1InEGhM9MdrY9tqGVzW631nX1uRV8aNhl+bLhtRs0i3QtOisWMWO5z5SQN6pOqUWx3nnwLPJzuoL+wGMDC2tdVRmH1+cuYCwq97curNq4hv9FBs7P/RS4e22WAoW0jtLWnx/5voVes1EsQE5iW/iG0z4ih3MIk3dHN6h8HcNr83DRxOW8JKmA79IbtcVFReZJ2AXQhx6VmvdUaIi3IKpW79K89ZzEuoEEO5Eyti2LLz9rti0iVknHejGYKWDCABflGaKjnj62tpUsAB9EsPPuwBegoKRd2bVy3kJ+RWGcMc4QfzsEq39z2ftQ8XJ800ZuuQvl7nsk86Dso+Hgr/T+5xU2wU6vFbwoDCWsxdnK2LXNpf3ci5PBZFhG9zLMRk+yFyAfh8OdQr19lxclay0X6na1K8i0=
|
||||
- os: osx
|
||||
env:
|
||||
- HOMEBREW_NO_AUTO_UPDATE=1
|
||||
- secure: iMXx74c2eUhDPJrukvAFxCFNWYDk8JB2alQ89Hc3T1ckXfDS37vgUplTze1aGo+AefUkDSFmTreFk9hVJvd4SQTHz4wS+qp7HQJFWECjR16jZwobIbukNPNU1JamozZoOa2igoVIJ8/tVIdIpfcsGfzj9WogwUlpChWHIiI8SM/Fc0WK+M9rDPKBpgjEN2yom73jbC2ETxuQ/HMdMNnNS9S1vS7MY+2W69+xi5Kl9hP0HUBIG/JtVXu1a4SO5NgqL5aW4cgKtgg0IjpedBRMcC0rpyEz+lDtl2jXYR+mXQEO8uNZOwzV7SLrq/ROGwW+DMtfiiySKxmuYoL/JOm4kcLyEup51dgnTQc1RdEcaYfk0twDry67prnQ/sXAQphzjl0StrTpLfzWUsCvgXRp7+XWhX9ElHN4KelOcAc7YeTSXoPY6bENk8LSy1woJ2HbH5TkSvtVJ6xrmssV3bEMp7aGx7qv1D/uvyAEMulB79WwdLyoDxmG9eIgXfp3nICko4p9kisrzK0hVCGDRCHSYgTnDBGTMJU/SlRRNUepmXHXQUrqWyTWvy2HTMUTjuYBaaNcUqZvyHyyaDq0MNBotwDCmes5o8fZu456lB/B26LwUu7cOSbCw19ePlGBNnbjA9NmNoQGOo66era3NEVJLYv+H91PAPQyWpzOt0X53Gk=
|
||||
- secure: Yc9lY76AEXwG1uf+pg1xyTDo3gg8zsIqJ6K/WwJr7zStLGU6J5Qf/iW7jFzGxTbq0Kc6/dgb4VInYwlcyhjsRE3DI5LDqKiP2dZATP07crwZnzwrhxDPdYA+s1sI9YDJN90aZZm48DbUPFR7DPZjkDqyRJMRCFstZ/fJ//kSDVJvMjEOPEixzT6k5sRW2j9sctzEzqCHhroKaz5/m1sSBWa+pJx7C4A76NQFrMZEmlnWf0qKoUERaGn4hv5I3/38KQa0wy1q43obMoltmaFrbyIV4tx9M60kSGfaQdVVgwYgxPsINZeESJk+N4JCQSUKr0biAcKamPfgIbfEN4FbCGiFzHf5w/eIyUG0yUg42NtzzMVVS4I0s/aaPGKrjDrJNZ9bj8/oQjWDHtlRx7nrREdPI2Ch/MF8e8t03tDm5unhLIa6Fk1Ic9UbgwjtUqDvAne5+kwhsh8WpyU+VnttP/LyKTi2eqtADF6kPuxKM9DbTFE/IvCE2DXDFc6OOzAWoqhnbBgPrX0L5OlQLWoL13oi+yJMnBsF4Rd3rhqpNJ2sJTukeHT9z5yhkBEXHe9PatT0hiXZ7AxHsgX292k9Ti4se3pPxETkbR3r8iOklItMu1PViQsvfRyOFu+XloqMaPO31z48LmcPOps+/DYkbRyaTqBMdmPPRJghZ9lzvno=
|
||||
- secure: RsFCZq/1Q6/++mgCZB6WsnIcbBsBwHFn6nfwC+vAomxbPtHevdiC930eIn8jKDza6Vmd4LoaMklvNOBEK1QpphbZXhKZIecakZOb+KyHVanSbQwErZCuVQdEo2p8cHJfuEh3guxmkE2OjAiBnSsgHlLmGiLAUF5GW5NPDLASPXIxXbBKOIKv7sTWj6tYYfVdUs1pQVz3Z+MkhRoS2uhVBOvQ14axtAtil1WmhgEJzuHAvjW29b1Q6l2goIuqoglqwKSna437CCt6mMFt6IVQqi36/lwXw0cYCLyJq3PURGDce6FdeQlwW0YfOXwT9k6BH+HcNuYmCSAbuL5hqC994avYbpemsBKKGfBK0Q8xZe0lQpS+R1C+iF3XXnPLU8B5TtALiBcFVRd3s291mxigxYqjkXbkgwVNAgkXKze+MhvrEQgoQwwhU3SbnmrZN8U6wW58MDYzjDxPaZdE5tUI+ROkfWeMRqtQrGNSJX6AwjkCrurW1/n0DXMlsUFnq4WGWF9nk8aHVzD8Y0cetQ+tLj3HxuxNqmAquewn+Z7pL41YTHlSTZ9+nHhI0GLQem6ANWL/4xJO8nBeOUETv1nULgbMyNOVaS9yBA7b2omE+Zuf8CMRCr9ID+Eeqtx1cUSMkWRymTdZvyPFPLjQ9KASTc7aCM7Cfc0aBceOoOOxMRw=
|
||||
addons:
|
||||
chrome: stable
|
||||
|
||||
before_script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
brew cask install chromedriver;
|
||||
else
|
||||
sudo add-apt-repository ppa:jcfp -y;
|
||||
sudo apt-get update -q;
|
||||
sudo apt-get install unrar p7zip-full par2 chromium-chromedriver -y;
|
||||
ln -s /usr/lib/chromium-browser/chromedriver ~/bin/chromedriver;
|
||||
fi;
|
||||
|
||||
install:
|
||||
- pip install --upgrade -r tests/requirements.txt
|
||||
|
||||
script:
|
||||
- pytest
|
||||
- python ./tests/test_functional.py
|
||||
|
||||
notifications:
|
||||
email:
|
||||
on_success: never
|
||||
on_failure: always
|
||||
on_failure: always
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
*******************************************
|
||||
*** This is SABnzbd 2.4.0 ***
|
||||
*** This is SABnzbd 2.3.8 ***
|
||||
*******************************************
|
||||
SABnzbd is an open-source cross-platform binary newsreader.
|
||||
It simplifies the process of downloading from Usenet dramatically,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
(c) Copyright 2007-2017 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
(c) Copyright 2007-2019 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
The SABnzbd-team is:
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
SABnzbd 2.3.1
|
||||
SABnzbd 2.3.8
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
(c) Copyright 2007-2017 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
(c) Copyright 2007-2019 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -66,3 +66,7 @@
|
||||
Config->Special->wait_for_dfolder to 1.
|
||||
SABnzbd will appear to hang until the drive is mounted.
|
||||
|
||||
- If you experience speed-drops to KB/s when using a VPN, try setting the number of connections
|
||||
to your servers to a total of 7. There is a CPU-usage reduction feature in SABnzbd that
|
||||
gets confused by the way some VPN's handle the state of a connection. Below 8 connections
|
||||
this feature is not active.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(c) Copyright 2007-2017 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
(c) Copyright 2007-2019 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 2.3.2RC2
|
||||
Summary: SABnzbd-2.3.2RC2
|
||||
Version: 2.3.8
|
||||
Summary: SABnzbd-2.3.8
|
||||
Home-page: https://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
SABnzbd - The automated Usenet download tool
|
||||
============================================
|
||||
|
||||
[](https://isitmaintained.com/project/sabnzbd/sabnzbd "Average time to resolve an issue")
|
||||
[](https://travis-ci.org/sabnzbd/sabnzbd)
|
||||
[](https://ci.appveyor.com/project/Safihre/sabnzbd)
|
||||
[](https://snapcraft.io/sabnzbd)
|
||||
[](https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html)
|
||||
|
||||
SABnzbd is an Open Source Binary Newsreader written in Python.
|
||||
|
||||
It's totally free, incredibly easy to use, and works practically everywhere.
|
||||
@@ -21,7 +27,6 @@ Optional:
|
||||
- `python-cryptography` (enables certificate generation and detection of encrypted RAR-files during download)
|
||||
- `python-dbus` (enable option to Shutdown/Restart/Standby PC on queue finish)
|
||||
- `7zip`
|
||||
- `unzip`
|
||||
|
||||
Your package manager should supply these. If not, we've got links in our more in-depth [installation guide](https://github.com/sabnzbd/sabnzbd/blob/master/INSTALL.txt).
|
||||
|
||||
|
||||
45
README.mkd
45
README.mkd
@@ -1,37 +1,16 @@
|
||||
Release Notes - SABnzbd 2.3.2 RC 2
|
||||
Release Notes - SABnzbd 2.3.8
|
||||
=========================================================
|
||||
|
||||
## Changes since 2.3.2 RC 1
|
||||
- Simplify Config pages by hiding Advanced Settings
|
||||
- Automatically set Article Cache to 25% of system memory (max. 2GB)
|
||||
- Added Hebrew date-time texts
|
||||
- Added option '%dn' to Date Sorting to rename files as job name
|
||||
- Added 'Job Name as Folder Name' as Sorting Preset for de-obfuscation
|
||||
- Add per-day download-statistics to 'server_stats' API-call
|
||||
- Having 'Download all par2' enabled would result in disappearing jobs
|
||||
- Pre-queue scripts would fail to run
|
||||
|
||||
## Changes since 2.3.1
|
||||
- SABYenc updated to 3.3.2 to fix rare crash during downloading
|
||||
- Minor updates of SABYenc (such as 3.3.2) are no longer mandatory
|
||||
- Server usage graphs are now linked to make comparing servers easier
|
||||
- First article of each file is downloaded first to identify filenames
|
||||
- Jobs finished by Direct Unpack will be post-processed first
|
||||
- URLs that fail to fetch due to server errors will only be retried 10x
|
||||
- Delay between URL retries increases when not specified by server
|
||||
- Job password entered by user is always shown in History
|
||||
- If available, 7zip will be used instead of unzip
|
||||
|
||||
## Bugfixes since 2.3.1
|
||||
- Dropped connections could result in stalled downloads
|
||||
- Pre-queue script output was not always parsed correctly
|
||||
- Notifications were always send for 'Default' category
|
||||
- 'History Retention' also checked on start of program
|
||||
- macOS: Restore compatibility with macOS 10.11.6 on some systems
|
||||
- Windows: Unpacking could fail due to paths not being quoted
|
||||
- Windows: Complete folder in root of drive could crash post-processing
|
||||
- Windows: Automatically correct 'Extra Par2 Parameters' for MultiPar
|
||||
- Windows: Prevent potential pause/unpause loop after tray icon click
|
||||
## Improvements and bug fixes since 2.3.7
|
||||
- Changes to newsserver configuration could be delayed
|
||||
- Filenames would not be sanitized when using "Make Windows compatible"
|
||||
- Sorting could fail on root-folders
|
||||
- 7z-files were not listed as supported NZB archives
|
||||
- SSL cipher settings were ignored during server test
|
||||
- Windows: update 7zip to 19.00
|
||||
- Windows: update MultiPar to v1.3.0.4
|
||||
- Windows and macOS: update Python to 2.7.16
|
||||
- Windows and macOS: update UnRar to 5.70
|
||||
|
||||
## Upgrading from 2.2.x and older
|
||||
- Finish queue
|
||||
@@ -57,4 +36,4 @@ Release Notes - SABnzbd 2.3.2 RC 2
|
||||
that automatically verify, repair, extract and clean up posts downloaded
|
||||
from Usenet.
|
||||
|
||||
(c) Copyright 2007-2017 by "The SABnzbd-team" \<team@sabnzbd.org\>
|
||||
(c) Copyright 2007-2019 by "The SABnzbd-team" \<team@sabnzbd.org\>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -20,7 +20,6 @@ if sys.version_info[:2] < (2, 6) or sys.version_info[:2] >= (3, 0):
|
||||
print "Sorry, requires Python 2.6 or 2.7."
|
||||
sys.exit(1)
|
||||
|
||||
import os
|
||||
import time
|
||||
import subprocess
|
||||
|
||||
|
||||
117
SABnzbd.py
117
SABnzbd.py
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -44,7 +44,7 @@ import re
|
||||
|
||||
try:
|
||||
import Cheetah
|
||||
if Cheetah.Version[0] != '2':
|
||||
if Cheetah.Version[0] < '2':
|
||||
raise ValueError
|
||||
except ValueError:
|
||||
print "Sorry, requires Python module Cheetah 2.0rc7 or higher."
|
||||
@@ -173,7 +173,7 @@ class guiHandler(logging.Handler):
|
||||
|
||||
def print_help():
|
||||
print
|
||||
print "Usage: %s [-f <configfile>] <other options>" % sabnzbd.MY_NAME
|
||||
print "Usage: %s [-f <configfile>] <other options> [NZB (or related) file]" % sabnzbd.MY_NAME
|
||||
print
|
||||
print "Options marked [*] are stored in the config file"
|
||||
print
|
||||
@@ -182,7 +182,7 @@ def print_help():
|
||||
print " -s --server <srv:port> Listen on server:port [*]"
|
||||
print " -t --templates <templ> Template directory [*]"
|
||||
print
|
||||
print " -l --logging <0..2> Set logging level (-1=off, 0= least, 2= most) [*]"
|
||||
print " -l --logging <-1..2> Set logging level (-1=off, 0= least, 2= most) [*]"
|
||||
print " -w --weblogging Enable cherrypy access logging"
|
||||
print
|
||||
print " -b --browser <0..1> Auto browser launch (0= off, 1= on) [*]"
|
||||
@@ -204,15 +204,20 @@ def print_help():
|
||||
print " --ipv6_hosting <0|1> Listen on IPv6 address [::1] [*]"
|
||||
print " --no-login Start with username and password reset"
|
||||
print " --log-all Log all article handling (for developers)"
|
||||
print " --disable-file-log Logging is only written to console"
|
||||
print " --console Force console logging for OSX app"
|
||||
print " --new Run a new instance of SABnzbd"
|
||||
print ""
|
||||
print "NZB (or related) file:"
|
||||
print " NZB or compressed NZB file, with extension .nzb, .zip, .rar, .7z, .gz, or .bz2"
|
||||
print ""
|
||||
|
||||
|
||||
def print_version():
|
||||
print """
|
||||
%s-%s
|
||||
|
||||
Copyright (C) 2008-2017, The SABnzbd-Team <team@sabnzbd.org>
|
||||
Copyright (C) 2007-2019, The SABnzbd-Team <team@sabnzbd.org>
|
||||
SABnzbd comes with ABSOLUTELY NO WARRANTY.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions. It is licensed under the
|
||||
@@ -497,7 +502,7 @@ def all_localhosts():
|
||||
def check_resolve(host):
|
||||
""" Return True if 'host' resolves """
|
||||
try:
|
||||
dummy = socket.getaddrinfo(host, None)
|
||||
socket.getaddrinfo(host, None)
|
||||
except:
|
||||
# Does not resolve
|
||||
return False
|
||||
@@ -593,7 +598,7 @@ def get_webhost(cherryhost, cherryport, https_port):
|
||||
cherryhost = cherryhost.strip('[]')
|
||||
else:
|
||||
try:
|
||||
info = socket.getaddrinfo(cherryhost, None)
|
||||
socket.getaddrinfo(cherryhost, None)
|
||||
except:
|
||||
cherryhost = cherryhost.strip('[]')
|
||||
|
||||
@@ -654,12 +659,12 @@ def attach_server(host, port, cert=None, key=None, chain=None):
|
||||
def is_sabnzbd_running(url):
|
||||
""" Return True when there's already a SABnzbd instance running. """
|
||||
try:
|
||||
url = '%s&mode=version' % (url)
|
||||
url = '%s&mode=version' % url
|
||||
# Do this without certificate verification, few installations will have that
|
||||
prev = sabnzbd.set_https_verification(False)
|
||||
ver = get_from_url(url)
|
||||
sabnzbd.set_https_verification(prev)
|
||||
return (ver and (re.search(r'\d+\.\d+\.', ver) or ver.strip() == sabnzbd.__version__))
|
||||
return ver and (re.search(r'\d+\.\d+\.', ver) or ver.strip() == sabnzbd.__version__)
|
||||
except:
|
||||
return False
|
||||
|
||||
@@ -723,7 +728,7 @@ def evaluate_inipath(path):
|
||||
return path
|
||||
|
||||
|
||||
def commandline_handler(frozen=True):
|
||||
def commandline_handler():
|
||||
""" Split win32-service commands are true parameters
|
||||
Returns:
|
||||
service, sab_opts, serv_opts, upload_nzbs
|
||||
@@ -756,7 +761,7 @@ def commandline_handler(frozen=True):
|
||||
opts, args = getopt.getopt(info, "phdvncwl:s:f:t:b:2:",
|
||||
['pause', 'help', 'daemon', 'nobrowser', 'clean', 'logging=',
|
||||
'weblogging', 'server=', 'templates', 'ipv6_hosting=',
|
||||
'template2', 'browser=', 'config-file=', 'force',
|
||||
'template2', 'browser=', 'config-file=', 'force', 'disable-file-log',
|
||||
'version', 'https=', 'autorestarted', 'repair', 'repair-all',
|
||||
'log-all', 'no-login', 'pid=', 'new', 'console', 'pidfile=',
|
||||
# Below Win32 Service options
|
||||
@@ -775,7 +780,7 @@ def commandline_handler(frozen=True):
|
||||
if not service:
|
||||
# Get and remove any NZB file names
|
||||
for entry in args:
|
||||
if get_ext(entry) in ('.nzb', '.zip', '.rar', '.gz', '.bz2'):
|
||||
if get_ext(entry) in VALID_NZB_FILES + VALID_ARCHIVES:
|
||||
upload_nzbs.append(os.path.abspath(entry))
|
||||
|
||||
for opt, arg in opts:
|
||||
@@ -819,11 +824,11 @@ def main():
|
||||
cherrypylogging = None
|
||||
clean_up = False
|
||||
logging_level = None
|
||||
no_file_log = False
|
||||
web_dir = None
|
||||
vista_plus = False
|
||||
win64 = False
|
||||
repair = 0
|
||||
api_url = None
|
||||
no_login = False
|
||||
sabnzbd.RESTART_ARGS = [sys.argv[0]]
|
||||
pid_path = None
|
||||
@@ -859,9 +864,9 @@ def main():
|
||||
elif opt in ('-b', '--browser'):
|
||||
try:
|
||||
autobrowser = bool(int(arg))
|
||||
except:
|
||||
except ValueError:
|
||||
autobrowser = True
|
||||
elif opt in ('--autorestarted', ):
|
||||
elif opt == '--autorestarted':
|
||||
autorestarted = True
|
||||
elif opt in ('-c', '--clean'):
|
||||
clean_up = True
|
||||
@@ -880,34 +885,36 @@ def main():
|
||||
exit_sab(0)
|
||||
elif opt in ('-p', '--pause'):
|
||||
pause = True
|
||||
elif opt in ('--https',):
|
||||
elif opt == '--https':
|
||||
https_port = int(arg)
|
||||
sabnzbd.RESTART_ARGS.append(opt)
|
||||
sabnzbd.RESTART_ARGS.append(arg)
|
||||
elif opt in ('--repair',):
|
||||
elif opt == '--repair':
|
||||
repair = 1
|
||||
pause = True
|
||||
elif opt in ('--repair-all',):
|
||||
elif opt == '--repair-all':
|
||||
repair = 2
|
||||
pause = True
|
||||
elif opt in ('--log-all',):
|
||||
elif opt == '--log-all':
|
||||
sabnzbd.LOG_ALL = True
|
||||
elif opt in ('--no-login',):
|
||||
elif opt == '--disable-file-log':
|
||||
no_file_log = True
|
||||
elif opt == '--no-login':
|
||||
no_login = True
|
||||
elif opt in ('--pid',):
|
||||
elif opt == '--pid':
|
||||
pid_path = arg
|
||||
sabnzbd.RESTART_ARGS.append(opt)
|
||||
sabnzbd.RESTART_ARGS.append(arg)
|
||||
elif opt in ('--pidfile',):
|
||||
elif opt == '--pidfile':
|
||||
pid_file = arg
|
||||
sabnzbd.RESTART_ARGS.append(opt)
|
||||
sabnzbd.RESTART_ARGS.append(arg)
|
||||
elif opt in ('--new',):
|
||||
elif opt == '--new':
|
||||
new_instance = True
|
||||
elif opt in ('--console',):
|
||||
elif opt == '--console':
|
||||
sabnzbd.RESTART_ARGS.append(opt)
|
||||
osx_console = True
|
||||
elif opt in ('--ipv6_hosting',):
|
||||
elif opt == '--ipv6_hosting':
|
||||
ipv6_hosting = arg
|
||||
|
||||
sabnzbd.MY_FULLNAME = os.path.normpath(os.path.abspath(sabnzbd.MY_FULLNAME))
|
||||
@@ -998,13 +1005,13 @@ def main():
|
||||
if enable_https and https_port:
|
||||
try:
|
||||
cherrypy.process.servers.check_port(cherryhost, https_port, timeout=0.05)
|
||||
except IOError, error:
|
||||
except IOError:
|
||||
Bail_Out(browserhost, cherryport)
|
||||
except:
|
||||
Bail_Out(browserhost, cherryport, '49')
|
||||
try:
|
||||
cherrypy.process.servers.check_port(cherryhost, cherryport, timeout=0.05)
|
||||
except IOError, error:
|
||||
except IOError:
|
||||
Bail_Out(browserhost, cherryport)
|
||||
except:
|
||||
Bail_Out(browserhost, cherryport, '49')
|
||||
@@ -1041,7 +1048,7 @@ def main():
|
||||
else:
|
||||
# In case HTTPS == HTTP port
|
||||
cherryport = newport
|
||||
sabnzbd.cfg.port.set(newport)
|
||||
sabnzbd.cfg.cherryport.set(newport)
|
||||
except:
|
||||
# Something else wrong, probably badly specified host
|
||||
Bail_Out(browserhost, cherryport, '49')
|
||||
@@ -1072,11 +1079,7 @@ def main():
|
||||
# We found a port, now we never check again
|
||||
sabnzbd.cfg.fixed_ports.set(True)
|
||||
|
||||
if logging_level is None:
|
||||
logging_level = sabnzbd.cfg.log_level()
|
||||
else:
|
||||
sabnzbd.cfg.log_level.set(logging_level)
|
||||
|
||||
# Logging-checks
|
||||
logdir = sabnzbd.cfg.log_dir.get_path()
|
||||
if fork and not logdir:
|
||||
print "Error:"
|
||||
@@ -1095,19 +1098,24 @@ def main():
|
||||
# Prevent the logger from raising exceptions
|
||||
# primarily to reduce the fallout of Python issue 4749
|
||||
logging.raiseExceptions = 0
|
||||
|
||||
# Log-related constants we always need
|
||||
if logging_level is None:
|
||||
logging_level = sabnzbd.cfg.log_level()
|
||||
else:
|
||||
sabnzbd.cfg.log_level.set(logging_level)
|
||||
sabnzbd.LOGFILE = os.path.join(logdir, DEF_LOG_FILE)
|
||||
logformat = '%(asctime)s::%(levelname)s::[%(module)s:%(lineno)d] %(message)s'
|
||||
logger.setLevel(LOGLEVELS[logging_level + 1])
|
||||
|
||||
try:
|
||||
rollover_log = logging.handlers.RotatingFileHandler(
|
||||
sabnzbd.LOGFILE, 'a+',
|
||||
sabnzbd.cfg.log_size.get_int(),
|
||||
sabnzbd.cfg.log_backups())
|
||||
|
||||
logformat = '%(asctime)s::%(levelname)s::[%(module)s:%(lineno)d] %(message)s'
|
||||
rollover_log.setFormatter(logging.Formatter(logformat))
|
||||
sabnzbd.LOGHANDLER = rollover_log
|
||||
logger.addHandler(rollover_log)
|
||||
logger.setLevel(LOGLEVELS[logging_level + 1])
|
||||
if not no_file_log:
|
||||
rollover_log = logging.handlers.RotatingFileHandler(
|
||||
sabnzbd.LOGFILE, 'a+',
|
||||
sabnzbd.cfg.log_size.get_int(),
|
||||
sabnzbd.cfg.log_backups())
|
||||
rollover_log.setFormatter(logging.Formatter(logformat))
|
||||
logger.addHandler(rollover_log)
|
||||
|
||||
except IOError:
|
||||
print "Error:"
|
||||
@@ -1137,6 +1145,8 @@ def main():
|
||||
console.setLevel(LOGLEVELS[logging_level + 1])
|
||||
console.setFormatter(logging.Formatter(logformat))
|
||||
logger.addHandler(console)
|
||||
if no_file_log:
|
||||
logging.info('Console logging only')
|
||||
if noConsoleLoggingOSX:
|
||||
logging.info('Console logging for OSX App disabled')
|
||||
so = file('/dev/null', 'a+')
|
||||
@@ -1169,7 +1179,7 @@ def main():
|
||||
logging.info('Preferred encoding = ERROR')
|
||||
preferredencoding = ''
|
||||
|
||||
# On Linux/FreeBSD/Unix "UTF-8" is strongly, strongly adviced:
|
||||
# On Linux/FreeBSD/Unix "UTF-8" is strongly, strongly advised:
|
||||
if not sabnzbd.WIN32 and not sabnzbd.DARWIN and not ('utf' in preferredencoding.lower() and '8' in preferredencoding.lower()):
|
||||
logging.warning(T("SABnzbd was started with encoding %s, this should be UTF-8. Expect problems with Unicoded file and directory names in downloads.") % preferredencoding)
|
||||
|
||||
@@ -1226,8 +1236,6 @@ def main():
|
||||
|
||||
if autobrowser is not None:
|
||||
sabnzbd.cfg.autobrowser.set(autobrowser)
|
||||
else:
|
||||
autobrowser = sabnzbd.cfg.autobrowser()
|
||||
|
||||
if not sabnzbd.WIN_SERVICE and not getattr(sys, 'frozen', None) == 'macosx_app':
|
||||
signal.signal(signal.SIGINT, sabnzbd.sig_handler)
|
||||
@@ -1361,8 +1369,11 @@ def main():
|
||||
staticcfg = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(sabnzbd.WEB_DIR_CONFIG, 'staticcfg'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
wizard_static = {'tools.staticdir.on': True, 'tools.staticdir.dir': os.path.join(sabnzbd.WIZARD_DIR, 'static'), 'tools.staticdir.content_types': forced_mime_types}
|
||||
|
||||
appconfig = {'/api': {'tools.basic_auth.on': False},
|
||||
'/rss': {'tools.basic_auth.on': False},
|
||||
appconfig = {'/api': {
|
||||
'tools.basic_auth.on': False,
|
||||
'tools.response_headers.on': True,
|
||||
'tools.response_headers.headers': [('Access-Control-Allow-Origin', '*')]
|
||||
},
|
||||
'/static': static,
|
||||
'/wizard/static': wizard_static,
|
||||
'/favicon.ico': {'tools.staticfile.on': True, 'tools.staticfile.filename': os.path.join(sabnzbd.WEB_DIR_CONFIG, 'staticcfg', 'ico', 'favicon.ico')},
|
||||
@@ -1510,9 +1521,7 @@ def main():
|
||||
# Or special restart cases like Mac and WindowsService
|
||||
if sabnzbd.TRIGGER_RESTART:
|
||||
# Shutdown
|
||||
cherrypy.engine.exit()
|
||||
sabnzbd.halt()
|
||||
sabnzbd.SABSTOP = True
|
||||
sabnzbd.shutdown_program()
|
||||
|
||||
if sabnzbd.downloader.Downloader.do.paused:
|
||||
sabnzbd.RESTART_ARGS.append('-p')
|
||||
@@ -1589,7 +1598,7 @@ if sabnzbd.WIN32:
|
||||
win32serviceutil.ServiceFramework.__init__(self, args)
|
||||
|
||||
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
|
||||
self.overlapped = pywintypes.OVERLAPPED() # @UndefinedVariable
|
||||
self.overlapped = pywintypes.OVERLAPPED()
|
||||
self.overlapped.hEvent = win32event.CreateEvent(None, 0, 0, None)
|
||||
sabnzbd.WIN_SERVICE = self
|
||||
|
||||
@@ -1719,9 +1728,7 @@ if __name__ == '__main__':
|
||||
|
||||
def stop(self):
|
||||
logging.info('[osx] sabApp Quit - stopping main thread ')
|
||||
sabnzbd.halt()
|
||||
cherrypy.engine.exit()
|
||||
sabnzbd.SABSTOP = True
|
||||
sabnzbd.shutdown_program()
|
||||
logging.info('[osx] sabApp Quit - main thread stopped')
|
||||
|
||||
sabApp = startApp()
|
||||
|
||||
10
appveyor.yml
10
appveyor.yml
@@ -1,6 +1,14 @@
|
||||
environment:
|
||||
SAB_NEWSSERVER_HOST:
|
||||
secure: 6SvOPWr5ypJeoumXJAZh90DLpk4C/5UAvzwyX7OOUr4=
|
||||
SAB_NEWSSERVER_USER:
|
||||
secure: Ty3ZG8T5vnacqIFPj5j5hg==
|
||||
SAB_NEWSSERVER_PASSWORD:
|
||||
secure: bO3XHtWTleVF9AqRV/V/nA==
|
||||
|
||||
install:
|
||||
- pip install --upgrade -r tests/requirements.txt
|
||||
- pip install pypiwin32 subprocessww
|
||||
|
||||
build_script:
|
||||
- pytest
|
||||
- python ./tests/test_functional.py
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
|
||||
<div class="colmask">
|
||||
<div class="padding alt">
|
||||
<h5 class="copyright">Copyright © 2008-2017 The SABnzbd Team <<a href="mailto:team@sabnzbd.org">team@sabnzbd.org</a>></h5>
|
||||
<h5 class="copyright">Copyright © 2007-2019 The SABnzbd Team <<a href="mailto:team@sabnzbd.org">team@sabnzbd.org</a>></h5>
|
||||
<p class="copyright"><small>$T('yourRights')</small></p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -61,11 +61,6 @@
|
||||
<input type="checkbox" name="email_rss" id="email_rss" value="1" <!--#if int($email_rss) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-email_rss')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="email_dir">$T('opt-email_dir')</label>
|
||||
<input type="text" name="email_dir" id="email_dir" value="$email_dir" data-initialdir="$my_home" />
|
||||
<span class="desc">$T('explain-email_dir')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="email_server">$T('opt-email_server')</label>
|
||||
<input type="text" name="email_server" id="email_server" value="$email_server" />
|
||||
@@ -194,7 +189,7 @@
|
||||
<fieldset>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="nscript_script">$T('opt-nscript_script')</label>
|
||||
<select name="nscript_script">
|
||||
<select name="nscript_script" id="nscript_script">
|
||||
<!--#for $sc in $scripts#-->
|
||||
<option value="$sc" <!--#if $nscript_script == $sc then 'selected="selected"' else ""#-->>$Tspec($sc)</option>
|
||||
<!--#end for#-->
|
||||
@@ -404,9 +399,6 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
\$(document).ready(function(){
|
||||
// Autocomplete and filebrowser
|
||||
\$('#email_dir').typeahead().fileBrowser();
|
||||
|
||||
// Expand on enable
|
||||
\$('.col2 input[name$="enable"]').change(function() {
|
||||
if(this.checked) {
|
||||
|
||||
@@ -390,9 +390,10 @@
|
||||
<th class="no-sort">$T('link-download')</th>
|
||||
<th>$T('rss-filter')</th>
|
||||
<th>$T('size')</th>
|
||||
<th width="65%">$T('sort-title')</th>
|
||||
<th width="60%">$T('sort-title')</th>
|
||||
<th>$T('category')</th>
|
||||
<th class="default-sort">$T('nzo-age')</th>
|
||||
<th>$T('source')</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<!--#for $job in $matched#-->
|
||||
@@ -411,6 +412,13 @@
|
||||
<td>$job['title']</td>
|
||||
<td>$job['cat']</td>
|
||||
<td data-sort-value="$job['age_ms']">$job['age']</td>
|
||||
<td data-sort-value="$job['baselink']" title="$job['baselink']">
|
||||
<!--#if not $job['infourl']#-->
|
||||
<div class="favicon source-icon" style="background-image: url(//$job['baselink']/favicon.ico);" data-domain="$job['baselink']"></div>
|
||||
<!--#else#-->
|
||||
<a class="favicon source-icon" href="$job['infourl']" target="_blank" style="background-image: url(//$job['baselink']/favicon.ico);" data-domain="$job['baselink']"></a>
|
||||
<!--#end if#-->
|
||||
</td>
|
||||
</tr>
|
||||
<!--#end for#-->
|
||||
</table>
|
||||
@@ -426,9 +434,10 @@
|
||||
<th class="no-sort">$T('link-download')</th>
|
||||
<th>$T('rss-filter')</th>
|
||||
<th>$T('size')</th>
|
||||
<th width="65%">$T('sort-title')</th>
|
||||
<th width="60%">$T('sort-title')</th>
|
||||
<th>$T('category')</th>
|
||||
<th class="default-sort">$T('nzo-age')</th>
|
||||
<th>$T('source')</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<!--#for $job in $unmatched#-->
|
||||
@@ -447,6 +456,13 @@
|
||||
<td>$job['title']</td>
|
||||
<td>$job['cat']</td>
|
||||
<td data-sort-value="$job['age_ms']">$job['age']</td>
|
||||
<td data-sort-value="$job['baselink']" title="$job['baselink']">
|
||||
<!--#if not $job['infourl']#-->
|
||||
<div class="favicon source-icon" style="background-image: url(//$job['baselink']/favicon.ico);" data-domain="$job['baselink']"></div>
|
||||
<!--#else#-->
|
||||
<a class="favicon source-icon" href="$job['infourl']" target="_blank" style="background-image: url(//$job['baselink']/favicon.ico);" data-domain="$job['baselink']"></a>
|
||||
<!--#end if#-->
|
||||
</td>
|
||||
</tr>
|
||||
<!--#end for#-->
|
||||
</table>
|
||||
@@ -476,8 +492,10 @@
|
||||
<td>$job['title']</td>
|
||||
<td>$job['cat']</td>
|
||||
<td data-sort-value="$job['baselink']" title="$job['baselink']">
|
||||
<!--#if $job['baselink']#-->
|
||||
<!--#if not $job['infourl']#-->
|
||||
<div class="favicon source-icon" style="background-image: url(//$job['baselink']/favicon.ico);" data-domain="$job['baselink']"></div>
|
||||
<!--#else#-->
|
||||
<a class="favicon source-icon" href="$job['infourl']" target="_blank" style="background-image: url(//$job['baselink']/favicon.ico);" data-domain="$job['baselink']"></a>
|
||||
<!--#end if#-->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
@@ -129,6 +129,12 @@
|
||||
</select>
|
||||
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</span>
|
||||
</div>
|
||||
<div class="field-pair advanced-settings">
|
||||
<label class="config" for="ssl_ciphers">$T('opt-ssl_ciphers')</label>
|
||||
<input type="text" name="ssl_ciphers" id="ssl_ciphers" />
|
||||
<span class="desc">$T('explain-ssl_ciphers') <br>$T('readwiki')
|
||||
<a href="${helpuri}advanced/ssl-ciphers" target="_blank">${helpuri}advanced/ssl-ciphers</a></span>
|
||||
</div>
|
||||
<div class="field-pair advanced-settings">
|
||||
<label class="config" for="send_group">$T('srv-send_group')</label>
|
||||
<input type="checkbox" name="send_group" id="send_group" value="1" />
|
||||
@@ -166,6 +172,7 @@
|
||||
<form action="saveServer" method="post" class="fullform" autocomplete="off">
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
<input type="hidden" name="server" value="$server['name']" />
|
||||
<input type="hidden" id="ajax" name="ajax" value=1 />
|
||||
|
||||
<div class="section <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
|
||||
<div class="col2 <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
|
||||
@@ -238,6 +245,12 @@
|
||||
</select>
|
||||
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</span>
|
||||
</div>
|
||||
<div class="field-pair advanced-settings">
|
||||
<label class="config" for="ssl_ciphers">$T('opt-ssl_ciphers')</label>
|
||||
<input type="text" name="ssl_ciphers" id="ssl_ciphers" value="$server['ssl_ciphers']" />
|
||||
<span class="desc">$T('explain-ssl_ciphers') <br>$T('readwiki')
|
||||
<a href="${helpuri}advanced/ssl-ciphers" target="_blank">${helpuri}advanced/ssl-ciphers</a></span>
|
||||
</div>
|
||||
<div class="field-pair advanced-settings">
|
||||
<label class="config" for="optional$cur">$T('srv-optional')</label>
|
||||
<input type="checkbox" name="optional" id="optional$cur" value="1" <!--#if int($server['optional']) != 0 then 'checked="checked"' else ""#--> />
|
||||
@@ -402,6 +415,8 @@
|
||||
// Exception when change of priority, reload
|
||||
\$('input[name="priority"], input[name="displayname"]').on('change', function() {
|
||||
\$('.fullform').submit(function() {
|
||||
// No ajax this time
|
||||
\$('input[name="ajax"]').val('')
|
||||
// Skip the fancy stuff, just submit
|
||||
this.submit()
|
||||
})
|
||||
@@ -435,6 +450,8 @@
|
||||
\$(this).html(\$(this).html().replace("$T('showDetails')", "$T('hideDetails')"));
|
||||
} else {
|
||||
\$(this).html(\$(this).html().replace("$T('hideDetails')", "$T('showDetails')"));
|
||||
// Recalculate the charts if changed while details were open
|
||||
showCharts()
|
||||
}
|
||||
// Add coloring
|
||||
addRowColor()
|
||||
@@ -465,6 +482,7 @@
|
||||
setTimeout(function() { portBox.removeClass('port-highlight') }, 2000)
|
||||
})
|
||||
|
||||
// Testing servers
|
||||
\$('.testServer').click(function(event){
|
||||
removeObfuscation()
|
||||
var theButton = \$(this)
|
||||
|
||||
@@ -25,12 +25,6 @@
|
||||
</select>
|
||||
<span class="desc">$T('explain-load_balancing')</span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="ssl_ciphers">$T('opt-ssl_ciphers')</label>
|
||||
<input type="text" name="ssl_ciphers" id="ssl_ciphers" value="$ssl_ciphers" />
|
||||
<span class="desc">$T('explain-ssl_ciphers') <br>$T('readwiki')
|
||||
<a href="${helpuri}advanced/ssl-ciphers" target="_blank">${helpuri}advanced/ssl-ciphers</a></span>
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="max_art_tries">$T('opt-max_art_tries')</label>
|
||||
<input type="number" name="max_art_tries" id="max_art_tries" value="$max_art_tries" min="2" max="2000" />
|
||||
@@ -170,6 +164,30 @@
|
||||
<input type="checkbox" name="enable_all_par" id="enable_all_par" value="1" <!--#if int($enable_all_par) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-enable_all_par').replace('. ', '.<br/>')</span>
|
||||
</div>
|
||||
<!--#if not $nt#-->
|
||||
<div class="field-pair advanced-settings <!--#if not $have_nice then "disabled" else "" #-->">
|
||||
<label class="config" for="nice">$T('opt-nice')</label>
|
||||
<input type="text" name="nice" id="nice" value="$nice" <!--#if not $have_nice then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-nice')</span>
|
||||
</div>
|
||||
<div class="field-pair advanced-settings <!--#if not $have_ionice then "disabled" else "" #-->">
|
||||
<label class="config" for="ionice">$T('opt-ionice')</label>
|
||||
<input type="text" name="ionice" id="ionice" value="$ionice" <!--#if not $have_ionice then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-ionice')</span>
|
||||
</div>
|
||||
<!--#else#-->
|
||||
<div class="field-pair advanced-settings">
|
||||
|
||||
<label class="config" for="win_process_prio">$T('opt-win_process_prio')</label>
|
||||
<select name="win_process_prio" id="win_process_prio">
|
||||
<option value="4" <!--#if int($win_process_prio) == 4 then 'selected="selected"' else ""#-->>$T('win_process_prio-high')</option>
|
||||
<option value="3" <!--#if int($win_process_prio) == 3 then 'selected="selected"' else ""#-->>$T('win_process_prio-normal')</option>
|
||||
<option value="2" <!--#if int($win_process_prio) == 2 then 'selected="selected"' else ""#-->>$T('win_process_prio-low')</option>
|
||||
<option value="1" <!--#if int($win_process_prio) == 1 then 'selected="selected"' else ""#-->>$T('win_process_prio-idle')</option>
|
||||
</select>
|
||||
<span class="desc">$T('explain-win_process_prio')</span>
|
||||
</div>
|
||||
<!--#end if#-->
|
||||
<div class="field-pair advanced-settings">
|
||||
<label class="config" for="par_option">$T('opt-par_option')</label>
|
||||
<input type="text" name="par_option" id="par_option" value="$par_option" />
|
||||
@@ -205,18 +223,6 @@
|
||||
<input type="checkbox" name="new_nzb_on_failure" id="new_nzb_on_failure" value="1" <!--#if int($new_nzb_on_failure) > 0 then 'checked="checked"' else ""#--> />
|
||||
<span class="desc">$T('explain-new_nzb_on_failure')</span>
|
||||
</div>
|
||||
<!--#if not $nt#-->
|
||||
<div class="field-pair advanced-settings <!--#if not $have_nice then "disabled" else "" #-->">
|
||||
<label class="config" for="nice">$T('opt-nice')</label>
|
||||
<input type="text" name="nice" id="nice" value="$nice" <!--#if not $have_nice then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-nice')</span>
|
||||
</div>
|
||||
<div class="field-pair advanced-settings <!--#if not $have_ionice then "disabled" else "" #-->">
|
||||
<label class="config" for="ionice">$T('opt-ionice')</label>
|
||||
<input type="text" name="ionice" id="ionice" value="$ionice" <!--#if not $have_ionice then 'readonly="readonly" disabled="disabled"' else "" #--> />
|
||||
<span class="desc">$T('explain-ionice')</span>
|
||||
</div>
|
||||
<!--#end if#-->
|
||||
<div class="field-pair">
|
||||
<label class="config" for="ignore_samples">$T('opt-ignore_samples')</label>
|
||||
<input type="checkbox" name="ignore_samples" id="ignore_samples" value="1" <!--#if int($ignore_samples) > 0 then 'checked="checked"' else ""#--> />
|
||||
|
||||
@@ -4,16 +4,13 @@ body {
|
||||
}
|
||||
#logo {
|
||||
display: block;
|
||||
margin: auto;
|
||||
margin-top: 3px;
|
||||
margin: 3px auto auto;
|
||||
}
|
||||
|
||||
#content {
|
||||
color: #000;
|
||||
padding: 15px 20px 20px;
|
||||
padding: 65px 20px 20px;
|
||||
font-size: 13px;
|
||||
padding-top: 65px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
.colmask {
|
||||
z-index: 20;
|
||||
@@ -314,7 +311,7 @@ tr.separator {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.Categories form.sorting-row:nth-child(even) tr {
|
||||
.Categories form.sorting-row:nth-child(2n-1) tr {
|
||||
background-color: #F8F8F8;
|
||||
}
|
||||
|
||||
@@ -529,7 +526,7 @@ tr.separator {
|
||||
}
|
||||
#filebrowser_modal .checkbox {
|
||||
float: left;
|
||||
margin: 8px 5px 0x;
|
||||
margin: 8px 5px 0px;
|
||||
}
|
||||
#filebrowser_modal .checkbox input {
|
||||
margin-top: 1px;
|
||||
@@ -576,6 +573,7 @@ h2.activeRSS {
|
||||
float: left;
|
||||
margin: 0 6px 0 2px;
|
||||
text-align: center;
|
||||
color: black !important;
|
||||
}
|
||||
.source-icon span {
|
||||
top: -3px;
|
||||
@@ -600,8 +598,7 @@ h2.activeRSS {
|
||||
padding-top: .4em;
|
||||
}
|
||||
#subscriptions .chk {
|
||||
padding: 5px;
|
||||
padding-top: 8px;
|
||||
padding: 8px 5px 5px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#subscriptions .title {
|
||||
@@ -773,7 +770,6 @@ input[type=radio] {
|
||||
input[type="button"],
|
||||
input[type="submit"] {
|
||||
color: #333;
|
||||
background-color: #fff;
|
||||
display:inline-block;
|
||||
padding:6px 12px;
|
||||
margin-bottom: 0;
|
||||
@@ -784,7 +780,7 @@ input[type="submit"] {
|
||||
white-space:nowrap;
|
||||
vertical-align:middle;
|
||||
cursor:pointer;
|
||||
background-image:none;
|
||||
background: #fff none;
|
||||
border:1px solid #ccc;
|
||||
height: 34px;
|
||||
}
|
||||
@@ -1002,7 +998,7 @@ input[type="checkbox"] {
|
||||
}
|
||||
|
||||
.Servers .col2.server-disabled .label {
|
||||
color: ##777 !important;
|
||||
color: #777 !important;
|
||||
}
|
||||
|
||||
.Servers .col2 .label:nth-child(2) {
|
||||
@@ -1063,9 +1059,7 @@ input[type="checkbox"] {
|
||||
|
||||
.Servers .col2 label,
|
||||
.Email .col2 label {
|
||||
margin: 0;
|
||||
margin-left: 4px;
|
||||
margin-top: 2px;
|
||||
margin: 2px 0 0 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -1141,6 +1135,7 @@ input[type="checkbox"] {
|
||||
}
|
||||
.value-and-select select {
|
||||
min-width: 30px;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.dotOne, .dotTwo, .dotThree {
|
||||
@@ -1341,9 +1336,7 @@ input[type="checkbox"] {
|
||||
}
|
||||
|
||||
.desc {
|
||||
margin: 0;
|
||||
margin-left: 3px;
|
||||
margin-top: 2px;
|
||||
margin: 2px 0 0 3px;
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
|
||||
@@ -313,7 +313,10 @@ function removeObfuscation() {
|
||||
|
||||
// Add coloring to rows (shorthand function)
|
||||
function addRowColor() {
|
||||
$('.field-pair:visible').removeClass('even').filter(':even').addClass('even')
|
||||
// Have to do it seperate for each section
|
||||
$('.section').each(function(i, elmn) {
|
||||
$(elmn).find('.field-pair:visible').removeClass('even').filter(':even').addClass('even')
|
||||
})
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
@@ -351,6 +354,7 @@ $(document).ready(function () {
|
||||
success: function (json) {
|
||||
if (json.error) {
|
||||
$('#config_err_msg').text(json.error);
|
||||
alert(json.error)
|
||||
config_failure()
|
||||
} else if(json.value && json.value.restart_req) {
|
||||
// Trigger restart question
|
||||
@@ -417,7 +421,7 @@ $(document).ready(function () {
|
||||
$('.advanced-button').on('change', function(event){
|
||||
localStorage.setItem('advanced-settings', !$('.advanced-settings').is(':visible'))
|
||||
$('.advanced-settings').toggle()
|
||||
|
||||
addRowColor()
|
||||
})
|
||||
if(localStorage.getItem('advanced-settings') == 'true') {
|
||||
$('.advanced-settings').show()
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<!--#from sabnzbd.constants import VALID_ARCHIVES, VALID_NZB_FILES#-->
|
||||
<!--#set $file_exts = ', '.join(VALID_NZB_FILES + VALID_ARCHIVES)#-->
|
||||
<!-- Notifcation box -->
|
||||
<div class="main-notification-box" style="display: none">
|
||||
<div class="main-notification-box-uploading">
|
||||
@@ -137,10 +139,17 @@
|
||||
</div>
|
||||
<div class="col-sm-6 col-loading" data-bind="visible: !hasPerformanceInfo()">$T('Glitter-loading')<span class="loader-dot-one">.</span><span class="loader-dot-two">.</span><span class="loader-dot-three">.</span></div>
|
||||
</div>
|
||||
<div class="row test-download">
|
||||
<div class="col-sm-6">$T('dashboard-testDownload')</div>
|
||||
<div class="col-sm-6">
|
||||
<a href="#" class="btn btn-default" data-bind="click: testDownload" data-size="100MB" data-tooltip="true" data-placement="top" title="$T('dashboard-testDownload-explain')"><span class="glyphicon glyphicon-download-alt"></span> 100 MB</a>
|
||||
<a href="#" class="btn btn-default" data-bind="click: testDownload" data-size="1000MB" data-tooltip="true" data-placement="top" title="$T('dashboard-testDownload-explain')"><span class="glyphicon glyphicon-download-alt"></span> 1000 MB</a>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div class="row options-function-box">
|
||||
<div class="col-sm-6">
|
||||
<a href="#" data-bind="click: forceDisconnect" class="btn btn-default "><span class="glyphicon glyphicon-minus-sign"></span> $T('link-forceDisc')</a>
|
||||
<a href="#" data-bind="click: forceDisconnect" class="btn btn-default" data-tooltip="true" data-placement="top" title="$T('explain-forceDisc')"><span class="glyphicon glyphicon-minus-sign"></span> $T('link-forceDisc')</a>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<a href="#" data-bind="click: repairQueue" data-tooltip="true" data-placement="top" title="$T('explain-Repair').replace('<br>',' ').replace('<br />',' ')" class="btn btn-default">
|
||||
@@ -426,7 +435,7 @@
|
||||
<form data-bind="submit: addNZBFromURL" class="col-sm-6">
|
||||
<fieldset>
|
||||
<legend class="row-wrap-text">$T('Glitter-addFromURL')</legend>
|
||||
<div class="input-group" data-tooltip="true" data-placement="bottom" title="$T('Glitter-nzbFormats')">
|
||||
<div class="input-group" data-tooltip="true" data-placement="bottom" title="$file_exts">
|
||||
<input type="text" name="nzbURL" class="form-control" placeholder="$T('enterURL')" />
|
||||
<span class="input-group-btn">
|
||||
<input type="submit" name="Add" value="$T('add')" class="btn btn-default" />
|
||||
@@ -437,10 +446,10 @@
|
||||
<form data-bind="submit: addNZBFromFileForm" class="col-sm-6">
|
||||
<fieldset>
|
||||
<legend class="row-wrap-text">$T('Glitter-addFromFile')</legend>
|
||||
<div class="input-group" data-tooltip="true" data-placement="bottom" title="$T('Glitter-nzbFormats')">
|
||||
<div class="input-group" data-tooltip="true" data-placement="bottom" title="$file_exts">
|
||||
<label class="btn btn-default btn-file">
|
||||
<span class="glyphicon glyphicon-file"></span> <em>$T('Glitter-chooseFile')…</em>
|
||||
<input type="file" multiple name="nzbFile" class="form-control" accept=".nzb,.rar,.zip,.gz,.bz2" data-bind="event : { change: updateBrowseLabel }" />
|
||||
<input type="file" multiple name="nzbFile" class="form-control" accept="$file_exts" data-bind="event : { change: updateBrowseLabel }" />
|
||||
</label>
|
||||
|
||||
<span class="input-group-btn">
|
||||
@@ -562,10 +571,10 @@
|
||||
<input type="hidden" name="retry_job_id" />
|
||||
<fieldset>
|
||||
<legend>$T('opt-extra-NZB')</legend>
|
||||
<div class="input-group input-group-addfile" data-tooltip="true" data-placement="bottom" title="$T('Glitter-nzbFormats')">
|
||||
<div class="input-group input-group-addfile" data-tooltip="true" data-placement="bottom" title="$file_exts">
|
||||
<label class="btn btn-default btn-file">
|
||||
<span class="glyphicon glyphicon-file"></span> <em>$T('Glitter-chooseFile')…</em>
|
||||
<input type="file" name="nzbFile" class="form-control" accept=".nzb,.rar,.zip,.gz,.bz2" data-bind="event : { change: updateBrowseLabel }" />
|
||||
<input type="file" name="nzbFile" class="form-control" accept="$file_exts" data-bind="event : { change: updateBrowseLabel }" />
|
||||
</label>
|
||||
</div>
|
||||
</fieldset>
|
||||
@@ -633,7 +642,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
<hr/>
|
||||
<p><small>Copyright (C) 2008-2017, The SABnzbd Team <team@sabnzbd.org><br/>$T('yourRights') </small></p>
|
||||
<p><small>Copyright (C) 2007-2019, The SABnzbd Team <team@sabnzbd.org><br/>$T('yourRights') </small></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -849,6 +849,24 @@ function ViewModel() {
|
||||
})
|
||||
}
|
||||
|
||||
// Download a test-NZB
|
||||
self.testDownload = function(data, event) {
|
||||
var nzbSize = $(event.target).data('size')
|
||||
// Build request
|
||||
var theCall = {
|
||||
mode: "addurl",
|
||||
name: "https://sabnzbd.org/tests/test_download_" + nzbSize + ".nzb",
|
||||
priority: self.queue.priorityName["Force"]
|
||||
}
|
||||
|
||||
// Add
|
||||
callAPI(theCall).then(function(r) {
|
||||
// Hide and reset/refresh
|
||||
self.refresh()
|
||||
$("#modal-options").modal("hide");
|
||||
});
|
||||
}
|
||||
|
||||
// Unblock server
|
||||
self.unblockServer = function(servername) {
|
||||
callSpecialAPI("./status/unblock_server/", {
|
||||
|
||||
@@ -76,7 +76,7 @@ legend,
|
||||
background-color: #666;
|
||||
}
|
||||
|
||||
.navbar-collapse.in .dropdown-menu, {
|
||||
.navbar-collapse.in .dropdown-menu {
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
||||
@@ -105,10 +105,7 @@ h2 {
|
||||
.navbar-logo {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin-right: 12px;
|
||||
margin-left: 15px;
|
||||
margin-top: 4px;
|
||||
margin-bottom: -1px;
|
||||
margin: 4px 12px -1px 15px;
|
||||
}
|
||||
|
||||
.navbar-logo svg {
|
||||
@@ -288,8 +285,7 @@ li.dropdown {
|
||||
opacity: 0.9;
|
||||
color: black;
|
||||
z-index: 2000;
|
||||
padding: 1em;
|
||||
padding-top: 15%;
|
||||
padding: 15% 1em 1em;
|
||||
}
|
||||
|
||||
.main-filedrop.in span {
|
||||
@@ -721,8 +717,7 @@ td.delete .dropdown>a {
|
||||
|
||||
td.delete input[type="checkbox"],
|
||||
.add-nzb-inputbox-options input[type="checkbox"]{
|
||||
margin: 0;
|
||||
margin-bottom: -2px;
|
||||
margin: 0 0 -2px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -1155,8 +1150,7 @@ tr.queue-item>td:first-child>a {
|
||||
#history-options {
|
||||
margin-top: 0;
|
||||
margin-left: 10px;
|
||||
padding: 0;
|
||||
padding-left: 4px;
|
||||
padding: 0 0 0 4px;
|
||||
}
|
||||
|
||||
#history-options .hover-button {
|
||||
@@ -1425,6 +1419,14 @@ tr.queue-item>td:first-child>a {
|
||||
margin: 5px 0px 10px;
|
||||
}
|
||||
|
||||
#modal-options .test-download .btn {
|
||||
padding: 1px 5px;
|
||||
}
|
||||
|
||||
#modal-options #options-status .test-download .btn .glyphicon {
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
#modal-options .options-function-box {
|
||||
margin-top: 5px;
|
||||
}
|
||||
@@ -1536,8 +1538,7 @@ tr.queue-item>td:first-child>a {
|
||||
|
||||
.add-nzb-inputbox span {
|
||||
display: inline-block;
|
||||
margin: 8px 2px 0px 5px;
|
||||
margin-left: -20px;
|
||||
margin: 8px 2px 0px -20px;
|
||||
}
|
||||
|
||||
.btn-file {
|
||||
@@ -1630,11 +1631,9 @@ input[name="nzbURL"] {
|
||||
|
||||
#modal-item-files .multioperations-selector {
|
||||
clear: left;
|
||||
margin: 0;
|
||||
float: left;
|
||||
padding: 5px 8px;
|
||||
margin-bottom: 5px;
|
||||
margin-right: 10px;
|
||||
margin: 0 10px 5px 0;
|
||||
border: 1px solid #cccccc;
|
||||
}
|
||||
|
||||
@@ -2045,9 +2044,8 @@ a:focus {
|
||||
right: 17px;
|
||||
display: inline-block;
|
||||
border-right: 6px solid transparent;
|
||||
border-bottom: 6px solid #ccc;
|
||||
border-bottom: 6px solid rgba(0, 0, 0, 0.2);
|
||||
border-left: 6px solid transparent;
|
||||
border-bottom-color: rgba(0, 0, 0, 0.2);
|
||||
content: '';
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
</table>
|
||||
<div class="sabnzbd_logo main_sprite_container sprite_sabnzbdplus_logo"></div>
|
||||
<p><strong>SABnzbd $T('version'):</strong> $version</p>
|
||||
<p><small>Copyright (C) 2008-2016, The SABnzbd Team <team@sabnzbd.org></small></p>
|
||||
<p><small>Copyright (C) 2008-2019, The SABnzbd Team <team@sabnzbd.org></small></p>
|
||||
<p><small>$T('yourRights')</small></p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1253,8 +1253,10 @@ function loadingJSON(){
|
||||
<option value="180" >3 $T("minutes")</option>
|
||||
<option value="300" >5 $T("minutes")</option>
|
||||
<option value="0" >$T("none")</option>
|
||||
</select>
|
||||
<br />SABnzbd $T('version'): $version | smpl skin</a></p>
|
||||
</select></p>
|
||||
|
||||
<p><strong>This skin is no longer supported and may lose functionality in future releases.</strong></p>
|
||||
|
||||
<!--#if $new_release#-->
|
||||
<!--#set $msg=$T('ft-newRelease@1')%($new_release)#-->
|
||||
<b>$msg <a href="$new_rel_url" target="_blank">SF.net</a></b><br/>
|
||||
|
||||
16146
interfaces/smpl/templates/static/MochiKit/MochiKit.js
vendored
16146
interfaces/smpl/templates/static/MochiKit/MochiKit.js
vendored
File diff suppressed because it is too large
Load Diff
@@ -1,2 +1,2 @@
|
||||
dojo.hostenv.conditionalLoadModule({"common": ["MochiKit.MochiKit"]});
|
||||
dojo.hostenv.moduleLoaded("MochiKit.*");
|
||||
dojo.hostenv.conditionalLoadModule({"common": ["MochiKit.MochiKit"]});
|
||||
dojo.hostenv.moduleLoaded("MochiKit.*");
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
$T('explain-language')<br /><br />
|
||||
<div class="main-container">
|
||||
<!--#for $l, $language in $languages#-->
|
||||
<label class="language <!--#if $lang == $l then 'language-active' else ''#-->">
|
||||
<label class="language">
|
||||
$language<br />
|
||||
<input type="radio" name="lang" id="$l" value="$l" <!--#if $lang == $l then 'checked="checked"' else ''#--> />
|
||||
<input type="radio" name="lang" id="$l" value="$l" <!--#if $active_lang == $l then 'checked="checked"' else ''#--> />
|
||||
</label>
|
||||
<!--#end for#-->
|
||||
<!--#if not $languages#-->
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<div class="form-group">
|
||||
<label for="host" class="col-sm-4 control-label">$T('srv-host')</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="text" class="form-control" name="host" id="host" value="$host" placeholder="$T('wizard-example') news.giganews.com" />
|
||||
<input type="text" class="form-control" name="host" id="host" value="$host" placeholder="$T('wizard-example') news.newshosting.com" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
@@ -87,7 +87,7 @@
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<div class="clearfix"></div>
|
||||
<iframe style="float: right; width: 325px; height: 325px;" frameborder="0" src="https://sabnzbd.org/wizard#$language"></iframe>
|
||||
<iframe style="float: right; width: 325px; height: 325px;" frameborder="0" src="https://sabnzbd.org/wizard#$active_lang"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
<input type="hidden" name="session" value="$session" />
|
||||
|
||||
@@ -88,19 +88,12 @@ label {
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
||||
.sup {
|
||||
vertical-align: sup !important;
|
||||
}
|
||||
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
.align-center {
|
||||
text-align: center;
|
||||
}
|
||||
.float-center {
|
||||
float: center;
|
||||
}
|
||||
.unselected,
|
||||
.selected {
|
||||
display: inline-block;
|
||||
@@ -123,9 +116,6 @@ label {
|
||||
.bigger {
|
||||
font-size: 14px;
|
||||
}
|
||||
.padded {
|
||||
padding: 12px;
|
||||
}
|
||||
.bigger input {
|
||||
font-size: 16px;
|
||||
}
|
||||
@@ -135,9 +125,6 @@ label {
|
||||
.full-width {
|
||||
width: 100%;
|
||||
}
|
||||
.bigbutton {
|
||||
font-size: 18px !important;
|
||||
}
|
||||
.correct {
|
||||
border: 2px solid #00cc22;
|
||||
}
|
||||
@@ -153,7 +140,6 @@ label {
|
||||
.text-input-wide {
|
||||
width: 230px;
|
||||
}
|
||||
.text-input-thin,
|
||||
#server-hidden-settings input[type="number"] {
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
<p><strong>$T('opt-complete_dir')</strong></p>
|
||||
<div class="quoteBlock">
|
||||
$complete_dir
|
||||
<a href="${access_url}config/folders" class="indented"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
<a href="${access_url}/config/folders#complete_dir" class="indented"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
</div>
|
||||
|
||||
<p><strong>$T('opt-download_dir')</strong></p>
|
||||
<div class="quoteBlock">
|
||||
$download_dir
|
||||
<a href="${access_url}config/folders" class="indented"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
<a href="${access_url}/config/folders#complete_dir" class="indented"><span class="glyphicon glyphicon-cog"></span></a>
|
||||
</div>
|
||||
|
||||
<hr/>
|
||||
|
||||
@@ -53,7 +53,7 @@ the various releases.
|
||||
2.4.2 2.4.1 2005 PSF yes
|
||||
2.4.3 2.4.2 2006 PSF yes
|
||||
2.5 2.4 2006 PSF yes
|
||||
2.5.1 2.5 2007 PSF yes
|
||||
2.7 2.6 2010 PSF yes
|
||||
|
||||
Footnotes:
|
||||
|
||||
@@ -89,9 +89,9 @@ license to reproduce, analyze, test, perform and/or display publicly,
|
||||
prepare derivative works, distribute, and otherwise use Python
|
||||
alone or in any derivative version, provided, however, that PSF's
|
||||
License Agreement and PSF's notice of copyright, i.e., "Copyright (c)
|
||||
2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation;
|
||||
All Rights Reserved" are retained in Python alone or in any derivative
|
||||
version prepared by Licensee.
|
||||
2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights
|
||||
Reserved" are retained in Python alone or in any derivative version
|
||||
prepared by Licensee.
|
||||
|
||||
3. In the event Licensee prepares a derivative work that is based on
|
||||
or incorporates Python or any part thereof, and wants to make
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
The original author of SABnzbd based his work on Pynewsleecher by Freddy@madcowdesease.org.
|
||||
|
||||
Few parts of Pynewsleecher have survived the generations of SABnzbd in a
|
||||
recognizable form.
|
||||
Still, we wish to thank Freddy for his inspiration.
|
||||
|
||||
The home of the Pynewsleecher project:
|
||||
http://www.madcowdisease.org/mcd/pynewsleecher
|
||||
|
||||
The software does not carry any license information.
|
||||
|
||||
The original author of SABnzbd based his work on Pynewsleecher by Freddy@madcowdesease.org.
|
||||
|
||||
Few parts of Pynewsleecher have survived the generations of SABnzbd in a
|
||||
recognizable form.
|
||||
Still, we wish to thank Freddy for his inspiration.
|
||||
|
||||
The home of the Pynewsleecher project:
|
||||
http://www.madcowdisease.org/mcd/pynewsleecher
|
||||
|
||||
The software does not carry any license information.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
On http://www.brunningonline.net/simon/blog/archives/001835.html,
|
||||
the author licensed SysTrayIcon.py under a variant of the WTFPL:
|
||||
|
||||
> Any road up, help yourself. Consider SysTrayIcon.py to be under an
|
||||
> "Aleister Crowley" style license - "Do what thou wilt shall be the
|
||||
> only law".
|
||||
>
|
||||
> Err, but don't sue me if it doesn't work. ;-)
|
||||
On http://www.brunningonline.net/simon/blog/archives/001835.html,
|
||||
the author licensed SysTrayIcon.py under a variant of the WTFPL:
|
||||
|
||||
> Any road up, help yourself. Consider SysTrayIcon.py to be under an
|
||||
> "Aleister Crowley" style license - "Do what thou wilt shall be the
|
||||
> only law".
|
||||
>
|
||||
> Err, but don't sue me if it doesn't work. ;-)
|
||||
|
||||
BIN
osx/unrar/unrar
BIN
osx/unrar/unrar
Binary file not shown.
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2011-2017 The SABnzbd-Team
|
||||
# Copyright 2011-2019 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2018-11-27 23:39+0000\n"
|
||||
"Last-Translator: scootergrisen <scootergrisen@gmail.com>\n"
|
||||
"Language-Team: Danish <da@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
@@ -65,13 +65,13 @@ msgid ""
|
||||
"<!--#end if#-->\n"
|
||||
msgstr ""
|
||||
"##\n"
|
||||
"## Standard Email skabelon til SABnzbd\n"
|
||||
"## Dette er en Cheetah skabelon\n"
|
||||
"## Standard E-mail-skabelon til SABnzbd\n"
|
||||
"## Dette er en Cheetah-skabelon\n"
|
||||
"## Dokumentation: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"##\n"
|
||||
"## Linjeskift og blanktegn er betydelig!\n"
|
||||
"## Linjeskift og blanktegn har betydning!\n"
|
||||
"##\n"
|
||||
"## Disse er e-mail-headerne \n"
|
||||
"## Dette er e-mail-headerne \n"
|
||||
"To: $to\n"
|
||||
"From: $from\n"
|
||||
"Date: $date\n"
|
||||
@@ -79,7 +79,7 @@ msgstr ""
|
||||
"job $name\n"
|
||||
"X-priority: 5\n"
|
||||
"X-MS-priority: 5\n"
|
||||
"## Efter dette kommer body, den tomme linje kræves!\n"
|
||||
"## Herefter kommer kroppen, den tomme linje skal være der!\n"
|
||||
"\n"
|
||||
"Hej,\n"
|
||||
"<!--#if $status #-->\n"
|
||||
@@ -100,13 +100,13 @@ msgstr ""
|
||||
"<!--#end for#-->\n"
|
||||
"<!--#end for#-->\n"
|
||||
"<!--#if $script!=\"\" #-->\n"
|
||||
"Output fra bruger script \"$script\" (Exit code = $script_ret):\n"
|
||||
"Output fra brugerscriptet \"$script\" (Afslutningskode = $script_ret):\n"
|
||||
"$script_output\n"
|
||||
"<!--#end if#-->\n"
|
||||
"<!--#if $status #-->\n"
|
||||
"Enjoy!\n"
|
||||
"Hav det godt!\n"
|
||||
"<!--#else#-->\n"
|
||||
"Sorry!\n"
|
||||
"Beklager!\n"
|
||||
"<!--#end if#-->\n"
|
||||
|
||||
#: email/rss.tmpl:1
|
||||
@@ -138,25 +138,25 @@ msgid ""
|
||||
"Bye\n"
|
||||
msgstr ""
|
||||
"##\n"
|
||||
"## RSS Email skabelon til SABnzbd\n"
|
||||
"## Dette er Cheetah skabelon\n"
|
||||
"## RSS E-mail-skabelon til SABnzbd\n"
|
||||
"## Dette er en Cheetah-skabelon\n"
|
||||
"## Dokumentation: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"##\n"
|
||||
"## Linjeskift og blanktegn er betydelig!\n"
|
||||
"## Linjeskift og blanktegn har betydning!\n"
|
||||
"##\n"
|
||||
"## Dette er email headers\n"
|
||||
"## Dette er e-mai-headere\n"
|
||||
"To: $to\n"
|
||||
"From: $from\n"
|
||||
"Date: $date\n"
|
||||
"Subject: SABnzbd har tilføjet $antal jobs til køen\n"
|
||||
"X-priority: 5\n"
|
||||
"X-MS-priority: 5\n"
|
||||
"## Efter dette kommer body, den tomme linje kræves!\n"
|
||||
"## Herefter kommer kroppen, den tomme linje skal være der!\n"
|
||||
"\n"
|
||||
"Hej,\n"
|
||||
"\n"
|
||||
"SABnzbd har tilføjet $antal job(s) til køen.\n"
|
||||
"De er fra RSS feed \"$feed\".\n"
|
||||
"De er fra RSS-feedet \"$feed\".\n"
|
||||
"<!--#for $job in $jobs#-->\n"
|
||||
" $job <!--#slurp#-->\n"
|
||||
"<!--#end for#-->\n"
|
||||
@@ -189,24 +189,24 @@ msgid ""
|
||||
"Bye\n"
|
||||
msgstr ""
|
||||
"##\n"
|
||||
"## Dårlig URL Fetch E-mail skabelon for SABnzbd\n"
|
||||
"## Dette er en Cheetah skabelon\n"
|
||||
"## Dårlig URL-hentning af E-mail-skabelon til SABnzbd\n"
|
||||
"## Dette er en Cheetah-skabelon\n"
|
||||
"## Dokumentation: http://sabnzbd.wikidot.com/email-templates\n"
|
||||
"##\n"
|
||||
"## Linjeskift og blanktegn er betydelig!\n"
|
||||
"## Linjeskift og blanktegn har betydning!\n"
|
||||
"##\n"
|
||||
"## Dette er email headers\n"
|
||||
"## Dette er e-mail-headere\n"
|
||||
"To: $to\n"
|
||||
"From: $from\n"
|
||||
"Date: $date\n"
|
||||
"Subject: SABnzbd kunne ikke hente en NZB\n"
|
||||
"X-priority: 5\n"
|
||||
"X-MS-priority: 5\n"
|
||||
"## Efter dette kommer body, den tomme linje kræves!\n"
|
||||
"## Herefter kommer kroppen, den tomme linje skal være der!\n"
|
||||
"\n"
|
||||
"Hej,\n"
|
||||
"\n"
|
||||
"SABnzbd kunne ikke hente NZB fra $url.\n"
|
||||
"Fejl meddelelsen er: $msg\n"
|
||||
"Fejlmeddelelsen er: $msg\n"
|
||||
"\n"
|
||||
"Farvel\n"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Thomas Lucke (Lucky) <Unknown>\n"
|
||||
"Language-Team: German <de@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Matti Ylönen <Unknown>\n"
|
||||
"Language-Team: Finnish <fi@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Fox Ace <Unknown>\n"
|
||||
"Language-Team: French <fr@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"PO-Revision-Date: 2017-08-01 16:45+0000\n"
|
||||
"Last-Translator: ION IL <Unknown>\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2019-01-21 15:26+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
|
||||
"Language-Team: Hebrew <he@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-08-02 06:03+0000\n"
|
||||
"X-Generator: Launchpad (build 18441)\n"
|
||||
"X-Launchpad-Export-Date: 2019-01-22 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18856)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
@@ -91,9 +91,9 @@ msgstr ""
|
||||
"הורדו $size\n"
|
||||
"\n"
|
||||
":תוצאות העבודה\n"
|
||||
"<!--#for $stage ב $stages #-->\n"
|
||||
"<!--#for $stage in $stages #-->\n"
|
||||
"שלב $stage <!--#slurp#-->\n"
|
||||
"<!--#for $result ב $stages[$stage]#-->\n"
|
||||
"<!--#for $result in $stages[$stage]#-->\n"
|
||||
" $result <!--#slurp#-->\n"
|
||||
"<!--#end for#-->\n"
|
||||
"<!--#end for#-->\n"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Norwegian Bokmal <nb@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"Language-Team: Dutch <nl@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Tomasz 'Zen' Napierala <tomasz@napierala.org>\n"
|
||||
"Language-Team: Polish <pl@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: lrrosa <Unknown>\n"
|
||||
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: nicusor <Unknown>\n"
|
||||
"Language-Team: Romanian <ro@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Pavel Maryanov <Unknown>\n"
|
||||
"Language-Team: Russian <gnu@mx.ru>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-06-24 19:51+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
|
||||
"Language-Team: Launchpad Serbian Translators\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-27 06:00+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
"Language: sr\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-06-24 19:50+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
|
||||
"Language-Team: Swedish <sv@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-27 06:00+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2015-10-24 11:05+0000\n"
|
||||
"Last-Translator: shypike <Unknown>\n"
|
||||
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:55+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: email/email.tmpl:1
|
||||
msgid ""
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
698
po/main/da.po
698
po/main/da.po
File diff suppressed because it is too large
Load Diff
474
po/main/de.po
474
po/main/de.po
File diff suppressed because it is too large
Load Diff
@@ -120,3 +120,5 @@ msgstr "Separate multiple URLs with a comma"
|
||||
msgid "Advanced"
|
||||
msgstr "Advanced Settings"
|
||||
|
||||
msgid "0 is highest priority, 100 is the lowest priority"
|
||||
msgstr "0 is highest priority, 99 is the lowest priority"
|
||||
|
||||
439
po/main/es.po
439
po/main/es.po
File diff suppressed because it is too large
Load Diff
438
po/main/fi.po
438
po/main/fi.po
File diff suppressed because it is too large
Load Diff
446
po/main/fr.po
446
po/main/fr.po
File diff suppressed because it is too large
Load Diff
560
po/main/he.po
560
po/main/he.po
File diff suppressed because it is too large
Load Diff
436
po/main/nb.po
436
po/main/nb.po
File diff suppressed because it is too large
Load Diff
441
po/main/nl.po
441
po/main/nl.po
File diff suppressed because it is too large
Load Diff
436
po/main/pl.po
436
po/main/pl.po
File diff suppressed because it is too large
Load Diff
436
po/main/pt_BR.po
436
po/main/pt_BR.po
File diff suppressed because it is too large
Load Diff
439
po/main/ro.po
439
po/main/ro.po
File diff suppressed because it is too large
Load Diff
429
po/main/ru.po
429
po/main/ru.po
File diff suppressed because it is too large
Load Diff
434
po/main/sr.po
434
po/main/sr.po
File diff suppressed because it is too large
Load Diff
436
po/main/sv.po
436
po/main/sv.po
File diff suppressed because it is too large
Load Diff
430
po/main/zh_CN.po
430
po/main/zh_CN.po
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2011-2017 The SABnzbd-Team
|
||||
# Copyright 2011-2019 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
msgid ""
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"PO-Revision-Date: 2017-04-10 11:28+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2018-11-27 23:30+0000\n"
|
||||
"Last-Translator: scootergrisen <scootergrisen@gmail.com>\n"
|
||||
"Language-Team: Danish <da@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
@@ -23,7 +23,7 @@ msgstr "Vis udgivelsesbemærkninger"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Start SABnzbd"
|
||||
msgstr ""
|
||||
msgstr "Start SABnzbd"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Support the project, Donate!"
|
||||
@@ -38,7 +38,7 @@ msgid ""
|
||||
"The installation directory has changed (now in \"Program Files\"). \\nIf you "
|
||||
"run SABnzbd as a service, you need to update the service settings."
|
||||
msgstr ""
|
||||
"Installationsmappen er ændret (nu i \"Program Files \"). \\nHvis du kører "
|
||||
"Installationsmappen er ændret (nu i \"Program Files\"). \\nHvis du kører "
|
||||
"SABnzbd som en tjeneste, skal du opdatere tjenesteindstillingerne."
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
@@ -55,7 +55,7 @@ msgstr "Skrivebordsikon"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "NZB File association"
|
||||
msgstr "NZB filtilknytning"
|
||||
msgstr "NZB-filtilknytning"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Delete Program"
|
||||
@@ -70,20 +70,20 @@ msgid ""
|
||||
"This system requires the Microsoft runtime library VC90 to be installed "
|
||||
"first. Do you want to do that now?"
|
||||
msgstr ""
|
||||
"Dette system kræver, at Microsoft runtime biblioteket VC90 skal installeres "
|
||||
"først. Ønsker du at gøre det nu?"
|
||||
"Systemet kræver at Microsoft runtime-biblioteket VC90 skal installeres "
|
||||
"først. Vil du gøre det nu?"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Downloading Microsoft runtime installer..."
|
||||
msgstr "Downloader Microsoft runtime installationsfil..."
|
||||
msgstr "Downloader Microsoft runtime-installationsfil..."
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Download error, retry?"
|
||||
msgstr "Download fejl, prøv igen?"
|
||||
msgstr "Fejl ved download, prøv igen?"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Cannot install without runtime library, retry?"
|
||||
msgstr "Kan ikke installere uden runtime bibliotek, prøv igen?"
|
||||
msgstr "Kan ikke installere uden runtime-bibliotek, prøv igen?"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid ""
|
||||
@@ -91,8 +91,7 @@ msgid ""
|
||||
"the previous version or `Cancel` to cancel this upgrade."
|
||||
msgstr ""
|
||||
"Du kan ikke overskrive en eksisterende installation. \\n\\nKlik `OK` for at "
|
||||
"fjerne den tidligere version eller `Annuller` for at annullere denne "
|
||||
"opgradering."
|
||||
"fjerne den tidligere version eller `Annuller` for at annullere opgraderingen."
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Your settings and data will be preserved."
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-05-22 08:00+0000\n"
|
||||
"Last-Translator: larshuth <Unknown>\n"
|
||||
"Language-Team: German <de@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Victor Herrero <victorhera@gmail.com>\n"
|
||||
"Language-Team: Spanish <es@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-04-02 07:38+0000\n"
|
||||
"Last-Translator: Paavo Rissanen <paavo.rissanen@outlook.com>\n"
|
||||
"Language-Team: Finnish <fi@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-03-21 08:58+0000\n"
|
||||
"Last-Translator: Fred <88com88@gmail.com>\n"
|
||||
"Language-Team: French <fr@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-05-06 09:07+0000\n"
|
||||
"Last-Translator: ION IL <Unknown>\n"
|
||||
"Language-Team: Hebrew <he@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
@@ -96,3 +96,14 @@ msgstr ""
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Your settings and data will be preserved."
|
||||
msgstr "ההגדרות והנתונים שלך יישמרו."
|
||||
|
||||
#~ msgid ""
|
||||
#~ " >>>> WARNING <<<<\\r\\n\\r\\nPlease, first check the "
|
||||
#~ "release notes or go to http://wiki.sabnzbd.org/introducing-0-7-0 !"
|
||||
#~ msgstr ""
|
||||
#~ " >>>> אזהרה <<<<\\r\\n\\r\\n! "
|
||||
#~ "http://wiki.sabnzbd.org/introducing-0-7-0 אנא, בדוק תחילה את הערות השחרור או "
|
||||
#~ "לך אל"
|
||||
|
||||
#~ msgid "Go to the SABnzbd Wiki"
|
||||
#~ msgstr "SABnzbd לך אל וויקי"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: Norwegian Bokmal <nb@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-03-19 09:47+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
|
||||
"Language-Team: Dutch <nl@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Tomasz 'Zen' Napierala <tomasz@napierala.org>\n"
|
||||
"Language-Team: Polish <pl@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: lrrosa <Unknown>\n"
|
||||
"Language-Team: Brazilian Portuguese <pt_BR@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: nicusor <Unknown>\n"
|
||||
"Language-Team: Romanian <ro@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Pavel Maryanov <Unknown>\n"
|
||||
"Language-Team: Russian <gnu@mx.ru>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Ozzii <Unknown>\n"
|
||||
"Language-Team: Launchpad Serbian Translators\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
"Language: sr\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
|
||||
"Last-Translator: Andreas Lindberg <andypandyswe@gmail.com>\n"
|
||||
"Language-Team: Swedish <sv@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -7,15 +7,15 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: sabnzbd\n"
|
||||
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"POT-Creation-Date: 2017-06-22 20:42+0000\n"
|
||||
"POT-Creation-Date: 2018-12-24 11:01+0000\n"
|
||||
"PO-Revision-Date: 2017-05-28 17:17+0000\n"
|
||||
"Last-Translator: ninjai <ninjai.us@gmail.com>\n"
|
||||
"Language-Team: Chinese (Simplified) <zh_CN@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2017-06-23 05:56+0000\n"
|
||||
"X-Generator: Launchpad (build 18416)\n"
|
||||
"X-Launchpad-Export-Date: 2018-12-25 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 18847)\n"
|
||||
|
||||
#: NSIS_Installer.nsi
|
||||
msgid "Show Release Notes"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -202,7 +202,7 @@ def sig_handler(signum=None, frame=None):
|
||||
INIT_LOCK = Lock()
|
||||
|
||||
|
||||
def connect_db(thread_index=0):
|
||||
def get_db_connection(thread_index=0):
|
||||
# Create a connection and store it in the current thread
|
||||
if not (hasattr(cherrypy.thread_data, 'history_db') and cherrypy.thread_data.history_db):
|
||||
cherrypy.thread_data.history_db = sabnzbd.database.HistoryDB()
|
||||
@@ -223,7 +223,7 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
|
||||
__SHUTTING_DOWN__ = False
|
||||
|
||||
# Set global database connection for Web-UI threads
|
||||
cherrypy.engine.subscribe('start_thread', connect_db)
|
||||
cherrypy.engine.subscribe('start_thread', get_db_connection)
|
||||
|
||||
# Paused?
|
||||
pause_downloader = pause_downloader or cfg.start_paused()
|
||||
@@ -270,7 +270,7 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
|
||||
cfg.quota_day.callback(guard_quota_dp)
|
||||
cfg.quota_period.callback(guard_quota_dp)
|
||||
cfg.fsys_type.callback(guard_fsys_type)
|
||||
cfg.language.callback(sabnzbd.notifier.reset_growl)
|
||||
cfg.language.callback(guard_language)
|
||||
cfg.enable_https_verification.callback(guard_https_ver)
|
||||
guard_https_ver()
|
||||
|
||||
@@ -311,6 +311,11 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
|
||||
cfg.sched_converted.set(2)
|
||||
config.save_config()
|
||||
|
||||
# Add hostname to the whitelist
|
||||
if not cfg.host_whitelist():
|
||||
cfg.host_whitelist.set(socket.gethostname())
|
||||
|
||||
# Do repair if requested
|
||||
if check_repair_request():
|
||||
repair = 2
|
||||
pause_downloader = True
|
||||
@@ -320,7 +325,6 @@ def initialize(pause_downloader=False, clean_up=False, evalSched=False, repair=0
|
||||
|
||||
paused = BPSMeter.do.read()
|
||||
|
||||
|
||||
NzbQueue()
|
||||
|
||||
Downloader(pause_downloader or paused)
|
||||
@@ -517,6 +521,13 @@ def guard_fsys_type():
|
||||
sabnzbd.encoding.change_fsys(cfg.fsys_type())
|
||||
|
||||
|
||||
def guard_language():
|
||||
""" Callback for change of the interface language """
|
||||
sabnzbd.notifier.reset_growl()
|
||||
sabnzbd.lang.set_language(cfg.language())
|
||||
sabnzbd.api.clear_trans_cache()
|
||||
|
||||
|
||||
def set_https_verification(value):
|
||||
prev = False
|
||||
try:
|
||||
@@ -650,13 +661,13 @@ def add_nzbfile(nzbfile, pp=None, script=None, cat=None, priority=NORMAL_PRIORIT
|
||||
try:
|
||||
filename = nzbfile.filename.encode('cp1252').decode('utf-8')
|
||||
except:
|
||||
# Correct encoding afterall!
|
||||
# Correct encoding after all!
|
||||
filename = nzbfile.filename
|
||||
filename = encoding.special_fixer(filename)
|
||||
keep = False
|
||||
|
||||
if not sabnzbd.WIN32:
|
||||
# If windows client sends file to Unix server backslashed may
|
||||
# If windows client sends file to Unix server backslashes may
|
||||
# be included, so convert these
|
||||
filename = filename.replace('\\', '/')
|
||||
|
||||
@@ -758,7 +769,7 @@ def system_standby():
|
||||
|
||||
def shutdown_program():
|
||||
""" Stop program after halting and saving """
|
||||
logging.info("Performing sabnzbd shutdown")
|
||||
logging.info("[%s] Performing SABnzbd shutdown", misc.caller_name())
|
||||
sabnzbd.halt()
|
||||
cherrypy.engine.exit()
|
||||
sabnzbd.SABSTOP = True
|
||||
@@ -952,9 +963,9 @@ def save_admin(data, _id):
|
||||
try:
|
||||
with open(path, 'wb') as data_file:
|
||||
if cfg.use_pickle():
|
||||
data = pickle.dump(data, data_file)
|
||||
pickle.dump(data, data_file)
|
||||
else:
|
||||
data = cPickle.dump(data, data_file)
|
||||
cPickle.dump(data, data_file)
|
||||
break
|
||||
except:
|
||||
if t == 2:
|
||||
@@ -997,12 +1008,12 @@ def pp_to_opts(pp):
|
||||
# Convert the pp to an int
|
||||
pp = sabnzbd.interface.int_conv(pp)
|
||||
if pp == 0:
|
||||
return (False, False, False)
|
||||
return False, False, False
|
||||
if pp == 1:
|
||||
return (True, False, False)
|
||||
return True, False, False
|
||||
if pp == 2:
|
||||
return (True, True, False)
|
||||
return (True, True, True)
|
||||
return True, True, False
|
||||
return True, True, True
|
||||
|
||||
|
||||
def opts_to_pp(repair, unpack, delete):
|
||||
@@ -1179,6 +1190,36 @@ def test_ipv6():
|
||||
return False
|
||||
|
||||
|
||||
def test_cert_checking():
|
||||
""" Test quality of certificate validation
|
||||
On systems with at least Python > 2.7.9
|
||||
"""
|
||||
if sabnzbd.HAVE_SSL_CONTEXT:
|
||||
# User disabled the test, assume proper SSL certificates
|
||||
if not cfg.selftest_host():
|
||||
return True
|
||||
# Try a connection to our test-host
|
||||
try:
|
||||
import ssl
|
||||
ctx = ssl.create_default_context()
|
||||
base_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
ssl_sock = ctx.wrap_socket(base_sock, server_hostname=cfg.selftest_host())
|
||||
ssl_sock.settimeout(2.0)
|
||||
ssl_sock.connect((cfg.selftest_host(), 443))
|
||||
ssl_sock.close()
|
||||
return True
|
||||
except (socket.gaierror, socket.timeout):
|
||||
# Non-SSL related error.
|
||||
# We now assume that certificates work instead of forcing
|
||||
# lower quality just because some (temporary) internet problem
|
||||
logging.info('Could not determine system certificate validation quality due to connection problems')
|
||||
return True
|
||||
except:
|
||||
# Seems something is still wrong
|
||||
sabnzbd.set_https_verification(0)
|
||||
return False
|
||||
|
||||
|
||||
def history_updated():
|
||||
""" To make sure we always have a fresh history """
|
||||
sabnzbd.LAST_HISTORY_UPDATE += 1
|
||||
|
||||
147
sabnzbd/api.py
147
sabnzbd/api.py
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -29,6 +29,7 @@ import cherrypy
|
||||
import locale
|
||||
|
||||
from threading import Thread
|
||||
|
||||
try:
|
||||
locale.setlocale(locale.LC_ALL, "")
|
||||
except:
|
||||
@@ -41,9 +42,9 @@ except ImportError:
|
||||
pass
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import VALID_ARCHIVES, Status, \
|
||||
TOP_PRIORITY, REPAIR_PRIORITY, HIGH_PRIORITY, NORMAL_PRIORITY, LOW_PRIORITY, \
|
||||
KIBI, MEBI, GIGI, JOB_ADMIN
|
||||
from sabnzbd.constants import VALID_ARCHIVES, VALID_NZB_FILES, Status, \
|
||||
TOP_PRIORITY, REPAIR_PRIORITY, HIGH_PRIORITY, NORMAL_PRIORITY, LOW_PRIORITY, \
|
||||
KIBI, MEBI, GIGI, JOB_ADMIN
|
||||
import sabnzbd.config as config
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.downloader import Downloader
|
||||
@@ -64,14 +65,12 @@ from sabnzbd.articlecache import ArticleCache
|
||||
from sabnzbd.utils.servertests import test_nntp_server_dict
|
||||
from sabnzbd.bpsmeter import BPSMeter
|
||||
from sabnzbd.rating import Rating
|
||||
from sabnzbd.getipaddress import localipv4, publicipv4, ipv6
|
||||
from sabnzbd.getipaddress import localipv4, publicipv4, ipv6, addresslookup
|
||||
from sabnzbd.newsunpack import userxbit
|
||||
from sabnzbd.database import build_history_info, unpack_history_info, HistoryDB
|
||||
import sabnzbd.notifier
|
||||
import sabnzbd.rss
|
||||
import sabnzbd.emailer
|
||||
import sabnzbd.getipaddress as getipaddress
|
||||
|
||||
|
||||
##############################################################################
|
||||
# API error messages
|
||||
@@ -87,7 +86,6 @@ _MSG_OUTPUT_FORMAT = 'Format not supported'
|
||||
_MSG_NO_SUCH_CONFIG = 'Config item does not exist'
|
||||
_MSG_BAD_SERVER_PARMS = 'Incorrect server settings'
|
||||
|
||||
|
||||
# For Windows: determine executable extensions
|
||||
if os.name == 'nt':
|
||||
PATHEXT = os.environ.get('PATHEXT', '').lower().split(';')
|
||||
@@ -103,15 +101,12 @@ def api_handler(kwargs):
|
||||
mode = kwargs.get('mode', '')
|
||||
output = kwargs.get('output')
|
||||
name = kwargs.get('name', '')
|
||||
callback = kwargs.get('callback', '')
|
||||
|
||||
if isinstance(mode, list):
|
||||
mode = mode[0]
|
||||
if isinstance(output, list):
|
||||
output = output[0]
|
||||
response = _api_table.get(mode, (_api_undefined, 2))[0](name, output, kwargs)
|
||||
if output == 'json' and callback:
|
||||
response = '%s(%s)' % (callback, response)
|
||||
return response
|
||||
|
||||
|
||||
@@ -223,6 +218,8 @@ def _api_queue_pause(output, value, kwargs):
|
||||
if value:
|
||||
items = value.split(',')
|
||||
handled = NzbQueue.do.pause_multiple_nzo(items)
|
||||
else:
|
||||
handled = False
|
||||
return report(output, keyword='', data={'status': bool(handled), 'nzo_ids': handled})
|
||||
|
||||
|
||||
@@ -231,6 +228,8 @@ def _api_queue_resume(output, value, kwargs):
|
||||
if value:
|
||||
items = value.split(',')
|
||||
handled = NzbQueue.do.resume_multiple_nzo(items)
|
||||
else:
|
||||
handled = False
|
||||
return report(output, keyword='', data={'status': bool(handled), 'nzo_ids': handled})
|
||||
|
||||
|
||||
@@ -344,7 +343,7 @@ def _api_addfile(name, output, kwargs):
|
||||
# Indexer category, so do mapping
|
||||
cat = cat_convert(xcat)
|
||||
res = sabnzbd.add_nzbfile(name, kwargs.get('pp'), kwargs.get('script'), cat,
|
||||
kwargs.get('priority'), kwargs.get('nzbname'))
|
||||
kwargs.get('priority'), kwargs.get('nzbname'))
|
||||
return report(output, keyword='', data={'status': res[0] == 0, 'nzo_ids': res[1]}, compat=True)
|
||||
else:
|
||||
return report(output, _MSG_NO_VALUE)
|
||||
@@ -401,7 +400,7 @@ def _api_addlocalfile(name, output, kwargs):
|
||||
if get_ext(name) in VALID_ARCHIVES:
|
||||
res = sabnzbd.dirscanner.ProcessArchiveFile(
|
||||
fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname)
|
||||
elif get_ext(name) in ('.nzb', '.gz', '.bz2'):
|
||||
elif get_ext(name) in VALID_NZB_FILES:
|
||||
res = sabnzbd.dirscanner.ProcessSingleFile(
|
||||
fn, name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname)
|
||||
else:
|
||||
@@ -465,6 +464,7 @@ def _api_change_opts(name, output, kwargs):
|
||||
""" API: accepts output, value(=nzo_id), value2(=pp) """
|
||||
value = kwargs.get('value')
|
||||
value2 = kwargs.get('value2')
|
||||
result = 0
|
||||
if value and value2 and value2.isdigit():
|
||||
result = NzbQueue.do.change_opts(value, int(value2))
|
||||
return report(output, keyword='status', data=bool(result > 0))
|
||||
@@ -486,7 +486,6 @@ def _api_history(name, output, kwargs):
|
||||
failed_only = kwargs.get('failed_only')
|
||||
categories = kwargs.get('category')
|
||||
|
||||
|
||||
# Do we need to send anything?
|
||||
if last_history_update == sabnzbd.LAST_HISTORY_UPDATE:
|
||||
return report(output, keyword='history', data=False)
|
||||
@@ -501,7 +500,7 @@ def _api_history(name, output, kwargs):
|
||||
special = value.lower()
|
||||
del_files = bool(int_conv(kwargs.get('del_files')))
|
||||
if special in ('all', 'failed', 'completed'):
|
||||
history_db = sabnzbd.connect_db()
|
||||
history_db = sabnzbd.get_db_connection()
|
||||
if special in ('all', 'failed'):
|
||||
if del_files:
|
||||
del_job_files(history_db.get_failed_paths(search))
|
||||
@@ -522,7 +521,7 @@ def _api_history(name, output, kwargs):
|
||||
history = {}
|
||||
grand, month, week, day = BPSMeter.do.get_sums()
|
||||
history['total_size'], history['month_size'], history['week_size'], history['day_size'] = \
|
||||
to_units(grand), to_units(month), to_units(week), to_units(day)
|
||||
to_units(grand), to_units(month), to_units(week), to_units(day)
|
||||
history['slots'], fetched_items, history['noofslots'] = build_history(start=start,
|
||||
limit=limit, verbose=True,
|
||||
search=search, failed_only=failed_only,
|
||||
@@ -592,10 +591,7 @@ def _api_resume(name, output, kwargs):
|
||||
|
||||
def _api_shutdown(name, output, kwargs):
|
||||
""" API: accepts output """
|
||||
logging.info('Shutdown requested by API')
|
||||
sabnzbd.halt()
|
||||
cherrypy.engine.exit()
|
||||
sabnzbd.SABSTOP = True
|
||||
sabnzbd.shutdown_program()
|
||||
return report(output)
|
||||
|
||||
|
||||
@@ -730,9 +726,7 @@ def _api_reset_quota(name, output, kwargs):
|
||||
def _api_test_email(name, output, kwargs):
|
||||
""" API: send a test email, return result """
|
||||
logging.info("Sending test email")
|
||||
pack = {}
|
||||
pack['download'] = ['action 1', 'action 2']
|
||||
pack['unpack'] = ['action 1', 'action 2']
|
||||
pack = {'download': ['action 1', 'action 2'], 'unpack': ['action 1', 'action 2']}
|
||||
res = sabnzbd.emailer.endjob(u'I had a d\xe8ja vu', 'unknown', True,
|
||||
os.path.normpath(os.path.join(cfg.complete_dir.get_path(), u'/unknown/I had a d\xe8ja vu')),
|
||||
123 * MEBI, None, pack, 'my_script', u'Line 1\nLine 2\nLine 3\nd\xe8ja vu\n', 0,
|
||||
@@ -808,7 +802,6 @@ def _api_browse(name, output, kwargs):
|
||||
compact = kwargs.get('compact')
|
||||
|
||||
if compact and compact == '1':
|
||||
paths = []
|
||||
name = platform_encode(kwargs.get('term', ''))
|
||||
paths = [entry['path'] for entry in folders_at_path(os.path.dirname(name)) if 'path' in entry]
|
||||
return report(output, keyword='', data=paths)
|
||||
@@ -898,12 +891,11 @@ def _api_config_undefined(output, kwargs):
|
||||
def _api_server_stats(name, output, kwargs):
|
||||
""" API: accepts output """
|
||||
sum_t, sum_m, sum_w, sum_d = BPSMeter.do.get_sums()
|
||||
stats = {'total': sum_t, 'month': sum_m, 'week': sum_w, 'day': sum_d}
|
||||
stats = {'total': sum_t, 'month': sum_m, 'week': sum_w, 'day': sum_d, 'servers': {}}
|
||||
|
||||
stats['servers'] = {}
|
||||
for svr in config.get_servers():
|
||||
t, m, w, d, daily = BPSMeter.do.amounts(svr)
|
||||
stats['servers'][svr] = {'total': t or 0, 'month': m or 0, 'week': w or 0, 'day': d or 0, 'daily': daily or {} }
|
||||
stats['servers'][svr] = {'total': t or 0, 'month': m or 0, 'week': w or 0, 'day': d or 0, 'daily': daily or {}}
|
||||
|
||||
return report(output, keyword='', data=stats)
|
||||
|
||||
@@ -1002,7 +994,7 @@ def api_level(cmd, name):
|
||||
return 4
|
||||
|
||||
|
||||
def report(output, error=None, keyword='value', data=None, callback=None, compat=False):
|
||||
def report(output, error=None, keyword='value', data=None, compat=False):
|
||||
""" Report message in json, xml or plain text
|
||||
If error is set, only an status/error report is made.
|
||||
If no error and no data, only a status report is made.
|
||||
@@ -1031,8 +1023,6 @@ def report(output, error=None, keyword='value', data=None, callback=None, compat
|
||||
if not FAST_JSON:
|
||||
# Use the slower, but safer encoder
|
||||
response = JsonWriter().write(info)
|
||||
if callback:
|
||||
response = '%s(%s)' % (callback, response)
|
||||
|
||||
elif output == 'xml':
|
||||
if not keyword:
|
||||
@@ -1158,6 +1148,24 @@ def handle_rss_api(output, kwargs):
|
||||
feed.set_dict(kwargs)
|
||||
else:
|
||||
config.ConfigRSS(name, kwargs)
|
||||
|
||||
action = kwargs.get('filter_action')
|
||||
if action in ('add', 'update'):
|
||||
# Use the general function, but catch the redirect-raise
|
||||
try:
|
||||
kwargs['feed'] = name
|
||||
sabnzbd.interface.ConfigRss('/').internal_upd_rss_filter(**kwargs)
|
||||
except cherrypy.HTTPRedirect:
|
||||
pass
|
||||
|
||||
elif action == 'delete':
|
||||
# Use the general function, but catch the redirect-raise
|
||||
try:
|
||||
kwargs['feed'] = name
|
||||
sabnzbd.interface.ConfigRss('/').internal_del_rss_filter(**kwargs)
|
||||
except cherrypy.HTTPRedirect:
|
||||
pass
|
||||
|
||||
return name
|
||||
|
||||
|
||||
@@ -1206,7 +1214,7 @@ def build_status(skip_dashboard=False, output=None):
|
||||
info['ipv6'] = ipv6()
|
||||
# Dashboard: DNS-check
|
||||
try:
|
||||
getipaddress.addresslookup(cfg.selftest_host())
|
||||
addresslookup(cfg.selftest_host())
|
||||
info['dnslookup'] = "OK"
|
||||
except:
|
||||
info['dnslookup'] = None
|
||||
@@ -1241,10 +1249,10 @@ def build_status(skip_dashboard=False, output=None):
|
||||
|
||||
# For the templates or for JSON
|
||||
if output:
|
||||
thread_info = { 'thrdnum': nw.thrdnum,
|
||||
'art_name': art_name,
|
||||
'nzf_name': nzf_name,
|
||||
'nzo_name': nzo_name }
|
||||
thread_info = {'thrdnum': nw.thrdnum,
|
||||
'art_name': art_name,
|
||||
'nzf_name': nzf_name,
|
||||
'nzo_name': nzo_name}
|
||||
serverconnections.append(thread_info)
|
||||
else:
|
||||
serverconnections.append((nw.thrdnum, art_name, nzf_name, nzo_name))
|
||||
@@ -1261,20 +1269,20 @@ def build_status(skip_dashboard=False, output=None):
|
||||
|
||||
# For the templates or for JSON
|
||||
if output:
|
||||
server_info = { 'servername': server.displayname,
|
||||
'serveractiveconn': connected,
|
||||
'servertotalconn': server.threads,
|
||||
'serverconnections': serverconnections,
|
||||
'serverssl': server.ssl,
|
||||
'serversslinfo': server.ssl_info,
|
||||
'serveractive': server.active,
|
||||
'servererror': server.errormsg,
|
||||
'serverpriority': server.priority,
|
||||
'serveroptional': server.optional }
|
||||
server_info = {'servername': server.displayname,
|
||||
'serveractiveconn': connected,
|
||||
'servertotalconn': server.threads,
|
||||
'serverconnections': serverconnections,
|
||||
'serverssl': server.ssl,
|
||||
'serversslinfo': server.ssl_info,
|
||||
'serveractive': server.active,
|
||||
'servererror': server.errormsg,
|
||||
'serverpriority': server.priority,
|
||||
'serveroptional': server.optional}
|
||||
info['servers'].append(server_info)
|
||||
else:
|
||||
info['servers'].append((server.displayname, '', connected, serverconnections, server.ssl,
|
||||
server.active, server.errormsg, server.priority, server.optional))
|
||||
server.active, server.errormsg, server.priority, server.optional))
|
||||
|
||||
info['warnings'] = sabnzbd.GUIHANDLER.content()
|
||||
|
||||
@@ -1354,10 +1362,10 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None):
|
||||
# Ensure compatibility of API status
|
||||
if status == Status.DELETED or priority == TOP_PRIORITY:
|
||||
status = Status.DOWNLOADING
|
||||
slot['status'] = "%s" % (status)
|
||||
slot['status'] = "%s" % status
|
||||
|
||||
if (Downloader.do.paused or Downloader.do.postproc or is_propagating or \
|
||||
status not in (Status.DOWNLOADING, Status.FETCHING, Status.QUEUED)) and priority != TOP_PRIORITY:
|
||||
if (Downloader.do.paused or Downloader.do.postproc or is_propagating or
|
||||
status not in (Status.DOWNLOADING, Status.FETCHING, Status.QUEUED)) and priority != TOP_PRIORITY:
|
||||
slot['timeleft'] = '0:00:00'
|
||||
slot['eta'] = 'unknown'
|
||||
else:
|
||||
@@ -1518,16 +1526,17 @@ def options_list(output):
|
||||
})
|
||||
|
||||
|
||||
def retry_job(job, new_nzb, password):
|
||||
def retry_job(job, new_nzb=None, password=None):
|
||||
""" Re enter failed job in the download queue """
|
||||
if job:
|
||||
history_db = sabnzbd.connect_db()
|
||||
history_db = sabnzbd.get_db_connection()
|
||||
futuretype, url, pp, script, cat = history_db.get_other(job)
|
||||
if futuretype:
|
||||
if pp == 'X':
|
||||
pp = None
|
||||
sabnzbd.add_url(url, pp, script, cat)
|
||||
nzo_id = sabnzbd.add_url(url, pp, script, cat)
|
||||
history_db.remove_history(job)
|
||||
return nzo_id
|
||||
else:
|
||||
path = history_db.get_path(job)
|
||||
if path:
|
||||
@@ -1539,8 +1548,13 @@ def retry_job(job, new_nzb, password):
|
||||
|
||||
def retry_all_jobs():
|
||||
""" Re enter all failed jobs in the download queue """
|
||||
history_db = sabnzbd.connect_db()
|
||||
return NzbQueue.do.retry_all_jobs(history_db)
|
||||
# Fetch all retryable folders from History
|
||||
items = sabnzbd.api.build_history()[0]
|
||||
nzo_ids = []
|
||||
for item in items:
|
||||
if item['retry']:
|
||||
nzo_ids.append(retry_job(item['nzo_id']))
|
||||
return nzo_ids
|
||||
|
||||
|
||||
def del_job_files(job_paths):
|
||||
@@ -1557,7 +1571,7 @@ def del_hist_job(job, del_files):
|
||||
if path:
|
||||
PostProcessor.do.delete(job, del_files=del_files)
|
||||
else:
|
||||
history_db = sabnzbd.connect_db()
|
||||
history_db = sabnzbd.get_db_connection()
|
||||
path = history_db.get_path(job)
|
||||
history_db.remove_history(job)
|
||||
|
||||
@@ -1576,7 +1590,9 @@ def Tspec(txt):
|
||||
return txt
|
||||
|
||||
|
||||
_SKIN_CACHE = {} # Stores pre-translated acronyms
|
||||
_SKIN_CACHE = {} # Stores pre-translated acronyms
|
||||
|
||||
|
||||
# This special is to be used in interface.py for template processing
|
||||
# to be passed for the $T function: so { ..., 'T' : Ttemplate, ...}
|
||||
def Ttemplate(txt):
|
||||
@@ -1693,7 +1709,6 @@ def build_queue_header(search=None, start=0, limit=0, output=None):
|
||||
header['size'] = format_bytes(bytes)
|
||||
header['noofslots_total'] = qnfo.q_fullsize
|
||||
|
||||
status = ''
|
||||
if Downloader.do.paused or Downloader.do.postproc:
|
||||
status = Status.PAUSED
|
||||
elif bytespersec > 0:
|
||||
@@ -1708,15 +1723,13 @@ def build_queue_header(search=None, start=0, limit=0, output=None):
|
||||
# new eta format: 16:00 Fri 07 Feb
|
||||
header['eta'] = datestart.strftime(time_format('%H:%M %a %d %b')).decode(codepage)
|
||||
except:
|
||||
datestart = datetime.datetime.now()
|
||||
header['eta'] = T('unknown')
|
||||
|
||||
return (header, qnfo.list, bytespersec, qnfo.q_fullsize, qnfo.bytes_left_previous_page)
|
||||
return header, qnfo.list, bytespersec, qnfo.q_fullsize, qnfo.bytes_left_previous_page
|
||||
|
||||
|
||||
def build_history(start=None, limit=None, verbose=False, verbose_list=None, search=None, failed_only=0,
|
||||
categories=None, output=None):
|
||||
|
||||
if output:
|
||||
converter = unicoder
|
||||
else:
|
||||
@@ -1769,7 +1782,7 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
|
||||
|
||||
# Aquire the db instance
|
||||
try:
|
||||
history_db = sabnzbd.connect_db()
|
||||
history_db = sabnzbd.get_db_connection()
|
||||
close_db = False
|
||||
except:
|
||||
# Required for repairs at startup because Cherrypy isn't active yet
|
||||
@@ -1780,7 +1793,6 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
|
||||
if not h_limit:
|
||||
items, fetched_items, total_items = history_db.fetch_history(h_start, 1, search, failed_only, categories)
|
||||
items = []
|
||||
fetched_items = 0
|
||||
else:
|
||||
items, fetched_items, total_items = history_db.fetch_history(h_start, h_limit, search, failed_only, categories)
|
||||
|
||||
@@ -1822,10 +1834,9 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
|
||||
item['show_details'] = 'True'
|
||||
else:
|
||||
item['show_details'] = ''
|
||||
if item['bytes']:
|
||||
item['size'] = format_bytes(item['bytes'])
|
||||
else:
|
||||
item['size'] = ''
|
||||
|
||||
item['size'] = format_bytes(item['bytes'])
|
||||
|
||||
if 'loaded' not in item:
|
||||
item['loaded'] = False
|
||||
|
||||
@@ -1865,7 +1876,7 @@ def build_history(start=None, limit=None, verbose=False, verbose_list=None, sear
|
||||
if close_db:
|
||||
history_db.close()
|
||||
|
||||
return (items, fetched_items, total_items)
|
||||
return items, fetched_items, total_items
|
||||
|
||||
|
||||
def get_active_history(queue=None, items=None):
|
||||
@@ -2021,7 +2032,6 @@ def history_remove_failed():
|
||||
del_job_files(history_db.get_failed_paths())
|
||||
history_db.remove_failed()
|
||||
history_db.close()
|
||||
del history_db
|
||||
|
||||
|
||||
def history_remove_completed():
|
||||
@@ -2030,4 +2040,3 @@ def history_remove_completed():
|
||||
history_db = HistoryDB()
|
||||
history_db.remove_completed()
|
||||
history_db.close()
|
||||
del history_db
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -28,9 +28,9 @@ from time import sleep
|
||||
import hashlib
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.misc import get_filepath, sanitize_filename, get_unique_filename, renamer, \
|
||||
set_permissions, long_path, clip_path, has_win_device, get_all_passwords, diskspace, \
|
||||
get_filename, get_ext
|
||||
from sabnzbd.misc import get_filepath, sanitize_filename, set_permissions, \
|
||||
long_path, clip_path, has_win_device, get_all_passwords, diskspace, \
|
||||
get_filename, get_ext, is_rarfile
|
||||
from sabnzbd.constants import Status, GIGI
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.articlecache import ArticleCache
|
||||
@@ -81,11 +81,6 @@ class Assembler(Thread):
|
||||
# Abort all direct unpackers, just to be sure
|
||||
sabnzbd.directunpacker.abort_all()
|
||||
|
||||
# Place job back in queue and wait 30 seconds to hope it gets resolved
|
||||
self.process(job)
|
||||
sleep(30)
|
||||
continue
|
||||
|
||||
# Prepare filename
|
||||
nzo.verify_nzf_filename(nzf)
|
||||
nzf.filename = sanitize_filename(nzf.filename)
|
||||
@@ -117,7 +112,7 @@ class Assembler(Thread):
|
||||
nzf.remove_admin()
|
||||
|
||||
# Do rar-related processing
|
||||
if rarfile.is_rarfile(filepath):
|
||||
if is_rarfile(filepath):
|
||||
# Encryption and unwanted extension detection
|
||||
rar_encrypted, unwanted_file = check_encrypted_and_unwanted_files(nzo, filepath)
|
||||
if rar_encrypted:
|
||||
@@ -210,6 +205,7 @@ def file_has_articles(nzf):
|
||||
|
||||
|
||||
RE_SUBS = re.compile(r'\W+sub|subs|subpack|subtitle|subtitles(?![a-z])', re.I)
|
||||
SAFE_EXTS = ('.mkv', '.mp4', '.avi', '.wmv', '.mpg', '.webm')
|
||||
def is_cloaked(nzo, path, names):
|
||||
""" Return True if this is likely to be a cloaked encrypted post """
|
||||
fname = unicoder(get_filename(path)).lower()
|
||||
@@ -223,7 +219,7 @@ def is_cloaked(nzo, path, names):
|
||||
logging.warning(T('Job "%s" is probably encrypted due to RAR with same name inside this RAR'), nzo.final_name)
|
||||
nzo.encrypted = 1
|
||||
return True
|
||||
elif 'password' in name:
|
||||
elif 'password' in name and ext not in SAFE_EXTS:
|
||||
# Only warn once
|
||||
if nzo.encrypted == 0:
|
||||
logging.warning(T('Job "%s" is probably encrypted: "password" in filename "%s"'), nzo.final_name, name)
|
||||
@@ -245,7 +241,7 @@ def check_encrypted_and_unwanted_files(nzo, filepath):
|
||||
return encrypted, unwanted
|
||||
|
||||
# Is it even a rarfile?
|
||||
if rarfile.is_rarfile(filepath):
|
||||
if is_rarfile(filepath):
|
||||
# Open the rar
|
||||
rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND
|
||||
zf = rarfile.RarFile(filepath, all_names=True)
|
||||
@@ -333,11 +329,11 @@ def nzo_filtered_by_rating(nzo):
|
||||
nzo.rating_filtered = 1
|
||||
reason = rating_filtered(rating, nzo.filename.lower(), True)
|
||||
if reason is not None:
|
||||
return (2, reason)
|
||||
return 2, reason
|
||||
reason = rating_filtered(rating, nzo.filename.lower(), False)
|
||||
if reason is not None:
|
||||
return (1, reason)
|
||||
return (0, "")
|
||||
return 1, reason
|
||||
return 0, ""
|
||||
|
||||
|
||||
def rating_filtered(rating, filename, abort):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -26,7 +26,7 @@ from sabnzbd.constants import DEF_HOST, DEF_PORT, DEF_STDINTF, DEF_ADMIN_DIR, \
|
||||
|
||||
from sabnzbd.config import OptionBool, OptionNumber, OptionPassword, \
|
||||
OptionDir, OptionStr, OptionList, no_nonsense, \
|
||||
validate_octal, validate_safedir, \
|
||||
validate_octal, validate_safedir, all_lowercase, \
|
||||
create_api_key, validate_notempty
|
||||
|
||||
##############################################################################
|
||||
@@ -137,14 +137,16 @@ top_only = OptionBool('misc', 'top_only', False)
|
||||
sfv_check = OptionBool('misc', 'sfv_check', True)
|
||||
quick_check_ext_ignore = OptionList('misc', 'quick_check_ext_ignore', ['nfo', 'sfv', 'srr'])
|
||||
script_can_fail = OptionBool('misc', 'script_can_fail', False)
|
||||
ssl_ciphers = OptionStr('misc', 'ssl_ciphers', '')
|
||||
ssl_ciphers = OptionStr('misc', 'ssl_ciphers', '') # Now per-server setting
|
||||
enable_recursive = OptionBool('misc', 'enable_recursive', True)
|
||||
flat_unpack = OptionBool('misc', 'flat_unpack', False)
|
||||
par_option = OptionStr('misc', 'par_option', '', validation=no_nonsense)
|
||||
pre_check = OptionBool('misc', 'pre_check', False)
|
||||
nice = OptionStr('misc', 'nice', '', validation=no_nonsense)
|
||||
win_process_prio = OptionNumber('misc', 'win_process_prio', 3)
|
||||
ionice = OptionStr('misc', 'ionice', '', validation=no_nonsense)
|
||||
fail_hopeless_jobs = OptionBool('misc', 'fail_hopeless_jobs', True)
|
||||
fast_fail = OptionBool('misc', 'fast_fail', True)
|
||||
autodisconnect = OptionBool('misc', 'auto_disconnect', True)
|
||||
no_dupes = OptionNumber('misc', 'no_dupes', 0)
|
||||
no_series_dupes = OptionNumber('misc', 'no_series_dupes', 0)
|
||||
@@ -262,6 +264,9 @@ api_warnings = OptionBool('misc', 'api_warnings', True, protect=True)
|
||||
disable_key = OptionBool('misc', 'disable_api_key', False, protect=True)
|
||||
no_penalties = OptionBool('misc', 'no_penalties', False)
|
||||
debug_log_decoding = OptionBool('misc', 'debug_log_decoding', False)
|
||||
ignore_empty_files = OptionBool('misc', 'ignore_empty_files', False)
|
||||
x_frame_options = OptionBool('misc', 'x_frame_options', True)
|
||||
require_modern_tls = OptionBool('misc', 'require_modern_tls', False)
|
||||
|
||||
# Text values
|
||||
rss_odd_titles = OptionList('misc', 'rss_odd_titles', ['nzbindex.nl/', 'nzbindex.com/', 'nzbclub.com/'])
|
||||
@@ -277,6 +282,8 @@ wait_ext_drive = OptionNumber('misc', 'wait_ext_drive', 5, 1, 60)
|
||||
marker_file = OptionStr('misc', 'nomedia_marker', '')
|
||||
ipv6_servers = OptionNumber('misc', 'ipv6_servers', 1, 0, 2)
|
||||
url_base = OptionStr('misc', 'url_base', '/sabnzbd')
|
||||
host_whitelist = OptionList('misc', 'host_whitelist', validation=all_lowercase)
|
||||
max_url_retries = OptionNumber('misc', 'max_url_retries', 10, 1)
|
||||
|
||||
##############################################################################
|
||||
# Config - Notifications
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -391,13 +391,12 @@ class ConfigServer(object):
|
||||
self.connections = OptionNumber(name, 'connections', 1, 0, 100, add=False)
|
||||
self.ssl = OptionBool(name, 'ssl', False, add=False)
|
||||
self.ssl_verify = OptionNumber(name, 'ssl_verify', 2, add=False) # 0=No, 1=Normal, 2=Strict (hostname verification)
|
||||
self.ssl_ciphers = OptionStr(name, 'ssl_ciphers', '', add=False)
|
||||
self.enable = OptionBool(name, 'enable', True, add=False)
|
||||
self.optional = OptionBool(name, 'optional', False, add=False)
|
||||
self.retention = OptionNumber(name, 'retention', add=False)
|
||||
self.send_group = OptionBool(name, 'send_group', False, add=False)
|
||||
self.priority = OptionNumber(name, 'priority', 0, 0, 99, add=False)
|
||||
# 'fillserver' field only here in order to set a proper priority when converting
|
||||
self.fillserver = OptionBool(name, 'fillserver', False, add=False)
|
||||
self.notes = OptionStr(name, 'notes', '', add=False)
|
||||
|
||||
self.set_dict(values)
|
||||
@@ -405,15 +404,15 @@ class ConfigServer(object):
|
||||
|
||||
def set_dict(self, values):
|
||||
""" Set one or more fields, passed as dictionary """
|
||||
for kw in ('displayname', 'host', 'port', 'timeout', 'username', 'password', 'connections', 'fillserver',
|
||||
'ssl', 'ssl_verify', 'send_group', 'enable', 'optional', 'retention', 'priority', 'notes'):
|
||||
for kw in ('displayname', 'host', 'port', 'timeout', 'username', 'password', 'connections', 'ssl',
|
||||
'ssl_verify', 'ssl_ciphers', 'send_group', 'enable', 'optional', 'retention', 'priority', 'notes'):
|
||||
try:
|
||||
value = values[kw]
|
||||
except KeyError:
|
||||
continue
|
||||
exec 'self.%s.set(value)' % kw
|
||||
if not self.displayname():
|
||||
self.displayname.set(self.__name)
|
||||
if not self.displayname():
|
||||
self.displayname.set(self.__name)
|
||||
return True
|
||||
|
||||
def get_dict(self, safe=False):
|
||||
@@ -432,6 +431,7 @@ class ConfigServer(object):
|
||||
dict['connections'] = self.connections()
|
||||
dict['ssl'] = self.ssl()
|
||||
dict['ssl_verify'] = self.ssl_verify()
|
||||
dict['ssl_ciphers'] = self.ssl_ciphers()
|
||||
dict['enable'] = self.enable()
|
||||
dict['optional'] = self.optional()
|
||||
dict['retention'] = self.retention()
|
||||
@@ -463,7 +463,7 @@ class ConfigCat(object):
|
||||
self.pp = OptionStr(name, 'pp', '', add=False)
|
||||
self.script = OptionStr(name, 'script', 'Default', add=False)
|
||||
self.dir = OptionDir(name, 'dir', add=False, create=False)
|
||||
self.newzbin = OptionList(name, 'newzbin', add=False)
|
||||
self.newzbin = OptionList(name, 'newzbin', add=False, validation=validate_single_tag)
|
||||
self.priority = OptionNumber(name, 'priority', DEFAULT_PRIORITY, add=False)
|
||||
|
||||
self.set_dict(values)
|
||||
@@ -877,13 +877,16 @@ def define_servers():
|
||||
for server in CFG['servers']:
|
||||
svr = CFG['servers'][server]
|
||||
s = ConfigServer(server.replace('{', '[').replace('}', ']'), svr)
|
||||
if s.fillserver():
|
||||
# One time conversion of backup to priority 1
|
||||
s.priority.set(1)
|
||||
s.fillserver.set(False)
|
||||
|
||||
# Conversion of global SSL-Ciphers to server ones
|
||||
if sabnzbd.cfg.ssl_ciphers():
|
||||
s.ssl_ciphers.set(sabnzbd.cfg.ssl_ciphers())
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
# No longer needed
|
||||
sabnzbd.cfg.ssl_ciphers.set('')
|
||||
|
||||
|
||||
def get_servers():
|
||||
global database
|
||||
@@ -893,7 +896,7 @@ def get_servers():
|
||||
return {}
|
||||
|
||||
|
||||
def define_categories(force=False):
|
||||
def define_categories():
|
||||
""" Define categories listed in the Setup file
|
||||
return a list of ConfigCat instances
|
||||
"""
|
||||
@@ -987,7 +990,7 @@ def get_rss():
|
||||
for feed_uri in feed.uri():
|
||||
if new_feed_uris and not urlparse(feed_uri).scheme and urlparse(new_feed_uris[-1]).scheme:
|
||||
# Current one has no scheme but previous one does, append to previous
|
||||
new_feed_uris[-1] += '%2C' + feed_uri
|
||||
new_feed_uris[-1] += ',' + feed_uri
|
||||
have_new_uri = True
|
||||
continue
|
||||
# Add full working URL
|
||||
@@ -1051,6 +1054,14 @@ def no_nonsense(value):
|
||||
return None, value
|
||||
|
||||
|
||||
def all_lowercase(value):
|
||||
""" Lowercase everything! """
|
||||
if isinstance(value, list):
|
||||
# If list, for each item
|
||||
return None, [item.lower() for item in value]
|
||||
return None, value.lower()
|
||||
|
||||
|
||||
def validate_octal(value):
|
||||
""" Check if string is valid octal number """
|
||||
if not value:
|
||||
@@ -1091,6 +1102,16 @@ def validate_notempty(root, value, default):
|
||||
return None, default
|
||||
|
||||
|
||||
def validate_single_tag(value):
|
||||
""" Don't split single indexer tags like "TV > HD"
|
||||
into ['TV', '>', 'HD']
|
||||
"""
|
||||
if len(value) == 3:
|
||||
if value[1] == '>':
|
||||
return None, ' '.join(value)
|
||||
return None, value
|
||||
|
||||
|
||||
def create_api_key():
|
||||
""" Return a new randomized API_KEY """
|
||||
# Create some values to seed md5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -51,7 +51,7 @@ RENAMES_FILE = '__renames__'
|
||||
ATTRIB_FILE = 'SABnzbd_attrib'
|
||||
REPAIR_REQUEST = 'repair-all.sab'
|
||||
|
||||
SABYENC_VERSION_REQUIRED = '3.3.2'
|
||||
SABYENC_VERSION_REQUIRED = '3.3.5'
|
||||
|
||||
DB_HISTORY_VERSION = 1
|
||||
DB_HISTORY_NAME = 'history%s.db' % DB_HISTORY_VERSION
|
||||
@@ -78,7 +78,6 @@ DEF_ARTICLE_CACHE_DEFAULT = '500M'
|
||||
DEF_ARTICLE_CACHE_MAX = '1G'
|
||||
DEF_TIMEOUT = 60
|
||||
DEF_SCANRATE = 5
|
||||
MAX_URL_RETRIES = 10
|
||||
MAX_DECODE_QUEUE = 10
|
||||
LIMIT_DECODE_QUEUE = 100
|
||||
MAX_WARNINGS = 20
|
||||
@@ -98,6 +97,7 @@ STOP_PRIORITY = -4
|
||||
STAGES = {'Source': 0, 'Download': 1, 'Servers': 2, 'Repair': 3, 'Filejoin': 4, 'Unpack': 5, 'Script': 6}
|
||||
|
||||
VALID_ARCHIVES = ('.zip', '.rar', '.7z')
|
||||
VALID_NZB_FILES = ('.nzb', '.gz', '.bz2')
|
||||
|
||||
IGNORED_FOLDERS = ('@eaDir', '.appleDouble')
|
||||
|
||||
@@ -123,7 +123,7 @@ year_match = r'[\W]([1|2]\d{3})([^\w]|$)' # Something '(YYYY)' or '.YYYY.' or '
|
||||
sample_match = r'((^|[\W_])(sample|proof))' # something-sample or something-proof
|
||||
|
||||
|
||||
class Status():
|
||||
class Status:
|
||||
COMPLETED = 'Completed' # PP: Job is finished
|
||||
CHECKING = 'Checking' # Q: Pre-check is running
|
||||
DOWNLOADING = 'Downloading' # Q: Normal downloading
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -40,7 +40,7 @@ from sabnzbd.constants import DB_HISTORY_NAME, STAGES
|
||||
from sabnzbd.encoding import unicoder
|
||||
from sabnzbd.bpsmeter import this_week, this_month
|
||||
from sabnzbd.decorators import synchronized
|
||||
from sabnzbd.misc import get_all_passwords, int_conv, remove_file, caller_name
|
||||
from sabnzbd.misc import int_conv, remove_file, caller_name
|
||||
|
||||
DB_LOCK = threading.RLock()
|
||||
|
||||
@@ -118,7 +118,7 @@ class HistoryDB(object):
|
||||
self.execute('ALTER TABLE "history" ADD COLUMN password TEXT;')
|
||||
|
||||
def execute(self, command, args=(), save=False):
|
||||
''' Wrapper for executing SQL commands '''
|
||||
""" Wrapper for executing SQL commands """
|
||||
for tries in xrange(5, 0, -1):
|
||||
try:
|
||||
if args and isinstance(args, tuple):
|
||||
@@ -314,7 +314,7 @@ class HistoryDB(object):
|
||||
# Stage Name is separated by ::: stage lines by ; and stages by \r\n
|
||||
items = [unpack_history_info(item) for item in items]
|
||||
|
||||
return (items, fetched_items, total_items)
|
||||
return items, fetched_items, total_items
|
||||
|
||||
def have_episode(self, series, season, episode):
|
||||
""" Check whether History contains this series episode """
|
||||
@@ -375,7 +375,7 @@ class HistoryDB(object):
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
return (total, month, week)
|
||||
return total, month, week
|
||||
|
||||
def get_script_log(self, nzo_id):
|
||||
""" Return decompressed log file """
|
||||
@@ -400,7 +400,7 @@ class HistoryDB(object):
|
||||
return name
|
||||
|
||||
def get_path(self, nzo_id):
|
||||
""" Return the `incomplete` path of the job `nzo_id` """
|
||||
""" Return the `incomplete` path of the job `nzo_id` if it is still there """
|
||||
t = (nzo_id,)
|
||||
path = ''
|
||||
if self.execute('SELECT path FROM history WHERE nzo_id=?', t):
|
||||
@@ -408,7 +408,9 @@ class HistoryDB(object):
|
||||
path = self.c.fetchone().get('path')
|
||||
except AttributeError:
|
||||
pass
|
||||
return path
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
return None
|
||||
|
||||
def get_other(self, nzo_id):
|
||||
""" Return additional data for job `nzo_id` """
|
||||
@@ -421,9 +423,10 @@ class HistoryDB(object):
|
||||
pp = items.get('pp')
|
||||
script = items.get('script')
|
||||
cat = items.get('category')
|
||||
return dtype, url, pp, script, cat
|
||||
except (AttributeError, IndexError):
|
||||
return '', '', '', '', ''
|
||||
return dtype, url, pp, script, cat
|
||||
pass
|
||||
return '', '', '', '', ''
|
||||
|
||||
|
||||
def dict_factory(cursor, row):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -125,7 +125,7 @@ class Decoder(Thread):
|
||||
nzf.article_count += 1
|
||||
found = True
|
||||
|
||||
except IOError, e:
|
||||
except IOError:
|
||||
logme = T('Decoding %s failed') % art_id
|
||||
logging.warning(logme)
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
@@ -134,7 +134,7 @@ class Decoder(Thread):
|
||||
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article)
|
||||
register = False
|
||||
|
||||
except MemoryError, e:
|
||||
except MemoryError:
|
||||
logme = T('Decoder failure: Out of memory')
|
||||
logging.warning(logme)
|
||||
anfo = sabnzbd.articlecache.ArticleCache.do.cache_info()
|
||||
@@ -240,7 +240,6 @@ class Decoder(Thread):
|
||||
nzf = article.nzf
|
||||
yenc, data = yCheck(data)
|
||||
ybegin, ypart, yend = yenc
|
||||
decoded_data = None
|
||||
|
||||
# Deal with non-yencoded posts
|
||||
if not ybegin:
|
||||
@@ -379,7 +378,7 @@ def yCheck(data):
|
||||
except IndexError:
|
||||
break
|
||||
|
||||
return ((ybegin, ypart, yend), data)
|
||||
return (ybegin, ypart, yend), data
|
||||
|
||||
# Example: =ybegin part=1 line=128 size=123 name=-=DUMMY=- abc.par
|
||||
YSPLIT_RE = re.compile(r'([a-zA-Z0-9]+)=')
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -28,9 +28,10 @@ import logging
|
||||
|
||||
import sabnzbd
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.misc import int_conv, clip_path, long_path, remove_all, globber, \
|
||||
format_time_string, has_win_device, real_path, remove_file
|
||||
from sabnzbd.misc import int_conv, clip_path, long_path, remove_all, \
|
||||
format_time_string, real_path, remove_file
|
||||
from sabnzbd.encoding import TRANS, unicoder
|
||||
from sabnzbd.decorators import synchronized
|
||||
from sabnzbd.newsunpack import build_command, EXTRACTFROM_RE, EXTRACTED_RE, rar_volumelist
|
||||
from sabnzbd.postproc import prepare_extraction_path
|
||||
from sabnzbd.utils.rarfile import RarFile
|
||||
@@ -46,6 +47,10 @@ if sabnzbd.WIN32:
|
||||
# Load the regular POpen (which is now patched on Windows)
|
||||
from subprocess import Popen
|
||||
|
||||
# Need a lock to make sure start and stop is handled correctlty
|
||||
# Otherwise we could stop while the thread was still starting
|
||||
START_STOP_LOCK = threading.RLock()
|
||||
|
||||
MAX_ACTIVE_UNPACKERS = 10
|
||||
ACTIVE_UNPACKERS = []
|
||||
|
||||
@@ -110,6 +115,7 @@ class DirectUnpacker(threading.Thread):
|
||||
if none_counter > found_counter:
|
||||
self.total_volumes = {}
|
||||
|
||||
@synchronized(START_STOP_LOCK)
|
||||
def add(self, nzf):
|
||||
""" Add jobs and start instance of DirectUnpack """
|
||||
if not cfg.direct_unpack_tested():
|
||||
@@ -170,11 +176,11 @@ class DirectUnpacker(threading.Thread):
|
||||
break
|
||||
|
||||
# Error? Let PP-handle it
|
||||
if linebuf.endswith(('ERROR: ', 'Cannot create', 'in the encrypted file', 'CRC failed', \
|
||||
'checksum failed', 'You need to start extraction from a previous volume', \
|
||||
'password is incorrect', 'Write error', 'checksum error', \
|
||||
'start extraction from a previous volume')):
|
||||
logging.info('Error in DirectUnpack of %s', self.cur_setname)
|
||||
if linebuf.endswith(('ERROR: ', 'Cannot create', 'in the encrypted file', 'CRC failed',
|
||||
'checksum failed', 'You need to start extraction from a previous volume',
|
||||
'password is incorrect', 'Write error', 'checksum error',
|
||||
'start extraction from a previous volume')):
|
||||
logging.info('Error in DirectUnpack of %s: %s', self.cur_setname, linebuf.strip())
|
||||
self.abort()
|
||||
|
||||
if linebuf.endswith('\n'):
|
||||
@@ -309,6 +315,7 @@ class DirectUnpacker(threading.Thread):
|
||||
with self.next_file_lock:
|
||||
self.next_file_lock.wait()
|
||||
|
||||
@synchronized(START_STOP_LOCK)
|
||||
def create_unrar_instance(self):
|
||||
""" Start the unrar instance using the user's options """
|
||||
# Generate extraction path and save for post-proc
|
||||
@@ -337,6 +344,11 @@ class DirectUnpacker(threading.Thread):
|
||||
# The first NZF
|
||||
self.rarfile_nzf = self.have_next_volume()
|
||||
|
||||
# Ignore if maybe this set is not there any more
|
||||
# This can happen due to race/timing issues when creating the sets
|
||||
if not self.rarfile_nzf:
|
||||
return
|
||||
|
||||
# Generate command
|
||||
rarfile_path = os.path.join(self.nzo.downpath, self.rarfile_nzf.filename)
|
||||
if sabnzbd.WIN32:
|
||||
@@ -366,9 +378,10 @@ class DirectUnpacker(threading.Thread):
|
||||
# Doing the first
|
||||
logging.info('DirectUnpacked volume %s for %s', self.cur_volume, self.cur_setname)
|
||||
|
||||
@synchronized(START_STOP_LOCK)
|
||||
def abort(self):
|
||||
""" Abort running instance and delete generated files """
|
||||
if not self.killed:
|
||||
if not self.killed and self.cur_setname:
|
||||
logging.info('Aborting DirectUnpack for %s', self.cur_setname)
|
||||
self.killed = True
|
||||
|
||||
@@ -377,9 +390,28 @@ class DirectUnpacker(threading.Thread):
|
||||
|
||||
# Abort Unrar
|
||||
if self.active_instance:
|
||||
# First we try to abort gracefully
|
||||
try:
|
||||
self.active_instance.stdin.write('Q\n')
|
||||
time.sleep(0.2)
|
||||
except IOError:
|
||||
pass
|
||||
|
||||
# Now force kill and give it a bit of time
|
||||
self.active_instance.kill()
|
||||
# We need to wait for it to kill the process
|
||||
self.active_instance.wait()
|
||||
time.sleep(0.2)
|
||||
|
||||
# Have to collect the return-code to avoid zombie
|
||||
# But it will block forever if the process is in special state.
|
||||
# That should never happen, but it can happen on broken unrar's
|
||||
if self.active_instance.poll():
|
||||
self.active_instance.communicate()
|
||||
else:
|
||||
# It is still running?!? This should never happen
|
||||
# Wait a little bit longer just to be sure..
|
||||
time.sleep(2.0)
|
||||
if not self.active_instance.poll():
|
||||
logging.warning(T('Unable to stop the unrar process.'))
|
||||
|
||||
# Wake up the thread
|
||||
with self.next_file_lock:
|
||||
@@ -404,7 +436,6 @@ class DirectUnpacker(threading.Thread):
|
||||
except:
|
||||
# The user will have to remove it themselves
|
||||
logging.info('Failed to clean Direct Unpack after aborting %s', rarfile_nzf.filename, exc_info=True)
|
||||
pass
|
||||
else:
|
||||
# We can just remove the whole path
|
||||
remove_all(extraction_path, recursive=True)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -28,7 +28,7 @@ import bz2
|
||||
import threading
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import SCAN_FILE_NAME, VALID_ARCHIVES
|
||||
from sabnzbd.constants import SCAN_FILE_NAME, VALID_ARCHIVES, VALID_NZB_FILES
|
||||
import sabnzbd.utils.rarfile as rarfile
|
||||
from sabnzbd.encoding import platform_encode
|
||||
from sabnzbd.decorators import NzbQueueLocker
|
||||
@@ -76,7 +76,7 @@ def is_archive(path):
|
||||
except:
|
||||
logging.info(T('Cannot read %s'), path, exc_info=True)
|
||||
return -1, None, ''
|
||||
elif rarfile.is_rarfile(path):
|
||||
elif misc.is_rarfile(path):
|
||||
try:
|
||||
# Set path to tool to open it
|
||||
rarfile.UNRAR_TOOL = sabnzbd.newsunpack.RAR_COMMAND
|
||||
@@ -144,7 +144,7 @@ def ProcessArchiveFile(filename, path, pp=None, script=None, cat=None, catdir=No
|
||||
priority=priority, nzbname=nzbname)
|
||||
if not nzo.password:
|
||||
nzo.password = password
|
||||
except (TypeError, ValueError) as e:
|
||||
except (TypeError, ValueError):
|
||||
# Duplicate or empty, ignore
|
||||
pass
|
||||
except:
|
||||
@@ -232,7 +232,7 @@ def ProcessSingleFile(filename, path, pp=None, script=None, cat=None, catdir=Non
|
||||
# Empty, but correct file
|
||||
return -1, nzo_ids
|
||||
except:
|
||||
if data.find("<nzb") >= 0 and data.find("</nzb") < 0:
|
||||
if data.find("<nzb") >= 0 > data.find("</nzb"):
|
||||
# Looks like an incomplete file, retry
|
||||
return -2, nzo_ids
|
||||
else:
|
||||
@@ -358,7 +358,7 @@ class DirScanner(threading.Thread):
|
||||
continue
|
||||
|
||||
ext = os.path.splitext(path)[1].lower()
|
||||
candidate = ext in ('.nzb', '.gz', '.bz2') or ext in VALID_ARCHIVES
|
||||
candidate = ext in VALID_NZB_FILES + VALID_ARCHIVES
|
||||
if candidate:
|
||||
try:
|
||||
stat_tuple = os.stat(path)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python -OO
|
||||
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2019 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -60,8 +60,8 @@ TIMER_LOCK = RLock()
|
||||
|
||||
class Server(object):
|
||||
|
||||
def __init__(self, id, displayname, host, port, timeout, threads, priority, ssl, ssl_verify, send_group, username=None,
|
||||
password=None, optional=False, retention=0):
|
||||
def __init__(self, id, displayname, host, port, timeout, threads, priority, ssl, ssl_verify, ssl_ciphers,
|
||||
send_group, username=None, password=None, optional=False, retention=0):
|
||||
|
||||
self.id = id
|
||||
self.newid = None
|
||||
@@ -74,6 +74,7 @@ class Server(object):
|
||||
self.priority = priority
|
||||
self.ssl = ssl
|
||||
self.ssl_verify = ssl_verify
|
||||
self.ssl_ciphers = ssl_ciphers
|
||||
self.optional = optional
|
||||
self.retention = retention
|
||||
self.send_group = send_group
|
||||
@@ -228,6 +229,7 @@ class Downloader(Thread):
|
||||
priority = srv.priority()
|
||||
ssl = srv.ssl()
|
||||
ssl_verify = srv.ssl_verify()
|
||||
ssl_ciphers = srv.ssl_ciphers()
|
||||
username = srv.username()
|
||||
password = srv.password()
|
||||
optional = srv.optional()
|
||||
@@ -247,7 +249,7 @@ class Downloader(Thread):
|
||||
|
||||
if create and enabled and host and port and threads:
|
||||
server = Server(newserver, displayname, host, port, timeout, threads, priority, ssl, ssl_verify,
|
||||
send_group, username, password, optional, retention)
|
||||
ssl_ciphers, send_group, username, password, optional, retention)
|
||||
self.servers.append(server)
|
||||
self.server_dict[newserver] = server
|
||||
|
||||
@@ -303,13 +305,13 @@ class Downloader(Thread):
|
||||
self.force_disconnect = True
|
||||
|
||||
def limit_speed(self, value):
|
||||
''' Set the actual download speed in Bytes/sec
|
||||
""" Set the actual download speed in Bytes/sec
|
||||
When 'value' ends with a '%' sign or is within 1-100, it is interpreted as a pecentage of the maximum bandwidth
|
||||
When no '%' is found, it is interpreted as an absolute speed (including KMGT notation).
|
||||
'''
|
||||
"""
|
||||
if value:
|
||||
mx = cfg.bandwidth_max.get_int()
|
||||
if '%' in str(value) or (from_units(value) > 0 and from_units(value) < 101):
|
||||
if '%' in str(value) or (0 < from_units(value) < 101):
|
||||
limit = value.strip(' %')
|
||||
self.bandwidth_perc = from_units(limit)
|
||||
if mx:
|
||||
@@ -364,14 +366,27 @@ class Downloader(Thread):
|
||||
return filter(nzo.server_in_try_list, self.servers)
|
||||
|
||||
def maybe_block_server(self, server):
|
||||
if server.optional and server.active and (server.bad_cons / server.threads) > 3:
|
||||
# Optional and active server had too many problems,
|
||||
# disable it now and send a re-enable plan to the scheduler
|
||||
# Was it resolving problem?
|
||||
if server.info is False:
|
||||
# Warn about resolving issues
|
||||
errormsg = T('Cannot connect to server %s [%s]') % (server.host, T('Server name does not resolve'))
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(errormsg)
|
||||
logging.warning(T('Server %s will be ignored for %s minutes'), server.host, _PENALTY_TIMEOUT)
|
||||
|
||||
# Not fully the same as the code below for optional servers
|
||||
server.bad_cons = 0
|
||||
server.active = False
|
||||
server.errormsg = T('Server %s will be ignored for %s minutes') % ('', _PENALTY_TIMEOUT)
|
||||
logging.warning(T('Server %s will be ignored for %s minutes'), server.id, _PENALTY_TIMEOUT)
|
||||
self.plan_server(server.id, _PENALTY_TIMEOUT)
|
||||
self.plan_server(server, _PENALTY_TIMEOUT)
|
||||
|
||||
# Optional and active server had too many problems.
|
||||
# Disable it now and send a re-enable plan to the scheduler
|
||||
if server.optional and server.active and (server.bad_cons / server.threads) > 3:
|
||||
server.bad_cons = 0
|
||||
server.active = False
|
||||
logging.warning(T('Server %s will be ignored for %s minutes'), server.host, _PENALTY_TIMEOUT)
|
||||
self.plan_server(server, _PENALTY_TIMEOUT)
|
||||
|
||||
# Remove all connections to server
|
||||
for nw in server.idle_threads + server.busy_threads:
|
||||
@@ -394,20 +409,8 @@ class Downloader(Thread):
|
||||
sabnzbd.EXTERNAL_IPV6 = sabnzbd.test_ipv6()
|
||||
logging.debug('External IPv6 test result: %s', sabnzbd.EXTERNAL_IPV6)
|
||||
|
||||
# Then have to check the quality of SSL verification
|
||||
if sabnzbd.HAVE_SSL_CONTEXT:
|
||||
try:
|
||||
import ssl
|
||||
ctx = ssl.create_default_context()
|
||||
base_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
ssl_sock = ctx.wrap_socket(base_sock, server_hostname=cfg.selftest_host())
|
||||
ssl_sock.settimeout(2.0)
|
||||
ssl_sock.connect((cfg.selftest_host(), 443))
|
||||
ssl_sock.close()
|
||||
except:
|
||||
# Seems something is still wrong
|
||||
sabnzbd.set_https_verification(0)
|
||||
sabnzbd.HAVE_SSL_CONTEXT = False
|
||||
# Then we check SSL certifcate checking
|
||||
sabnzbd.HAVE_SSL_CONTEXT = sabnzbd.test_cert_checking()
|
||||
logging.debug('SSL verification test: %s', sabnzbd.HAVE_SSL_CONTEXT)
|
||||
|
||||
# Start decoders
|
||||
@@ -455,9 +458,11 @@ class Downloader(Thread):
|
||||
else:
|
||||
nw.timeout = None
|
||||
|
||||
if server.info is None:
|
||||
self.maybe_block_server(server)
|
||||
request_server_info(server)
|
||||
if not server.info:
|
||||
# Only request info if there's stuff in the queue
|
||||
if not sabnzbd.nzbqueue.NzbQueue.do.is_empty():
|
||||
self.maybe_block_server(server)
|
||||
request_server_info(server)
|
||||
break
|
||||
|
||||
article = sabnzbd.nzbqueue.NzbQueue.do.get_article(server, self.servers)
|
||||
@@ -467,7 +472,7 @@ class Downloader(Thread):
|
||||
|
||||
if server.retention and article.nzf.nzo.avg_stamp < time.time() - server.retention:
|
||||
# Let's get rid of all the articles for this server at once
|
||||
logging.info('Job %s too old for %s, moving on', article.nzf.nzo.work_name, server.id)
|
||||
logging.info('Job %s too old for %s, moving on', article.nzf.nzo.work_name, server.host)
|
||||
while article:
|
||||
self.decode(article, None, None)
|
||||
article = article.nzf.nzo.get_article(server, self.servers)
|
||||
@@ -482,10 +487,10 @@ class Downloader(Thread):
|
||||
self.__request_article(nw)
|
||||
else:
|
||||
try:
|
||||
logging.info("%s@%s: Initiating connection", nw.thrdnum, server.id)
|
||||
logging.info("%s@%s: Initiating connection", nw.thrdnum, server.host)
|
||||
nw.init_connect(self.write_fds)
|
||||
except:
|
||||
logging.error(T('Failed to initialize %s@%s with reason: %s'), nw.thrdnum, server.id, sys.exc_info()[1])
|
||||
logging.error(T('Failed to initialize %s@%s with reason: %s'), nw.thrdnum, server.host, sys.exc_info()[1])
|
||||
self.__reset_nw(nw, "failed to initialize")
|
||||
|
||||
# Exit-point
|
||||
@@ -614,7 +619,7 @@ class Downloader(Thread):
|
||||
try:
|
||||
nw.finish_connect(nw.status_code)
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug("%s@%s last message -> %s", nw.thrdnum, nw.server.id, nntp_to_msg(nw.data))
|
||||
logging.debug("%s@%s last message -> %s", nw.thrdnum, nw.server.host, nntp_to_msg(nw.data))
|
||||
nw.clear_data()
|
||||
except NNTPPermanentError, error:
|
||||
# Handle login problems
|
||||
@@ -631,9 +636,9 @@ class Downloader(Thread):
|
||||
errormsg = T('Too many connections to server %s') % display_msg
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(T('Too many connections to server %s'), server.id)
|
||||
logging.warning(T('Too many connections to server %s'), server.host)
|
||||
self.__reset_nw(nw, None, warn=False, destroy=True, quit=True)
|
||||
self.plan_server(server.id, _PENALTY_TOOMANY)
|
||||
self.plan_server(server, _PENALTY_TOOMANY)
|
||||
server.threads -= 1
|
||||
elif ecode in ('502', '481', '482') and clues_too_many_ip(msg):
|
||||
# Account sharing?
|
||||
@@ -641,7 +646,7 @@ class Downloader(Thread):
|
||||
errormsg = T('Probable account sharing') + display_msg
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
name = ' (%s)' % server.id
|
||||
name = ' (%s)' % server.host
|
||||
logging.warning(T('Probable account sharing') + name)
|
||||
penalty = _PENALTY_SHARE
|
||||
block = True
|
||||
@@ -651,7 +656,7 @@ class Downloader(Thread):
|
||||
errormsg = T('Failed login for server %s') % display_msg
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.error(T('Failed login for server %s'), server.id)
|
||||
logging.error(T('Failed login for server %s'), server.host)
|
||||
penalty = _PENALTY_PERM
|
||||
block = True
|
||||
elif ecode in ('502', '482'):
|
||||
@@ -660,7 +665,7 @@ class Downloader(Thread):
|
||||
errormsg = T('Cannot connect to server %s [%s]') % ('', display_msg)
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(T('Cannot connect to server %s [%s]'), server.id, msg)
|
||||
logging.warning(T('Cannot connect to server %s [%s]'), server.host, msg)
|
||||
if clues_pay(msg):
|
||||
penalty = _PENALTY_PERM
|
||||
else:
|
||||
@@ -669,7 +674,7 @@ class Downloader(Thread):
|
||||
elif ecode == '400':
|
||||
# Temp connection problem?
|
||||
if server.active:
|
||||
logging.debug('Unspecified error 400 from server %s', server.id)
|
||||
logging.debug('Unspecified error 400 from server %s', server.host)
|
||||
penalty = _PENALTY_VERYSHORT
|
||||
block = True
|
||||
else:
|
||||
@@ -678,25 +683,25 @@ class Downloader(Thread):
|
||||
errormsg = T('Cannot connect to server %s [%s]') % ('', display_msg)
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(T('Cannot connect to server %s [%s]'), server.id, msg)
|
||||
logging.warning(T('Cannot connect to server %s [%s]'), server.host, msg)
|
||||
penalty = _PENALTY_UNKNOWN
|
||||
block = True
|
||||
if block or (penalty and server.optional):
|
||||
if server.active:
|
||||
server.active = False
|
||||
if penalty and (block or server.optional):
|
||||
self.plan_server(server.id, penalty)
|
||||
self.plan_server(server, penalty)
|
||||
sabnzbd.nzbqueue.NzbQueue.do.reset_all_try_lists()
|
||||
self.__reset_nw(nw, None, warn=False, quit=True)
|
||||
continue
|
||||
except:
|
||||
logging.error(T('Connecting %s@%s failed, message=%s'),
|
||||
nw.thrdnum, nw.server.id, nntp_to_msg(nw.data))
|
||||
nw.thrdnum, nw.server.host, nntp_to_msg(nw.data))
|
||||
# No reset-warning needed, above logging is sufficient
|
||||
self.__reset_nw(nw, None, warn=False)
|
||||
|
||||
if nw.connected:
|
||||
logging.info("Connecting %s@%s finished", nw.thrdnum, nw.server.id)
|
||||
logging.info("Connecting %s@%s finished", nw.thrdnum, nw.server.host)
|
||||
self.__request_article(nw)
|
||||
|
||||
elif nw.status_code == '223':
|
||||
@@ -713,27 +718,27 @@ class Downloader(Thread):
|
||||
elif nw.status_code in ('411', '423', '430'):
|
||||
done = True
|
||||
logging.debug('Thread %s@%s: Article %s missing (error=%s)',
|
||||
nw.thrdnum, nw.server.id, article.article, nw.status_code)
|
||||
nw.thrdnum, nw.server.host, article.article, nw.status_code)
|
||||
nw.clear_data()
|
||||
|
||||
elif nw.status_code == '480':
|
||||
if server.active:
|
||||
server.active = False
|
||||
server.errormsg = T('Server %s requires user/password') % ''
|
||||
self.plan_server(server.id, 0)
|
||||
self.plan_server(server, 0)
|
||||
sabnzbd.nzbqueue.NzbQueue.do.reset_all_try_lists()
|
||||
msg = T('Server %s requires user/password') % nw.server.id
|
||||
msg = T('Server %s requires user/password') % nw.server.host
|
||||
self.__reset_nw(nw, msg, quit=True)
|
||||
|
||||
elif nw.status_code == '500':
|
||||
if nzo.precheck:
|
||||
# Assume "STAT" command is not supported
|
||||
server.have_stat = False
|
||||
logging.debug('Server %s does not support STAT', server.id)
|
||||
logging.debug('Server %s does not support STAT', server.host)
|
||||
else:
|
||||
# Assume "BODY" command is not supported
|
||||
server.have_body = False
|
||||
logging.debug('Server %s does not support BODY', server.id)
|
||||
logging.debug('Server %s does not support BODY', server.host)
|
||||
nw.clear_data()
|
||||
self.__request_article(nw)
|
||||
|
||||
@@ -741,7 +746,7 @@ class Downloader(Thread):
|
||||
server.bad_cons = 0 # Succesful data, clear "bad" counter
|
||||
server.errormsg = server.warning = ''
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug('Thread %s@%s: %s done', nw.thrdnum, server.id, article.article)
|
||||
logging.debug('Thread %s@%s: %s done', nw.thrdnum, server.host, article.article)
|
||||
self.decode(article, nw.lines, nw.data)
|
||||
|
||||
nw.soft_reset()
|
||||
@@ -773,9 +778,9 @@ class Downloader(Thread):
|
||||
|
||||
if warn and errormsg:
|
||||
server.warning = errormsg
|
||||
logging.info('Thread %s@%s: ' + errormsg, nw.thrdnum, server.id)
|
||||
logging.info('Thread %s@%s: ' + errormsg, nw.thrdnum, server.host)
|
||||
elif errormsg:
|
||||
logging.info('Thread %s@%s: ' + errormsg, nw.thrdnum, server.id)
|
||||
logging.info('Thread %s@%s: ' + errormsg, nw.thrdnum, server.host)
|
||||
|
||||
if nw in server.busy_threads:
|
||||
server.busy_threads.remove(nw)
|
||||
@@ -809,11 +814,11 @@ class Downloader(Thread):
|
||||
if nw.server.send_group and nzo.group != nw.group:
|
||||
group = nzo.group
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug('Thread %s@%s: GROUP <%s>', nw.thrdnum, nw.server.id, group)
|
||||
logging.debug('Thread %s@%s: GROUP <%s>', nw.thrdnum, nw.server.host, group)
|
||||
nw.send_group(group)
|
||||
else:
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug('Thread %s@%s: BODY %s', nw.thrdnum, nw.server.id, nw.article.article)
|
||||
logging.debug('Thread %s@%s: BODY %s', nw.thrdnum, nw.server.host, nw.article.article)
|
||||
nw.body(nzo.precheck)
|
||||
|
||||
fileno = nw.nntp.sock.fileno()
|
||||
@@ -835,24 +840,24 @@ class Downloader(Thread):
|
||||
# Each server has a dictionary entry, consisting of a list of timestamps.
|
||||
|
||||
@synchronized(TIMER_LOCK)
|
||||
def plan_server(self, server_id, interval):
|
||||
def plan_server(self, server, interval):
|
||||
""" Plan the restart of a server in 'interval' minutes """
|
||||
if cfg.no_penalties() and interval > _PENALTY_SHORT:
|
||||
# Overwrite in case of no_penalties
|
||||
interval = _PENALTY_SHORT
|
||||
|
||||
logging.debug('Set planned server resume %s in %s mins', server_id, interval)
|
||||
if server_id not in self._timers:
|
||||
self._timers[server_id] = []
|
||||
logging.debug('Set planned server resume %s in %s mins', server.host, interval)
|
||||
if server.id not in self._timers:
|
||||
self._timers[server.id] = []
|
||||
stamp = time.time() + 60.0 * interval
|
||||
self._timers[server_id].append(stamp)
|
||||
self._timers[server.id].append(stamp)
|
||||
if interval:
|
||||
sabnzbd.scheduler.plan_server(self.trigger_server, [server_id, stamp], interval)
|
||||
sabnzbd.scheduler.plan_server(self.trigger_server, [server.id, stamp], interval)
|
||||
|
||||
@synchronized(TIMER_LOCK)
|
||||
def trigger_server(self, server_id, timestamp):
|
||||
""" Called by scheduler, start server if timer still valid """
|
||||
logging.debug('Trigger planned server resume %s', server_id)
|
||||
logging.debug('Trigger planned server resume for server-id %s', server_id)
|
||||
if server_id in self._timers:
|
||||
if timestamp in self._timers[server_id]:
|
||||
del self._timers[server_id]
|
||||
@@ -869,7 +874,7 @@ class Downloader(Thread):
|
||||
# Activate server if it was inactive
|
||||
for server in self.servers:
|
||||
if server.id == server_id and not server.active:
|
||||
logging.debug('Unblock server %s', server_id)
|
||||
logging.debug('Unblock server %s', server.host)
|
||||
self.init_server(server_id, server_id)
|
||||
break
|
||||
|
||||
@@ -886,7 +891,7 @@ class Downloader(Thread):
|
||||
kicked = []
|
||||
for server_id in self._timers.keys():
|
||||
if not [stamp for stamp in self._timers[server_id] if stamp >= now]:
|
||||
logging.debug('Forcing re-evaluation of server %s', server_id)
|
||||
logging.debug('Forcing re-evaluation of server-id %s', server_id)
|
||||
del self._timers[server_id]
|
||||
self.init_server(server_id, server_id)
|
||||
kicked.append(server_id)
|
||||
@@ -894,11 +899,14 @@ class Downloader(Thread):
|
||||
for server in self.servers:
|
||||
if server.id not in self._timers:
|
||||
if server.id not in kicked and not server.active:
|
||||
logging.debug('Forcing activation of server %s', server.id)
|
||||
logging.debug('Forcing activation of server %s', server.host)
|
||||
self.init_server(server.id, server.id)
|
||||
|
||||
def update_server(self, oldserver, newserver):
|
||||
""" Update the server and make sure we trigger
|
||||
the update in the loop to do housekeeping """
|
||||
self.init_server(oldserver, newserver)
|
||||
self.wakeup()
|
||||
|
||||
@NzbQueueLocker
|
||||
def wakeup(self):
|
||||
@@ -937,7 +945,7 @@ def clues_too_many(text):
|
||||
text = text.lower()
|
||||
for clue in ('exceed', 'connections', 'too many', 'threads', 'limit'):
|
||||
# Not 'download limit exceeded' error
|
||||
if (clue in text) and ('download' not in text):
|
||||
if (clue in text) and ('download' not in text) and ('byte' not in text):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user