Compare commits

...

173 Commits

Author SHA1 Message Date
Safihre
ca66eb04ad Note restoring of OSX 10.11.6 compatibility for 2.3.2RC1
Closes #1075
2017-11-26 11:07:24 +01:00
Safihre
91a2532c95 Show warning in wizard when language files are not present
Closes #1074
2017-11-25 10:51:31 +01:00
SABnzbd Automation
cb49f7bb53 Automatic translation update 2017-11-23 17:12:04 +00:00
Safihre
0049f14d7f Update text files for 2.3.2RC1 2017-11-23 17:31:22 +01:00
Safihre
e414874910 Only report missing UnZip when missing 7Zip 2017-11-23 13:39:04 +01:00
Safihre
5931beaa5c Quote all arguments to external processes on Windows 2017-11-23 13:36:47 +01:00
Safihre
b3d80b7c65 Remove unzip from Windows distribution 2017-11-20 20:24:01 +01:00
shypike
9aa90083b2 When available, use 7zip instead of built-in unzip.
7zip supports passwords, many old platform unzips do not.
2017-11-20 20:24:01 +01:00
Safihre
0b939a9519 Notification category Default only means "all categories" if non other 2017-11-20 20:08:32 +01:00
Safihre
501867137a Reset also article try-list on dropped server connections
Test release for these users showed that "server dropped connection" also needed a reset of the article trylist.
Linked:
https://forums.sabnzbd.org/viewtopic.php?f=2&t=23111
https://forums.sabnzbd.org/viewtopic.php?f=2&t=23109
2017-11-20 12:06:56 +01:00
Safihre
75d4b5deca Add tooltip to server graph month selector 2017-11-19 15:02:17 +01:00
Safihre
442591f20c Link server graphs (month and scale) and show monthly total
Closes #1028
2017-11-19 14:58:43 +01:00
Safihre
74b7f383db Always show 1 decimal for MB and above
So it is similar to the JS filesize function
2017-11-19 14:55:46 +01:00
Safihre
b966707247 Implement fast and slow queue in postprocessor
So I implemented this in a kind of cheeky easy way: 
There is a fast and a slow queue in the `PostProcessor`, if we see it has completed Direct Unpack or if it is still active (might be unpacking that last volume) it is put in the fast queue.
We always check the fast queue first, then the slow one. To not have slow jobs be stuck in the post-proc queue forever, every 3 fast jobs we force a slow job (if present).
Closes #1014
2017-11-18 19:00:52 +01:00
Safihre
eada7286d1 Small optimization in registering of article for first articles 2017-11-18 16:31:47 +01:00
Safihre
b9c312961b listdir can fail on Windows for C: instead of C:\ and crashing postproc 2017-11-18 09:55:56 +01:00
Safihre
8389b4fedb Re-evaluate filenames after first par2 file is finished
Just in case it came in after all first articles were downloaded.
2017-11-18 00:57:15 +01:00
Safihre
7720cd60ec Decode first articles of each file first to find filenames
Get first article of each file first, so that we can use the par2 information to get the filename. This way on obfuscated posts we can faster start Direct Unpack.
In a bit convoluted way so that we can also stay performance tuned.
Closes #1044
2017-11-18 00:45:40 +01:00
Safihre
d1d437074a Do not flush article cache to disk on pause
Overly cautious
2017-11-18 00:13:50 +01:00
Safihre
30d3d62e09 Correct MultiPar Extra Par2 Option passing 2017-11-17 22:29:15 +01:00
Safihre
fd1975617b Simplify and comment code on par2 errors
Closes #1070 (read for details)
2017-11-17 22:24:55 +01:00
SABnzbd Automation
1d037dcb62 Automatic translation update 2017-11-16 22:12:35 +00:00
Safihre
bd5fb3e88f Remove unused crash_msg postproc code 2017-11-16 22:21:39 +01:00
Safihre
5ca66bfeef Only require SABYenc to match minor version and bump to 3.3.2 2017-11-16 20:27:32 +01:00
Safihre
c9fbadd097 Improve progressbar on new Firefox 2017-11-15 15:33:44 +02:00
Safihre
f4568ad7dd Do not warn about disk-errors when job is deleted/done
Only happens in really fast situations with many server connections for small downloads completed within 1 or 2 seconds.
2017-11-15 13:02:01 +02:00
Safihre
74a395f584 Increase wait-time in URLGrabber and stop after 10 tries
Closes #1069
2017-11-13 18:10:18 +02:00
Safihre
dd703ace7f Fully parse output of Pre-Q script correctly
PP/Priority are different, since 0 is also a valid value for these settings.
2017-11-12 14:19:10 +02:00
Safihre
ddc8396260 Empty values in Pre-Q script should not just be ignored 2017-11-12 13:07:41 +02:00
Safihre
e6724e347c Do not 'fix' sending of priority and pp-setting, removes the 0 setting
Priority Normal and PP-setting Download have a value of 0, so they were not send to the pre-Q script.
2017-11-11 17:26:14 +02:00
Safihre
7fa0508ae8 Show tooltip to explain 'Show Logging' anonymized the data 2017-11-11 17:03:53 +02:00
Safihre
06c6f7d38e Auto-history-purge on start-up
Closes #1065
2017-11-11 16:46:11 +02:00
Safihre
59ef400fec Log history-status of failure during repair
For easier debugging
2017-11-11 16:40:04 +02:00
Safihre
0acdf15755 Always show user-entered password in History-info
People like to have this info, some users want to only unpack later etc.
2017-11-11 16:31:38 +02:00
SABnzbd Automation
40128f59dd Automatic translation update 2017-11-07 13:33:01 +00:00
Safihre
286914f253 Correctly report when repair is performed, but fails
Strange, but it can happen. There has been an uptick in this kind of failing downloads. Seems to be a problem with the original par2-files, but not sure yet what it is.
 https://forums.sabnzbd.org/viewtopic.php?f=2&t=23048&p=114059
2017-11-06 13:02:23 +01:00
Fish2
f9bd58bb74 lossless compression of images 2017-11-04 11:47:21 +01:00
Safihre
30cfb9c6fc Prevent potential pause/unpause loop after tray click 2017-10-27 23:39:01 +02:00
Safihre
f1695ec875 Set Windows tray double click timeout to user double-click timeout 2017-10-26 20:30:49 +02:00
Safihre
a3db910a4d Update text files for 2.3.1 Final 2017-10-26 20:15:21 +02:00
Safihre
80a29c50c9 In the binaries (macOS/Windows) getmodule does not work
Because the files are compiled, they loose this info it seems.
2017-10-26 14:23:58 +02:00
SABnzbd Automation
d693e20e1a Automatic translation update 2017-10-26 11:23:00 +00:00
SABnzbd Automation
1a36f548df Automatic translation update 2017-10-25 23:23:37 +00:00
Safihre
a6f6d88ab9 Move get_from_url to sabnzbd.misc 2017-10-25 23:00:32 +02:00
Safihre
aa7fb17b4e Reduce standard timeout of new servers to 60 seconds
In line with other usenet software.
2017-10-25 22:08:14 +02:00
Safihre
a99d333272 Fix racing-condition for files coming in after post-proc is started
Files could still come in after post-proc is already started. Post-proc could even have already deleted the job folder, resulting in Assembler errors for these new files. So when post-proc is active, it is safe to ignore write-errors.
Linked topic: https://forums.sabnzbd.org/viewtopic.php?f=3&t=23049
2017-10-25 11:21:59 +02:00
Safihre
801aadecfc Add logging to stop_idle_jobs 2017-10-24 10:46:18 +02:00
Safihre
124e2b253c Do not crash when unrar gets stopped or killed in Direct Unpacker 2017-10-24 10:32:17 +02:00
Safihre
39cceed580 NZF completed is a property method, not an attribute 2017-10-24 10:07:45 +02:00
Safihre
bfcf56ec45 Log traceback on assembler disk error 2017-10-23 21:58:24 +02:00
Safihre
01603b24f5 Do not log decoding of articles by default to reduce logging density
The Debug logs were getting way too confusing with all the "Decoding X" in there, when 99% of the time it is of no importance.
2017-10-23 20:42:17 +02:00
Safihre
d93d2591b7 Do not pause after sending notifications 2017-10-23 11:33:11 +02:00
Safihre
c17fcec499 Correctly handle single and double clicks on Windows tray-icon
On Windows, double click is actually 1 single click followed by a double-click event, no way to differentiate that first click-event of a double-click from an actual just single-click. So we need a timed callback to cancel when we do get the double-click event. Luckily the win32api provides this function.
2017-10-23 11:11:39 +02:00
Safihre
6804ac20da Remove unused is_utf8 function 2017-10-23 11:09:55 +02:00
Safihre
4ed7ac3dea Do not crash when directory creation fails in Direct Unpack 2017-10-22 13:23:57 +02:00
Safihre
eae8056366 Remove old par2cmdline/par2tbb options for MultiPar 2017-10-22 12:58:07 +02:00
Safihre
df4680b6d0 Simply function-caller detection for performance
Much much faster.
#1059
2017-10-22 11:46:41 +02:00
Safihre
b8f5861044 Add new translatable text 2017-10-22 11:24:46 +02:00
Safihre
8e01ceca7a Show current output of running script in History
For long-running scripts.
2017-10-21 14:31:22 +02:00
Safihre
0e1cdec78f Log actual filename and ID of new files 2017-10-21 14:07:06 +02:00
Safihre
13e5e93953 Tweak display of Direct Unpack and Fetching jobs 2017-10-20 21:56:26 +02:00
Safihre
02d08f38eb Correct handeling of jobs fetching extra blocks
Always need to set status to Fetching when getting more blocks and not show the priority selector in Glitter to prevent it from updating the priority. 
@OneCDOnly
2017-10-20 21:03:58 +02:00
Safihre
770951bfe6 Update text files for 2.3.1RC2 2017-10-20 10:59:21 +02:00
Safihre
022898bf63 ENV fields of 0 should be listed as 0 and not empty
So first convert to string, then de-unicode.
2017-10-20 10:58:48 +02:00
Safihre
4fd2d8505b Reset last_volume_linebuf for multi-sets in Direct Unpacker
And log in case of duplicate lines in Unrar output
2017-10-19 22:32:11 +02:00
Safihre
cc72bb743a Use C for [C]ontinue in Direct Unpack 2017-10-19 17:24:06 +02:00
Safihre
d7869fc3a1 Make Direct Unpack icon always visible
Add also the info to the hover, to somehow still explain the icon. Having this info always visible is more important than being able to hover over it directly.
Closes #1013
2017-10-19 15:07:47 +02:00
Sander Jo
4fbf870028 Example Post-Processing Script, written in Python. 2017-10-16 10:21:08 +02:00
Safihre
306558b52f Tracing of function caller only on Debug level logging
And add caller-name to NzbQueue-remove
2017-10-15 16:26:04 +02:00
Safihre
db19875f5d Add caller name to more logging 2017-10-15 10:46:44 +02:00
Safihre
f8061dc9c8 Log caller of history delete and pickle loading/saving
#1054
2017-10-15 10:30:38 +02:00
Safihre
c73591eb20 Allow up to 4GB Article Cache on 64bit systems 2017-10-15 09:58:51 +02:00
Safihre
ec132374a6 Resolve locking situation by only using 1 lock 2017-10-14 15:06:45 +02:00
Safihre
262964c6c2 Add path to gzipped NZB to script environment variables 2017-10-14 10:42:15 +02:00
OneCDOnly
cdaad3ed90 Correct spelling of 'separate' in a few contexts 2017-10-14 09:51:25 +02:00
SABnzbd Automation
84f54f5c57 Automatic translation update 2017-10-13 14:36:36 +00:00
Safihre
00436dfb2c Update text files for 2.3.1RC1 2017-10-13 16:07:21 +02:00
Safihre
c3ce87bd10 TRANS/UNTRANS fails when input is None 2017-10-13 14:03:55 +02:00
Safihre
c3a48a61b6 Correctly fix deadlock of NZBQUEUE_LOCK and DOWNLOADER_CV 2017-10-13 14:03:49 +02:00
Safihre
0c03476d76 Always send failure_url, like we say in the documentation 2017-10-12 16:23:26 +02:00
Safihre
6148cd5445 NZBQUEUE_LOCK in DirScanner causes lock-up when changing prio during add 2017-10-12 15:39:44 +02:00
Safihre
7f72e2042c Add 'Accept' to 'From Show SxxEyy' 2017-10-12 15:28:06 +02:00
Safihre
638b29819c 'From Show SxxEyy' is an Accept filter
Oops.........
2017-10-11 22:23:25 +02:00
Safihre
b950820099 Testing notification email and limiting to certain categories was broken 2017-10-11 13:27:01 +02:00
Safihre
96adf76ef1 Show NZF-ID in warning to find where files got deleted
Linked: #1034 and #952
2017-10-11 11:59:53 +02:00
Safihre
556a4db186 Log all file and folder removal
Linked: #1034 and #973
2017-10-11 11:55:53 +02:00
Safihre
b9fbd19064 Prevent downloader crash when performing slowdown check 2017-10-11 10:13:30 +02:00
Safihre
167e7f2870 Do not warn too much when renames can't be saved
Probably happens after the sucessfull finishing of the job anyway.
2017-10-10 16:25:19 +02:00
Safihre
4dba5b8caa Make sure that Category folders are not a sub-folder of Incomplete
We only check during adding or updating of categories, but that's already better than before.
Example: #1047
2017-10-09 23:11:11 +02:00
SABnzbd Automation
831b64daa8 Automatic translation update 2017-10-09 21:04:38 +00:00
Safihre
38fd5cde29 Unicode needs to be de-unicoded on all platforms 2017-10-09 22:34:47 +02:00
Safihre
e39456cca1 Filter out any unicode in ENV variables 2017-10-09 22:21:19 +02:00
andofrjando
8e9425855b Much nicer icon and colour 2017-10-08 11:39:37 +02:00
andofrjando
89add6edac New feature: Safari pinned tab icon 2017-10-08 11:39:37 +02:00
SABnzbd Automation
16b85429ae Automatic translation update 2017-10-06 09:14:40 +00:00
Safihre
2482c8e70a Update text files for 2.3.1Beta1 2017-10-06 10:58:23 +02:00
Safihre
ad2bb6c3a7 Also remove trailing .par2 from final folder
Otherwise Deobfuscate.py fails due to bug in par2cmdline that can't handle folders with "par2" in it.
2017-10-06 10:32:53 +02:00
SABnzbd Automation
2c7e725e39 Automatic translation update 2017-10-05 13:29:56 +00:00
Safihre
123f05f164 Use internal list2cmdline to correct path escaping on Windows
More info: #1043
Closes #1043
2017-10-05 14:46:13 +02:00
Safihre
4ade2e0c60 Special Windows-names can break RarFile 2017-10-05 14:29:04 +02:00
Safihre
c908a396df Correct the Deobfuscate script 2017-10-04 19:51:28 +02:00
Safihre
15f2370bca Leave undefined ENV variables empty 2017-10-04 19:51:04 +02:00
Safihre
a5e208eb11 Abort Direct Unpack if stuck for more than 2 minutes
Safety measure
2017-10-04 15:21:22 +02:00
Safihre
d59b3b3679 Also parse extracted files during DirectUnpack 2017-10-04 15:21:22 +02:00
Safihre
476542463a Start-up check for subprocessww 2017-10-04 15:21:21 +02:00
Safihre
52267a9565 Use special patched version of subprocess for Unicode POpen on Windows 2017-10-03 14:31:49 +02:00
SABnzbd Automation
972e708810 Automatic translation update 2017-10-02 20:48:06 +00:00
walgarch
a636f7f18e Added 'with' to list of lowercase words in titles 2017-10-02 14:02:47 +02:00
Safihre
9d5b3e9621 When re-adding set status to Downloading so time left is calculated
@OneCDOnly
2017-09-30 22:54:20 +02:00
SABnzbd Automation
9e2d8e5e55 Automatic translation update 2017-09-30 19:32:39 +00:00
Safihre
d9899cc5cd Increase delay to 2 seconds between sub-processes on Windows
1 was not enough, or something else is wrong
2017-09-30 21:18:44 +02:00
Safihre
650e83e1b8 Datetimes in history/warnings were displayed in UTC and not local time 2017-09-30 17:55:22 +02:00
Safihre
4296e1628b Add NZBQUEUE_LOCK to importing of NZBs
So that nothing can happen between uploading/adding and when they are actually in the Queue. Before this it would show the job as "orphaned" while it was being added.
2017-09-28 17:17:16 +02:00
Safihre
5dddc7ab61 Re-introduce NZBQUEUE_LOCK
There seems to be no performance impact.

Linked #1034 and #952 

Reverts partially 02ebb97a8b
2017-09-28 16:52:31 +02:00
Safihre
529ba69584 Do not save to disk when pausing due to import error
Linked #1034
2017-09-28 16:22:49 +02:00
Safihre
9f35568a24 UnRar prints path including folder, even when set to flat-unpack 2017-09-28 11:13:23 +02:00
Safihre
fe40d49c26 Update server-info on every update
https://forums.sabnzbd.org/viewtopic.php?f=3&t=23003
@OneCDOnly
2017-09-28 10:25:14 +02:00
Safihre
6c0b32004a Update RecursivePar2 to be more general deobfuscation
On top of scanning for the "rename.par2", it will also rename the largest file to the job-name. But only if there's 1 large file, otherwise it could get messy. If they want more, they can do it themselves or submit a PR.
2017-09-27 14:32:12 +02:00
Safihre
bda4e102d6 Correctly display Force priority icon in Glitter Night 2017-09-27 10:27:14 +02:00
Safihre
5e03204dbc The From SxxEyy filters need integers, not strings 2017-09-26 11:53:08 +02:00
Safihre
b5deda4195 Revert "Improve display of quota"
This reverts commit 5076892d83.
2017-09-25 21:57:42 +02:00
Safihre
5076892d83 Improve display of quota 2017-09-25 21:17:17 +02:00
Safihre
6c3a3e1694 Update translatable texts 2017-09-25 21:02:32 +02:00
Safihre
edbbcec272 Remove unused imports 2017-09-24 17:45:08 +02:00
Safihre
aced381763 Add example script for users that will handle "rename.par2" after unpack 2017-09-24 11:46:43 +02:00
Safihre
cdd3f9cc8a Add also program information to PostProcessing-ENV vars 2017-09-24 11:46:33 +02:00
Safihre
a2074f06d5 Only run Pre-Queue script section when it is set 2017-09-24 11:02:06 +02:00
Safihre
39aa3a9c51 Fix the priority assigment when uploading file
Thanks @OneCDOnly

https://forums.sabnzbd.org/viewtopic.php?f=3&p=113482#p113482
2017-09-24 11:02:00 +02:00
Safihre
c6cf3cc45d Left-click on Windows-tray now toggles Pause/Resume (did nothing before) 2017-09-22 13:50:41 +02:00
Safihre
0378f6f8b1 Show pop-up on Windows for some start failures like port occupied 2017-09-22 10:50:01 +02:00
Safihre
d6b48803a6 Priority of category was ignored when adding NZB 2017-09-22 09:42:37 +02:00
Safihre
6da23930bf Let browsers do part of the input validation 2017-09-22 09:19:11 +02:00
Safihre
d4e1464cc0 Server priority is maxium 99, not 100
Otherwise the sorting and selecting does not work.
https://forums.sabnzbd.org/viewtopic.php?f=3&p=113467
2017-09-22 09:10:12 +02:00
Safihre
e8dc3ebd51 Bump version to 2.4.0 2017-09-22 09:05:30 +02:00
onno.vos.dev
4009d855c3 Ensure that Pushover works for Emergency prio as well 2017-09-21 21:12:57 +02:00
Safihre
ba7d906bea Update text files for 2.3.0 2017-09-20 23:16:26 +02:00
Safihre
68f78b0e71 Subprocess on Windows needs at least 1 second timeout globally 2017-09-20 11:50:41 +02:00
Safihre
d5cd0180d8 Update SABYenc to 3.3.1 2017-09-19 17:23:29 +02:00
Safihre
10265bdfb4 Always use save-routine in database.execute so we can catch locked DB
Linked #1034
2017-09-19 09:18:22 +02:00
Safihre
3d0d67bffc Update SABYenc to 3.3.0
Faster!
2017-09-19 08:31:31 +02:00
Safihre
11bd16a653 Accidentally removed HTML-cleaning from error display
Linked #1034
2017-09-19 06:44:29 +02:00
Safihre
248f2da8a6 Pause job in case of failing imports
Linked #1034
2017-09-19 06:19:06 +02:00
Safihre
7b7aaaf467 Widen Confg Servers month selector
Closes #1032
2017-09-16 10:15:20 +02:00
SABnzbd Automation
0030e4dd36 Automatic translation update 2017-09-15 13:51:26 +00:00
Safihre
c3013d67b4 Show NZB name from RSS-feed when fetching
Of course not the name of the RSS-feed itself.
2017-09-15 14:21:45 +02:00
Safihre
ddb7f2a40c Require SABYenc 3.1.1 due to PyPi mixup
Broken source-distribution resulted in heaving to create new release, PyPi does not allow to re-upload files.
2017-09-15 12:59:24 +02:00
Safihre
167a94736e Update text files for 2.3.0RC2 2017-09-15 09:41:12 +02:00
Safihre
8b3e30f0a1 Require SABYenc 3.1.0 and no longer list CRC values
Since SABYenc 3.1.0 doesn't calculate them anymore for speed improvements.
2017-09-15 09:36:24 +02:00
Safihre
c383fa88fb Update ISSUES to match the website and list Synology being special 2017-09-13 20:51:07 +02:00
Safihre
ee72c1e4d5 Correct the testing-releases feedback slider 2017-09-11 22:13:06 +02:00
Safihre
a80bd826d6 Use the NZO password to save in database
build_history_info is called on every interface update to pretend the post-processing job is a history-job. So a password file (if set) would be loaded every second. Thanks @sanderjo!
2017-09-11 20:43:27 +02:00
Safihre
63e6d45bb1 Make sure users are warned that their settings could be unsafe 2017-09-10 21:45:19 +02:00
SABnzbd Automation
61300db1fb Automatic translation update 2017-09-10 18:24:12 +00:00
Safihre
23d005fc36 Update texts and links for 2.3.0 release to come 2017-09-10 20:01:45 +02:00
Safihre
871b351656 Set could potentially be missing from extrapars
Some bad handeling of newsunpack possibly
2017-09-10 19:29:58 +02:00
Safihre
6b53b9934e Waiting for URL would result in 100% CPU usage due to constant looping 2017-09-10 12:45:30 +02:00
Safihre
e038e08a60 Revert "Permanent notice in Plush to upgrade to Glitter"
6fdeab6948
2017-09-09 23:51:23 +02:00
Safihre
8300cb7762 Correct command-line help 2017-09-09 17:31:00 +02:00
Safihre
ec8302717f Warnings API-call now returns a dict like it should 2017-09-09 16:27:55 +02:00
Safihre
6b872b44db MultiPar can report both "PAR File(s) Incomplete" and "Need more blocks" 2017-09-09 16:20:35 +02:00
Safihre
6e48ebccc7 Correctly display time if server and brower are not in same timezone
#989
2017-09-09 13:16:11 +02:00
Safihre
1cd24d1fd0 Locking when iterating over extrapars for queue-stats
But only when we request all the files.
Closes #1029
2017-09-09 10:45:39 +02:00
Safihre
fa6bb79f53 Fix Chrome 61 table border change 2017-09-08 14:51:43 +02:00
Safihre
22e9086e09 Add AppVeyor for Windows testing
#999
2017-09-08 12:07:28 +02:00
Safihre
408b84e02d Basic NZB adding via upload or from disk 2017-09-08 10:28:01 +02:00
Safihre
16ac4dce21 Use requests module for testing 2017-09-08 10:28:01 +02:00
Safihre
5ce1554a46 Hide/Show Details in Config > Servers 2017-09-08 10:27:46 +02:00
Safihre
2d84ed6813 Always have something in RSS jobs storage 2017-09-07 00:26:59 +02:00
Safihre
06dc5b181e Do not leave rss.jobs empty to prevent crash later on
See: https://forums.sabnzbd.org/viewtopic.php?f=11&t=22952
2017-09-06 20:54:21 +02:00
Safihre
37b759fece Only notify upon testing failures 2017-09-06 20:50:27 +02:00
Safihre
3f8430780d Add test requirements 2017-09-06 20:44:47 +02:00
Safihre
9e9bc5f3b0 Very basic testing
Does it start, does it serve pages, does it serve api-requests
2017-09-06 20:44:47 +02:00
Safihre
85204105c2 Check input when setting priority of job
There was no input validation, via the API you could set any value.
2017-09-06 20:25:08 +02:00
112 changed files with 3400 additions and 2553 deletions

7
.gitignore vendored
View File

@@ -19,6 +19,10 @@ SABnzbd*.dmg
# WingIDE project files
*.wp[ru]
# Testing folders
.cache
.xprocess
# General junk
*.keep
*.bak
@@ -27,3 +31,6 @@ SABnzbd*.dmg
# Some people use Emacs as an editor
\#*
.\#*
.DS_Store
/venv

15
.travis.yml Normal file
View File

@@ -0,0 +1,15 @@
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
install:
- pip install --upgrade -r tests/requirements.txt
script:
- pytest
notifications:
email:
on_success: never
on_failure: always

View File

@@ -1,5 +1,5 @@
*******************************************
*** This is SABnzbd 2.2.0 ***
*** This is SABnzbd 2.4.0 ***
*******************************************
SABnzbd is an open-source cross-platform binary newsreader.
It simplifies the process of downloading from Usenet dramatically,

View File

@@ -1,4 +1,4 @@
SABnzbd 2.3.0
SABnzbd 2.3.1
-------------------------------------------------------------------------------
0) LICENSE
@@ -60,6 +60,7 @@ All platforms
Windows
PyWin32 use "pip install pypiwin32"
subprocessww use "pip install subprocessww"
Essential modules
cheetah-2.0.1+ use "pip install cheetah"
@@ -71,7 +72,7 @@ Essential modules
Optional modules
unzip >= 6.00 http://www.info-zip.org/
7zip >= 9.20 http://www.7zip.org/
sabyenc == 3.0.2 use "pip install sabyenc"
sabyenc == 3.3.1 use "pip install sabyenc"
More information: https://sabnzbd.org/sabyenc
cryptography >= 1.0 use "pip install cryptography"
Enables certificate generation and detection of encrypted RAR-files
@@ -92,12 +93,11 @@ Start this from a shell terminal (or command prompt):
python tools/make_mo.py
Start this from a shell terminal (or command prompt):
python SABnzbd.py
python -OO SABnzbd.py
Within a few seconds your web browser will start and show the user interface.
Use the "Help" button in the web-interface to be directed to the Help Wiki.
-------------------------------------------------------------------------------
5) TROUBLESHOOTING
-------------------------------------------------------------------------------
@@ -123,7 +123,6 @@ may help you solve problems easier.
Visit our wiki:
https://sabnzbd.org/wiki/
-------------------------------------------------------------------------------
7) CREDITS
-------------------------------------------------------------------------------

View File

@@ -9,28 +9,18 @@
- When par2 or unrar hang up, never just stop SABnzbd.
Instead use your operating system's task manager to stop the par2 or unrar program.
Forcing SABnzbd to quit may damage your queues.
Windows-only:
If you keep having trouble with par2 multicore you can disable it
in Config->Switches.
This will force the use of the old and tried, but slower par2cmdline program.
- A bug in Windows 7 may cause severe memory leaks when you use SABnzbd in
combination with some virus scanners and firewalls.
Install this hotfix:
Description: http://support.microsoft.com/kb/979223/en-us
Download location: http://support.microsoft.com/hotfix/KBHotfix.aspx?kbnum=979223&kbln=en-us
- Some Usenet servers have intermittent login (or other) problems.
For these the server blocking method is not very favourable.
There is an INI-only option that will limit blocks to 1 minute.
no_penalties = 1
See: https://sabnzbd.org/wiki/configuration/2.2/special
See: https://sabnzbd.org/wiki/configuration/2.3/special
- Some third-party utilties try to probe SABnzbd API in such a way that you will
often see warnings about unauthenticated access.
If you are sure these probes are harmless, you can suppress the warnings by
setting the option "api_warnings" to 0.
See: https://sabnzbd.org/wiki/configuration/2.2/special
See: https://sabnzbd.org/wiki/configuration/2.3/special
- On OSX you may encounter downloaded files with foreign characters.
The par2 repair may fail when the files were created on a Windows system.
@@ -41,7 +31,7 @@
You will see this only when downloaded files contain accented characters.
You need to fix it yourself by running the convmv utility (available for most Linux platforms).
Possible the file system override setting 'fsys_type' might be solve things:
See: https://sabnzbd.org/wiki/configuration/2.2/special
See: https://sabnzbd.org/wiki/configuration/2.3/special
- The "Watched Folder" sometimes fails to delete the NZB files it has
processed. This happens when other software still accesses these files.
@@ -51,6 +41,10 @@
- Memory usage can sometimes have high peaks. This makes using SABnzbd on very low
memory systems (e.g. a NAS device or a router) a challenge.
In particular on Synology (SynoCommunity) the device may report that SABnzbd is using
a lot of memory even when idle. In this case the memory is usually not actually used by
SABnzbd and will be available if required by other apps or the system. More information
can be found in the discussion here: https://github.com/SynoCommunity/spksrc/issues/2856
- SABnzbd is not compatible with some software firewall versions.
The Microsoft Windows Firewall works fine, but remember to tell this
@@ -72,13 +66,3 @@
Config->Special->wait_for_dfolder to 1.
SABnzbd will appear to hang until the drive is mounted.
- On some operating systems it looks like there is a problem with one of the standard Python libraries.
It is possible that you get errors about saving admin files and even unexplained crashes.
If so, you can enable the option for the alternative library.
It has the same functionality, but is slower.
We've had reports about this issue on non-mainstream Linux platforms.
- OpenElec
- Squeeze Linux
There is a "special" option that will allow you to select an alternative library.
use_pickle = 1
See: https://sabnzbd.org/wiki/configuration/2.2/special

View File

@@ -1,7 +1,7 @@
Metadata-Version: 1.0
Name: SABnzbd
Version: 2.3.0Alpha2
Summary: SABnzbd-2.3.0Alpha1
Version: 2.3.2RC1
Summary: SABnzbd-2.3.2RC1
Home-page: https://sabnzbd.org
Author: The SABnzbd Team
Author-email: team@sabnzbd.org

View File

@@ -13,7 +13,6 @@ SABnzbd has a good deal of dependencies you'll need before you can get running.
- `python` (only 2.7.x and higher, but not 3.x.x)
- `python-cheetah`
- `python-support`
- `par2` (Multi-threaded par2 installation guide can be found [here](https://sabnzbd.org/wiki/installation/multicore-par2))
- `unrar` (Make sure you get the "official" non-free version of unrar)
- `sabyenc` (installation guide can be found [here](https://sabnzbd.org/sabyenc))

View File

@@ -1,53 +1,36 @@
Release Notes - SABnzbd 2.3.0 Alpha 2
Release Notes - SABnzbd 2.3.2 RC 1
=========================================================
## Changes and bugfixes since 2.3.0 Alpha 1
- Specials Config page could not be loaded
- Crash when adding new jobs
- Further stalling-detection improvements
- Crash when a job was set to only Download
- Display of download progress and missing data improved
- Retried jobs would show incorrect download progress
- Different icon for downloads with Force priority
- Show progress during verification of extra files
- API: 'missing' field removed, use 'mbmissing'
## 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
## Changes since 2.2.1
- Option to limit Servers to specific Categories removed
- Improved par2 handling and obfuscated files detection
- Duplicate filenames in NZB's no longer rejected by default
- Set custom URL instead of /sabnzbd/ (in Config > Specials)
- Article-state (which servers are tried) is preserved after restart
- Auto disconnect (if enabled) only after verification of last item
- Slight performance improvement when fetching RSS-feeds
- RSS-feed title is shown for URLs being grabbed
- URL grabbing can now be individually paused
- Scheduler can pause/unpause jobs in specific category
- Series Duplicate Checker can allow PROPER/REAL/REPACK versions
- Refresh-icon in Glitter when refresh rate is above 2 seconds
- macOS: Bundled new OpenSSL version with support for TLSv1.2
- macOS: No longer linked to system certificate store
- macOS and Windows: Installers include Mozilla CA certificates
## Bugfixes since 2.2.1
- Reduce CPU usage with multiple servers
- Fix yet another potential stalling issue
- Remove Timeout tracebacks
- Only warn if number of actual passwords is larger than 30
- Unexpected behavior when diskspace becomes critically low
- MacOS: Direct Unpack could hang in case of special charters in names
- API: Correct listing of downloaded and queued files in get_files
- API: Jobs with Force priority should always have status 'Downloading'
## Upgrading from 2.1.x and older
## Upgrading from 2.2.x and older
- Finish queue
- Stop SABnzbd
- Install new version
- Start SABnzbd
## Upgrade notices
- When upgrading from 2.1.0 or older the queue will be converted. Job order,
- When upgrading from 2.2.0 or older the queue will be converted. Job order,
settings and data will be preserved, but all jobs will be unpaused and
URL's that did not finish fetching before the upgrade will be lost.
- The organization of the download queue is different from 0.7.x releases.

View File

@@ -32,6 +32,7 @@ except:
import logging
import logging.handlers
import traceback
import os
import getopt
import signal
@@ -86,7 +87,7 @@ import sabnzbd.interface
from sabnzbd.constants import *
import sabnzbd.newsunpack
from sabnzbd.misc import real_path, \
check_latest_version, exit_sab, \
check_latest_version, exit_sab, get_from_url, \
split_host, get_ext, create_https_certificates, \
windows_variant, ip_extract, set_serv_parms, get_serv_parms, globber_full
from sabnzbd.panic import panic_tmpl, panic_port, panic_host, \
@@ -150,7 +151,11 @@ class guiHandler(logging.Handler):
# Loose the oldest record
self.store.pop(0)
try:
self.store.append(self.format(record))
# Append traceback, if available
warning = {'type': record.levelname, 'text': record.msg % record.args, 'time': int(time.time())}
if record.exc_info:
warning['text'] = '%s\n%s' % (warning['text'], traceback.format_exc())
self.store.append(warning)
except UnicodeDecodeError:
# Catch elusive Unicode conversion problems
pass
@@ -161,12 +166,6 @@ class guiHandler(logging.Handler):
def count(self):
return len(self.store)
def last(self):
if self.store:
return self.store[len(self.store) - 1]
else:
return ""
def content(self):
""" Return an array with last records """
return self.store
@@ -202,11 +201,11 @@ def print_help():
print " --repair-all Try to reconstruct the queue from the incomplete folder"
print " with full data reconstruction"
print " --https <port> Port to use for HTTPS server"
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 " --console Force console logging for OSX app"
print " --new Run a new instance of SABnzbd"
print " --ipv6_hosting <0|1> Listen on IPv6 address [::1]"
def print_version():
@@ -402,7 +401,7 @@ def print_modules():
""" Log all detected optional or external modules """
if sabnzbd.decoder.SABYENC_ENABLED:
# Yes, we have SABYenc, and it's the correct version, so it's enabled
logging.info("SABYenc module (v%s)... found!", sabnzbd.constants.SABYENC_VERSION_REQUIRED)
logging.info("SABYenc module (v%s)... found!", sabnzbd.decoder.SABYENC_VERSION)
else:
# Something wrong with SABYenc, so let's determine and print what:
if sabnzbd.decoder.SABYENC_VERSION:
@@ -658,7 +657,7 @@ def is_sabnzbd_running(url):
url = '%s&mode=version' % (url)
# Do this without certificate verification, few installations will have that
prev = sabnzbd.set_https_verification(False)
ver = sabnzbd.newsunpack.get_from_url(url)
ver = get_from_url(url)
sabnzbd.set_https_verification(prev)
return (ver and (re.search(r'\d+\.\d+\.', ver) or ver.strip() == sabnzbd.__version__))
except:

6
appveyor.yml Normal file
View File

@@ -0,0 +1,6 @@
install:
- pip install --upgrade -r tests/requirements.txt
- pip install pypiwin32 subprocessww
build_script:
- pytest

View File

@@ -596,7 +596,7 @@ class MemcachedSession(Session):
# Wrap all .get and .set operations in a single lock.
mc_lock = threading.RLock()
# This is a seperate set of locks per session id.
# This is a separate set of locks per session id.
locks = {}
servers = ['127.0.0.1:11211']

View File

@@ -1,16 +0,0 @@
import six
import mock
from cherrypy import wsgiserver
class TestWSGIGateway_u0:
@mock.patch('cherrypy.wsgiserver.WSGIGateway_10.get_environ',
lambda self: {'foo': 'bar'})
def test_decodes_items(self):
req = mock.MagicMock(path=b'/', qs=b'')
gw = wsgiserver.WSGIGateway_u0(req=req)
env = gw.get_environ()
assert env['foo'] == 'bar'
assert isinstance(env['foo'], six.text_type)

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Config"#-->
<!--#set global $help_uri="configuration/2.2/configure"#-->
<!--#set global $help_uri="configuration/2.3/configure"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#from locale import getpreferredencoding#-->
@@ -81,7 +81,7 @@
</td>
</tr>
<!--#end if#-->
<!--#if not $have_unzip #-->
<!--#if not $have_unzip and not $have_7zip #-->
<tr>
<th scope="row">$T('opt-enable_unzip'):</th>
<td>

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Categories"#-->
<!--#set global $help_uri="configuration/2.2/categories"#-->
<!--#set global $help_uri="configuration/2.3/categories"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
<div class="section">

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Folders"#-->
<!--#set global $help_uri="configuration/2.2/folders"#-->
<!--#set global $help_uri="configuration/2.3/folders"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">

View File

@@ -1,9 +1,9 @@
<!--#set global $pane="General"#-->
<!--#set global $help_uri="configuration/2.2/general"#-->
<!--#set global $help_uri="configuration/2.3/general"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
<form action="saveGeneral" method="post" name="fullform" class="fullform" autocomplete="off" novalidate>
<form action="saveGeneral" method="post" name="fullform" class="fullform" autocomplete="off">
<input type="hidden" id="session" name="session" value="$session" />
<input type="hidden" id="ajax" name="ajax" value=1 />
<div class="section">
@@ -253,6 +253,32 @@
})
hideOrShowTranslate()
// Highlight in case user is not safe
// So when exposed to internet and no password, no external limit or no username/password
var safeCheck = \$('#host, #local_ranges, #inet_exposure, #${pid}_wu, #${pid}_wp')
function checkSafety() {
if(\$('#host').val() != 'localhost' && \$('#host').val() != '127.0.0.1') {
// No limitation on local-network
if(!\$('#local_ranges').val() || \$('#inet_exposure').val() > 3) {
// And no username and password?
if(!\$('#${pid}_wu').val() || !\$('#${pid}_wp').val()) {
// Add warning icon if not there already
if(!\$('.host-warning').length) {
safeCheck.after('<span class="glyphicon glyphicon-alert host-warning"></span>')
\$('.host-warning').tooltip({'title': '$T('checkSafety')'})
}
return
}
}
}
// Remove warnings
\$('.host-warning').remove()
safeCheck.removeClass('host-warning-highlight')
}
checkSafety()
safeCheck.on('change', checkSafety)
// Click functions
\$('#apikey, #nzbkey').click(function () { \$(this).select() });
\$('#generate_new_apikey').click(function () {
@@ -330,7 +356,6 @@
}
}
// Update the value
\$('#bandwidth_max_value, #bandwidth_max_dropdown').on('change', function() {
if(\$('#bandwidth_max_value').val()) {

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Email"#-->
<!--#set global $help_uri="configuration/2.2/notifications"#-->
<!--#set global $help_uri="configuration/2.3/notifications"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#def show_notify_checkboxes($section_label)#-->
@@ -26,7 +26,7 @@
<!--#end def#-->
<div class="colmask">
<form action="saveEmail" method="post" name="fullform" class="fullform" autocomplete="off" novalidate>
<form action="saveEmail" method="post" name="fullform" class="fullform" autocomplete="off">
<input type="hidden" id="session" name="session" value="$session" />
<input type="hidden" id="ajax" name="ajax" value="1" />
<div class="section" id="email">
@@ -326,6 +326,16 @@
<input type="text" name="pushover_device" id="pushover_device" value="$pushover_device" />
<span class="desc">$T('explain-pushover_device')</span>
</div>
<div class="field-pair">
<label class="config" for="pushover_emergency_retry">$T('opt-pushover_emergency_retry')</label>
<input type="text" name="pushover_emergency_retry" id="pushover_emergency_retry" value="$pushover_emergency_retry" />
<span class="desc">$T('explain-pushover_emergency_retry')</span>
</div>
<div class="field-pair">
<label class="config" for="pushover_emergency_expire">$T('opt-pushover_emergency_expire')</label>
<input type="text" name="pushover_emergency_expire" id="pushover_emergency_expire" value="$pushover_emergency_expire" />
<span class="desc">$T('explain-pushover_emergency_expire')</span>
</div>
<!--#set $section_label = 'pushover'#-->
<!--#for $type in $notify_keys#-->
<div class="field-pair">

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="RSS"#-->
<!--#set global $help_uri="configuration/2.2/rss"#-->
<!--#set global $help_uri="configuration/2.3/rss"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
<!--#if not $active_feed#-->
@@ -7,7 +7,7 @@
<div class="padTable">
<a class="main-helplink" href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<p>$T('explain-RSS')</p>
<form action="add_rss_feed" method="post" autocomplete="off" novalidate>
<form action="add_rss_feed" method="post" autocomplete="off">
<input type="hidden" name="session" value="$session" />
<table class="catTable">
<tr>
@@ -37,7 +37,7 @@
<!--#if $rss#-->
<div class="section">
<div class="padTable">
<form action="save_rss_feed" method="post" autocomplete="off" novalidate>
<form action="save_rss_feed" method="post" autocomplete="off">
<input type="hidden" name="session" value="$session" />
<table id="subscriptions">
<tbody>
@@ -73,7 +73,7 @@
</form>
<!--#if $feeds#-->
<br/>
<form action="rss_now" method="post" autocomplete="off" novalidate>
<form action="rss_now" method="post" autocomplete="off">
<input type="hidden" name="session" value="$session" />
<button type="submit" class="btn btn-default readAll"><span class="glyphicon glyphicon-sort"></span> $T('button-rssNow')</button>
</form>
@@ -154,7 +154,7 @@
<option value=">"> $T('rss-atleast')</option>
<option value="<"> $T('rss-atmost')</option>
<option value="F"> $T('rss-from')</option>
<option value="F"> $T('rss-from-show')</option>
<option value="F"> $T('rss-from-show') ($T('rss-accept'))</option>
</select>
</td>
<td>
@@ -226,8 +226,8 @@
<option value="C"> $T('rss-mustcat')</option>
<option value=">"> $T('rss-atleast')</option>
<option value="<"> $T('rss-atmost')</option>
<option value="S"> $T('rss-from-show')</option>
<option value="F"> $T('rss-from')</option>
<option value="S"> $T('rss-from-show') ($T('rss-accept'))</option>
</select>
</td>
<td>
@@ -287,7 +287,7 @@
<input type="hidden" name="feed" value="$feed" />
<table class="catTable">
<tbody>
<tr class="<!--#if $odd then " alt " else " "#--> <!--#if $filter[3]!="A" then 'disabled_options_rule' else ""#-->">
<tr class="<!--#if $odd then " alt " else " "#--> <!--#if $filter[3]!="A" and $filter[3]!="S" then 'disabled_options_rule' else ""#-->">
<td>
<input type="checkbox" name="enabled" value="1" <!--#if $filter[6]=='1' then 'checked="checked"' else ""#--> />
</td>
@@ -302,8 +302,8 @@
<option value="C" <!--#if $filter[3]=="C" then 'selected="selected"' else ""#-->> $T('rss-mustcat')</option>
<option value=">" <!--#if $filter[3]==">" then 'selected="selected"' else ""#-->> $T('rss-atleast')</option>
<option value="<" <!--#if $filter[3]=="<" then 'selected="selected"' else ""#-->> $T('rss-atmost')</option>
<option value="S" <!--#if $filter[3]=="S" then 'selected="selected"' else ""#-->> $T('rss-from-show')</option>
<option value="F" <!--#if $filter[3]=="F" then 'selected="selected"' else ""#-->> $T('rss-from')</option>
<option value="S" <!--#if $filter[3]=="S" then 'selected="selected"' else ""#-->> $T('rss-from-show') ($T('rss-accept'))</option>
</select>
</td>
<td>
@@ -568,7 +568,7 @@ function urlencode(str) {
// Only the Accept filter needs all the options
\$('form[action="upd_rss_filter"]').find('select[name="filter_type"]').change(function() {
\$(this).parent().parent().find('select:not([name="filter_type"])').attr('disabled', \$(this).val() != "A")
\$(this).parent().parent().find('select:not([name="filter_type"])').attr('disabled', \$(this).val() != "A" && \$(this).val() != "S")
})
// Trigger on-load for all
\$('.disabled_options_rule').find('td select:not([name="filter_type"])').attr('disabled', true)

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Scheduling"#-->
<!--#set global $help_uri="configuration/2.2/scheduling"#-->
<!--#set global $help_uri="configuration/2.3/scheduling"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<%

View File

@@ -1,108 +1,299 @@
<!--#set global $pane="Servers"#-->
<!--#set global $help_uri="configuration/2.2/servers"#-->
<!--#set global $help_uri="configuration/2.3/servers"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--
We need to find how many months we have recorded so far, so we
loop over all the dates to find the lowest value and then use
this to calculate the date-selector and maximum value per month.
-->
<!--#import json#-->
<!--#import datetime#-->
<!--#import sabnzbd.misc#-->
<!--#set month_names = [$T('January'), $T('February'), $T('March'), $T('April'), $T('May'), $T('June'), $T('July'), $T('August'), $T('September'), $T('October'), $T('November'), $T('December')] #-->
<!--#set min_date = datetime.date.today()#-->
<!--#set max_data_all = {}#-->
<!--#for $server in $servers #-->
<!--#if 'amounts' in $server#-->
<!--#set max_data_server = {}#-->
<!--#for date in $server['amounts'][4]#-->
<!--#set split_date = $date.split('-')#-->
<!--#set min_date = min(min_date, datetime.date(int(split_date[0]), int(split_date[1]), 1))#-->
<!--#set month_date = $date[:7]#-->
<!--#if $month_date not in $max_data_server#-->
<!--#set max_data_server[$month_date] = 0#-->
<!--#end if#-->
<!--#set max_data_server[$month_date] = max(max_data_server[$month_date], $server['amounts'][4][$date])#-->
<!--#end for#-->
<!--#for month_date in max_data_server#-->
<!--#if $month_date not in $max_data_all#-->
<!--#set max_data_all[$month_date] = 0#-->
<!--#end if#-->
<!--#set max_data_all[$month_date] = max(max_data_all[$month_date], max_data_server[$month_date])#-->
<!--#end for#-->
<!--#end if#-->
<!--#end for#-->
<!--#set months_recorded = list(sabnzbd.misc.monthrange(min_date, datetime.date.today()))#-->
<!--#$months_recorded.reverse()#-->
<script type="text/javascript">
// Define variable needed for the server-plots
var serverData = {}
</script>
<div class="colmask">
<form action="addServer" method="post" autocomplete="off" onsubmit="removeObfuscation();" novalidate>
<input type="hidden" name="session" value="$session" />
<div id="addServer">
<div class="padding alt">
<button type="button" class="btn btn-default" id="addServerButton"><span class="glyphicon glyphicon-plus"></span> $T('button-addServer')</button>
</div>
</div>
<div class="section" id="addServerContent" style="display: none;">
<div class="col2">
<h3>$T('addServer') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
<div class="field-pair">
<label class="config" for="enable">$T('srv-enable')</label>
<input type="checkbox" name="enable" id="enable" value="1" checked="checked" />
<span class="desc">$T('srv-enable')</span>
</div>
<div class="field-pair">
<label class="config" for="host">$T('srv-host')</label>
<input type="text" name="host" id="host" />
</div>
<div class="field-pair">
<label class="config" for="port">$T('srv-port')</label>
<input type="number" name="port" id="port" size="8" value="119" />
</div>
<div class="field-pair">
<label class="config" for="ssl">$T('srv-ssl')</label>
<input type="checkbox" name="ssl" id="ssl" value="1" />
<span class="desc">$T('explain-ssl')</span>
</div>
<!-- Tricks to avoid browser auto-fill, fixed on-submit with javascript -->
<div class="field-pair">
<label class="config" for="${pid}_00">$T('srv-username')</label>
<input type="text" name="${pid}_00" id="${pid}_00" data-hide="username" />
</div>
<div class="field-pair">
<label class="config" for="${pid}_01">$T('srv-password')</label>
<input type="text" name="${pid}_01" id="${pid}_01" data-hide="password" />
</div>
<div class="field-pair">
<label class="config" for="connections">$T('srv-connections')</label>
<input type="number" name="connections" id="connections" min="0" max="100" value="8" />
</div>
<div class="field-pair">
<label class="config" for="priority">$T('srv-priority')</label>
<input type="number" name="priority" id="priority" min="0" max="100" /> <i>$T('explain-svrprio')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="retention">$T('srv-retention')</label>
<input type="number" name="retention" id="retention" min="0" /> <i>$T('days')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="timeout">$T('srv-timeout')</label>
<input type="number" name="timeout" id="timeout" min="30" /> <i>$T('seconds')</i>
</div>
<div class="field-pair <!--#if int($have_ssl_context) == 0 then "disabled" else ""#--> advanced-settings">
<label class="config" for="ssl_verify">$T('opt-ssl_verify')</label>
<select name="ssl_verify" id="ssl_verify" <!--#if int($have_ssl_context) == 0 then "disabled=\"disabled\"" else ""#-->>
<option value="2" selected>$T('ssl_verify-strict')</option>
<option value="1">$T('ssl_verify-normal')</option>
<option value="0">$T('ssl_verify-disabled')</option>
<form action="addServer" method="post" autocomplete="off" onsubmit="removeObfuscation();">
<input type="hidden" name="session" value="$session" />
<div id="addServer">
<div class="padding alt">
<button type="button" class="btn btn-default" id="addServerButton"><span class="glyphicon glyphicon-plus"></span> $T('button-addServer')</button>
<!--#if $months_recorded#-->
<div class="chart-selector-container" title="$T('srv-bandwidth')">
<span class="glyphicon glyphicon-signal"></span>
<select name="chart-selector" id="chart-selector">
<!--#for $cur_date in months_recorded#-->
<!--#set month_date = '%d-%02d' % ($cur_date.year, $cur_date.month)#-->
<!--#if $month_date not in $max_data_all#-->
<!--#set max_data_all[$month_date] = 0#-->
<!--#end if#-->
<option value="$month_date" data-max="$max_data_all[$month_date]">$month_names[$cur_date.month-1] $cur_date.year</option>
<!--#end for#-->
</select>
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</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" />
<span class="desc">$T('srv-explain-send_group')</span>
<!--#end if#-->
</div>
</div>
<div class="section" id="addServerContent" style="display: none;">
<div class="col2">
<h3>$T('addServer') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div>
<div class="col1">
<fieldset>
<div class="field-pair">
<label class="config" for="enable">$T('srv-enable')</label>
<input type="checkbox" name="enable" id="enable" value="1" checked="checked" />
<span class="desc">$T('srv-enable')</span>
</div>
<div class="field-pair">
<label class="config" for="host">$T('srv-host')</label>
<input type="text" name="host" id="host" required />
</div>
<div class="field-pair">
<label class="config" for="port">$T('srv-port')</label>
<input type="number" name="port" id="port" size="8" value="119" min="0" />
</div>
<div class="field-pair">
<label class="config" for="ssl">$T('srv-ssl')</label>
<input type="checkbox" name="ssl" id="ssl" value="1" />
<span class="desc">$T('explain-ssl')</span>
</div>
<!-- Tricks to avoid browser auto-fill, fixed on-submit with javascript -->
<div class="field-pair">
<label class="config" for="${pid}_00">$T('srv-username')</label>
<input type="text" name="${pid}_00" id="${pid}_00" data-hide="username" />
</div>
<div class="field-pair">
<label class="config" for="${pid}_01">$T('srv-password')</label>
<input type="text" name="${pid}_01" id="${pid}_01" data-hide="password" />
</div>
<div class="field-pair">
<label class="config" for="connections">$T('srv-connections')</label>
<input type="number" name="connections" id="connections" min="1" max="100" value="8" required />
</div>
<div class="field-pair">
<label class="config" for="priority">$T('srv-priority')</label>
<input type="number" name="priority" id="priority" min="0" max="99" /> <i>$T('explain-svrprio')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="retention">$T('srv-retention')</label>
<input type="number" name="retention" id="retention" min="0" /> <i>$T('days')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="timeout">$T('srv-timeout')</label>
<input type="number" name="timeout" id="timeout" min="20" max="240" /> <i>$T('seconds')</i>
</div>
<div class="field-pair <!--#if int($have_ssl_context) == 0 then "disabled" else ""#--> advanced-settings">
<label class="config" for="ssl_verify">$T('opt-ssl_verify')</label>
<select name="ssl_verify" id="ssl_verify" <!--#if int($have_ssl_context) == 0 then "disabled=\"disabled\"" else ""#-->>
<option value="2" selected>$T('ssl_verify-strict')</option>
<option value="1">$T('ssl_verify-normal')</option>
<option value="0">$T('ssl_verify-disabled')</option>
</select>
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</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" />
<span class="desc">$T('srv-explain-send_group')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="optional">$T('srv-optional')</label>
<input type="checkbox" name="optional" id="optional" value="1" />
<span class="desc">$T('explain-optional')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="displayname">$T('srv-displayname')</label>
<input type="text" name="displayname" id="displayname" />
</div>
<div class="field-pair advanced-settings">
<label class="config" for="notes">$T('srv-notes')</label>
<textarea name="notes" id="notes" rows="3" cols="50"></textarea>
</div>
<div class="field-pair">
<button class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> $T('button-addServer')</button>
<button class="btn btn-default advancedButton"><span class="glyphicon glyphicon-cog"></span> $T('button-advanced')</button>
<button class="btn btn-default testServer" type="button"><span class="glyphicon glyphicon-sort"></span> $T('button-testServer')</button>
</div>
<div class="field-pair result-box">
<div class="alert"></div>
</div>
</fieldset>
</div>
</div>
</form>
<!--#set $prio_colors = ["#59cc33", "#3366cc","#7f33cc", "#cc33a6", "#cc3333"] #-->
<!--#set $cur_prio_color = -1 #-->
<!--#set $last_prio = -1 #-->
<!--#for $cur, $server in enumerate($servers) #-->
<form action="saveServer" method="post" class="fullform" autocomplete="off">
<input type="hidden" name="session" value="$session" />
<input type="hidden" name="server" value="$server['name']" />
<div class="section <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
<div class="col2 <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
<h3>$server['displayname'] <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<!--#if int($server['enable']) != 0 #-->
<!--#if $last_prio != $server['priority'] and $cur_prio_color+1 < len($prio_colors) #-->
<!--#set $cur_prio_color = $cur_prio_color+1 #-->
<!--#set $last_prio = $server['priority'] #-->
<!--#end if#-->
<span class="label label-primary" style="background-color: $prio_colors[$cur_prio_color]">$server['priority']</span>
<span class="label label-primary" style="background-color: $prio_colors[$cur_prio_color]">$T('srv-priority'):</span>
<!--#end if#-->
<table>
<tr>
<td><input type="checkbox" class="toggleServerCheckbox" id="enable_$cur" name="$server['name']" value="1" <!--#if int($server['enable']) != 0 then 'checked="checked"' else ""#--> /></td>
<td><label for="enable_$cur">$T('enabled')</label></td>
</tr>
</table>
<button type="button" class="btn btn-default showserver"><span class="glyphicon glyphicon-pencil"></span> $T('showDetails')</button>
<button type="button" class="btn btn-default clrServer"><span class="glyphicon glyphicon-remove"></span> $T('button-clrServer')</button>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="optional">$T('srv-optional')</label>
<input type="checkbox" name="optional" id="optional" value="1" />
<span class="desc">$T('explain-optional')</span>
<div class="col1" style="display:none;">
<input type="hidden" name="enable" id="enable$cur" value="$int($server['enable'])" />
<fieldset>
<div class="field-pair">
<label class="config" for="host$cur">$T('srv-host')</label>
<input type="text" name="host" id="host$cur" value="$server['host']" required />
</div>
<div class="field-pair">
<label class="config" for="port$cur">$T('srv-port')</label>
<input type="number" name="port" id="port$cur" value="$server['port']" size="8" min="0" required />
</div>
<div class="field-pair">
<label class="config" for="ssl$cur">$T('srv-ssl')</label>
<input type="checkbox" name="ssl" id="ssl$cur" value="1" <!--#if int($server['ssl']) != 0 then 'checked="checked"' else ""#--> />
<span class="desc">$T('explain-ssl')</span>
</div>
<!-- Tricks to avoid browser auto-fill, fixed on-submit with javascript -->
<div class="field-pair">
<label class="config" for="${pid}_${cur}0">$T('srv-username')</label>
<input type="text" name="${pid}_${cur}0" id="${pid}_${cur}0" value="$server['username']" data-hide="username" />
</div>
<div class="field-pair">
<label class="config" for="${pid}_${cur}1">$T('srv-password')</label>
<input type="text" name="${pid}_${cur}1" id="${pid}_${cur}1" value="$server['password']" data-hide="password" />
</div>
<div class="field-pair">
<label class="config" for="connections$cur">$T('srv-connections')</label>
<input type="number" name="connections" id="connections$cur" value="$server['connections']" min="1" max="100" required />
</div>
<div class="field-pair">
<label class="config" for="priority$cur">$T('srv-priority')</label>
<input type="number" name="priority" id="priority$cur" value="$server['priority']" min="0" max="99" required /> <i>$T('explain-svrprio')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="retention$cur">$T('srv-retention')</label>
<input type="number" name="retention" id="retention$cur" value="$server['retention']" min="0" required /> <i>$T('days')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="timeout$cur">$T('srv-timeout')</label>
<input type="number" name="timeout" id="timeout$cur" value="$server['timeout']" min="20" max="240" required /> <i>$T('seconds')</i>
</div>
<div class="field-pair <!--#if int($have_ssl_context) == 0 then "disabled" else ""#--> advanced-settings">
<label class="config" for="ssl_verify$cur">$T('opt-ssl_verify')</label>
<select name="ssl_verify" id="ssl_verify$cur" <!--#if int($have_ssl_context) == 0 then "disabled=\"disabled\"" else ""#-->>
<option value="2" <!--#if $server['ssl_verify'] == 2 then 'selected="selected"' else ""#--> >$T('ssl_verify-strict')</option>
<option value="1" <!--#if $server['ssl_verify'] == 1 then 'selected="selected"' else ""#--> >$T('ssl_verify-normal')</option>
<option value="0" <!--#if $server['ssl_verify'] == 0 then 'selected="selected"' else ""#--> >$T('ssl_verify-disabled')</option>
</select>
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</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 ""#--> />
<span class="desc">$T('explain-optional')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="send_group$cur">$T('srv-send_group')</label>
<input type="checkbox" name="send_group" id="send_group$cur" value="1" <!--#if int($server['send_group']) != 0 then 'checked="checked"' else ""#--> />
<span class="desc">$T('srv-explain-send_group')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="displayname$cur">$T('srv-displayname')</label>
<input type="text" name="displayname" id="displayname$cur" value="$server['displayname']" />
</div>
<div class="field-pair advanced-settings">
<label class="config" for="notes$cur">$T('srv-notes')</label>
<textarea name="notes" id="notes$cur" rows="3" cols="50">$server['notes']</textarea>
</div>
<div class="field-pair">
<button class="btn btn-default saveButton"><span class="glyphicon glyphicon-ok"></span> $T('button-saveChanges')</button>
<button class="btn btn-default advancedButton"><span class="glyphicon glyphicon-cog"></span> $T('button-advanced')</button>
<button class="btn btn-default testServer" type="button"><span class="glyphicon glyphicon-sort"></span> $T('button-testServer')</button>
<button class="btn btn-default delServer"><span class="glyphicon glyphicon-trash"></span> $T('button-delServer')</button>
</div>
<div class="field-pair result-box">
<div class="alert"></div>
</div>
</fieldset>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="displayname">$T('srv-displayname')</label>
<input type="text" name="displayname" id="displayname" />
<div class="col1" style="display:block;">
<!--#if 'amounts' in $server#-->
<div class="server-amounts-text">
<b>$T('srv-bandwidth'):</b><br/>
$T('total'): $(server['amounts'][0])B<br/>
$T('today'): $(server['amounts'][3])B<br/>
$T('thisWeek'): $(server['amounts'][2])B<br/>
$T('thisMonth'): $(server['amounts'][1])B<br/>
<span id="server-data-label-${cur}"></span>: <span id="server-data-value-${cur}"></span>
</div>
<div class="server-chart" data-serverid="${cur}"s>
<div id="server-chart-${cur}" class="ct-chart"></div>
</div>
<script type="text/javascript">
// Server data
serverData[${cur}] = <!--#echo json.dumps($server['amounts'][4])#-->
</script>
<!--#end if#-->
</div>
<div class="field-pair advanced-settings">
<label class="config" for="notes">$T('srv-notes')</label>
<textarea name="notes" id="notes" rows="3" cols="50"></textarea>
</div>
<div class="field-pair">
<button class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> $T('button-addServer')</button>
<button class="btn btn-default advancedButton"><span class="glyphicon glyphicon-cog"></span> $T('button-advanced')</button>
<button class="btn btn-default testServer" type="button"><span class="glyphicon glyphicon-sort"></span> $T('button-testServer')</button>
</div>
<div class="field-pair result-box">
<div class="alert"></div>
</div>
</fieldset>
</div><!-- /col1 -->
</div><!-- /section -->
</form>
</div>
</form>
<!--#end for#-->
</div>
<script type="text/javascript" src="${root}staticcfg/js/chartist.min.js"></script>
<script type="text/javascript" src="${root}staticcfg/js/filesize.min.js"></script>
<script type="text/javascript">
// Define variables needed for the server-plots
var serverData = {}
// Standardize chart options
var chartOptions = {
fullWidth: true,
showArea: true,
@@ -125,246 +316,76 @@
right: 20
}
}
</script>
<!--
We need to find how many months we have recorded so far, so we
loop over all the dates to find the lowest value and then use
this to calculate the date-selector
-->
<!--#import json#-->
<!--#import datetime#-->
<!--#import sabnzbd.misc#-->
<!--#def show_date_selector($server, $id)#-->
<!--#set month_names = [$T('January'), $T('February'), $T('March'), $T('April'), $T('May'), $T('June'), $T('July'), $T('August'), $T('September'), $T('October'), $T('November'), $T('December')] #-->
<!--#set min_date = datetime.date.today()#-->
<!--#for date in $server['amounts'][4]#-->
<!--#set split_date = $date.split('-')#-->
<!--#set min_date = min(min_date, datetime.date(int(split_date[0]), int(split_date[1]), 1))#-->
<!--#end for#-->
<!--#set months_recorded = list(sabnzbd.misc.monthrange(min_date, datetime.date.today()))#-->
<!--#$months_recorded.reverse()#-->
<select class="chart-selector" name="chart-selector-${id}" id="chart-selector-${id}" data-id="${id}">
<!--#for $cur_date in months_recorded#-->
<option value="<!--#echo '%d-%02d' % ($cur_date.year, $cur_date.month)#-->">$month_names[$cur_date.month-1] $cur_date.year</option>
<!--#end for#-->
</select>
<!--#end def#-->
<!--#set $prio_colors = ["#59cc33", "#3366cc","#7f33cc", "#cc33a6", "#cc3333"] #-->
<!--#set $cur_prio_color = -1 #-->
<!--#set $last_prio = -1 #-->
<!--#for $cur, $server in enumerate($servers) #-->
<form action="saveServer" method="post" class="fullform" autocomplete="off" novalidate>
<input type="hidden" name="session" value="$session" />
<input type="hidden" name="server" value="$server['name']" />
<div class="section <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
<div class="col2 <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
<h3>$server['displayname'] <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<!--#if int($server['enable']) != 0 #-->
<!--#if $last_prio != $server['priority'] and $cur_prio_color+1 < len($prio_colors) #-->
<!--#set $cur_prio_color = $cur_prio_color+1 #-->
<!--#set $last_prio = $server['priority'] #-->
<!--#end if#-->
<span class="label label-primary" style="background-color: $prio_colors[$cur_prio_color]">$server['priority']</span>
<span class="label label-primary" style="background-color: $prio_colors[$cur_prio_color]">$T('srv-priority'):</span>
<!--#end if#-->
<table><tr>
<td><input type="checkbox" class="toggleServerCheckbox" id="enable_$cur" name="$server['name']" value="1" <!--#if int($server['enable']) != 0 then 'checked="checked"' else ""#--> /></td>
<td><label for="enable_$cur">$T('enabled')</label></td>
</tr></table>
<button type="button" class="btn btn-default showserver"><span class="glyphicon glyphicon-pencil"></span> $T('showDetails')</button>
<button type="button" class="btn btn-default clrServer"><span class="glyphicon glyphicon-remove"></span> $T('button-clrServer')</button>
</div><!-- /col2 -->
<div class="col1" style="display:none;">
<input type="hidden" name="enable" id="enable$cur" value="$int($server['enable'])" />
<fieldset>
<div class="field-pair">
<label class="config" for="host$cur">$T('srv-host')</label>
<input type="text" name="host" id="host$cur" value="$server['host']" />
</div>
<div class="field-pair">
<label class="config" for="port$cur">$T('srv-port')</label>
<input type="number" name="port" id="port$cur" value="$server['port']" size="8" />
</div>
<div class="field-pair">
<label class="config" for="ssl$cur">$T('srv-ssl')</label>
<input type="checkbox" name="ssl" id="ssl$cur" value="1" <!--#if int($server['ssl']) != 0 then 'checked="checked"' else ""#--> />
<span class="desc">$T('explain-ssl')</span>
</div>
<!-- Tricks to avoid browser auto-fill, fixed on-submit with javascript -->
<div class="field-pair">
<label class="config" for="${pid}_${cur}0">$T('srv-username')</label>
<input type="text" name="${pid}_${cur}0" id="${pid}_${cur}0" value="$server['username']" data-hide="username" />
</div>
<div class="field-pair">
<label class="config" for="${pid}_${cur}1">$T('srv-password')</label>
<input type="text" name="${pid}_${cur}1" id="${pid}_${cur}1" value="$server['password']" data-hide="password" />
</div>
<div class="field-pair">
<label class="config" for="connections$cur">$T('srv-connections')</label>
<input type="number" name="connections" id="connections$cur" value="$server['connections']" min="0" max="100" />
</div>
<div class="field-pair">
<label class="config" for="priority$cur">$T('srv-priority')</label>
<input type="number" name="priority" id="priority$cur" value="$server['priority']" min="0" max="100" /> <i>$T('explain-svrprio')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="retention$cur">$T('srv-retention')</label>
<input type="number" name="retention" id="retention$cur" value="$server['retention']" min="0" /> <i>$T('days')</i>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="timeout$cur">$T('srv-timeout')</label>
<input type="number" name="timeout" id="timeout$cur" value="$server['timeout']" min="30" /> <i>$T('seconds')</i>
</div>
<div class="field-pair <!--#if int($have_ssl_context) == 0 then "disabled" else ""#--> advanced-settings">
<label class="config" for="ssl_verify$cur">$T('opt-ssl_verify')</label>
<select name="ssl_verify" id="ssl_verify$cur" <!--#if int($have_ssl_context) == 0 then "disabled=\"disabled\"" else ""#-->>
<option value="2" <!--#if $server['ssl_verify'] == 2 then 'selected="selected"' else ""#--> >$T('ssl_verify-strict')</option>
<option value="1" <!--#if $server['ssl_verify'] == 1 then 'selected="selected"' else ""#--> >$T('ssl_verify-normal')</option>
<option value="0" <!--#if $server['ssl_verify'] == 0 then 'selected="selected"' else ""#--> >$T('ssl_verify-disabled')</option>
</select>
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</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 ""#--> />
<span class="desc">$T('explain-optional')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="send_group$cur">$T('srv-send_group')</label>
<input type="checkbox" name="send_group" id="send_group$cur" value="1" <!--#if int($server['send_group']) != 0 then 'checked="checked"' else ""#--> />
<span class="desc">$T('srv-explain-send_group')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="displayname$cur">$T('srv-displayname')</label>
<input type="text" name="displayname" id="displayname$cur" value="$server['displayname']" />
</div>
<div class="field-pair advanced-settings">
<label class="config" for="notes$cur">$T('srv-notes')</label>
<textarea name="notes" id="notes$cur" rows="3" cols="50">$server['notes']</textarea>
</div>
<div class="field-pair">
<button class="btn btn-default saveButton"><span class="glyphicon glyphicon-ok"></span> $T('button-saveChanges')</button>
<button class="btn btn-default advancedButton"><span class="glyphicon glyphicon-cog"></span> $T('button-advanced')</button>
<button class="btn btn-default testServer" type="button"><span class="glyphicon glyphicon-sort"></span> $T('button-testServer')</button>
<button class="btn btn-default delServer"><span class="glyphicon glyphicon-trash"></span> $T('button-delServer')</button>
</div>
<div class="field-pair result-box">
<div class="alert"></div>
</div>
</fieldset>
</div>
<div class="col1" style="display:block;">
<!--#if 'amounts' in $server#-->
<div class="server-amounts-text">
<b>$T('srv-bandwidth'):</b><br/>
$T('total'): $(server['amounts'][0])B<br/>
$T('today'): $(server['amounts'][3])B<br/>
$T('thisWeek'): $(server['amounts'][2])B<br/>
$T('thisMonth'): $(server['amounts'][1])B
</div>
<div class="server-chart">
$show_date_selector($server, $cur)
<div id="server-chart-${cur}" class="ct-chart"></div>
</div>
<script type="text/javascript">
// Server data
serverData[${cur}] = <!--#echo json.dumps($server['amounts'][4])#-->
\$(document).ready(function() {
showChart(${cur}, \$('#chart-selector-${cur}').val())
})
</script>
<!--#end if#-->
</div>
</div>
</form>
<!--#end for#-->
</div><!-- /colmask -->
<script type="text/javascript">
function showChart(server_id, month) {
function showCharts() {
// This month
var theMonth = \$('#chart-selector').val()
var thisDay = new Date()
// What month are we doing?
var inputDate = new Date(month+'-01')
var inputDate = new Date(theMonth+'-01')
var baseDate = new Date(inputDate.getUTCFullYear(), inputDate.getUTCMonth(), 1)
var maxDaysInMonth = new Date(baseDate.getFullYear(), baseDate.getMonth()+1, 0).getDate()
// Fill the data array
var data = {
labels: [],
series: [[]]
};
var largestVal = 0
for(var i = 1; i < maxDaysInMonth+1; i++) {
// Add X-label
if(i % 3 == 1) {
data['labels'].push(i)
} else {
data['labels'].push(NaN)
// Set the new maximum
chartOptions.axisY.high = \$('#chart-selector :selected').data('max');
chartOptions.axisY.low = 0
// For each chart
\$('.server-chart').each(function(i, elemn) {
var server_id = \$(elemn).data('serverid')
// Fill the data array
var data = {
labels: [],
series: [[]]
};
var totalThisMonth = 0
for(var i = 1; i < maxDaysInMonth+1; i++) {
// Add X-label
if(i % 3 == 1) {
data['labels'].push(i)
} else {
data['labels'].push(NaN)
}
// Get formatted date
baseDate.setDate(i)
var dateCheck = toFormattedDate(baseDate)
// Add data if we have it
if(dateCheck in serverData[server_id]) {
data['series'][0].push(serverData[server_id][dateCheck])
totalThisMonth += serverData[server_id][dateCheck]
} else if(thisDay.getYear() == baseDate.getYear() && thisDay.getMonth() == baseDate.getMonth() && thisDay.getDate() < i) {
data['series'][0].push(NaN)
} else {
data['series'][0].push(0)
}
}
// Get formatted date
baseDate.setDate(i)
var dateCheck = toFormattedDate(baseDate)
// Update the text value
\$('#server-data-label-' + server_id).text(\$('#chart-selector :selected').text())
\$('#server-data-value-' + server_id).text(filesize(totalThisMonth, {round: 1}))
// Add data if we have it
if(dateCheck in serverData[server_id]) {
data['series'][0].push(serverData[server_id][dateCheck])
largestVal = Math.max(largestVal, serverData[server_id][dateCheck])
} else if(thisDay.getYear() == baseDate.getYear() && thisDay.getMonth() == baseDate.getMonth() && thisDay.getDate() < i) {
data['series'][0].push(NaN)
} else {
data['series'][0].push(0)
}
}
// Check if we should shrink the Y-axis values
var devideBy = 1024
var axisLabel = 'KB'
if(largestVal > 1024*1024) {
devideBy = 1024*1024
axisLabel = 'MB'
}
if(largestVal > 1024*1024*1024) {
devideBy = 1024*1024*1024
axisLabel = 'GB'
}
if(largestVal > 1024*1024*1024*1024) {
devideBy = 1024*1024*1024*1024
axisLabel = 'TB'
}
// Shrink the value
data['series'][0] = data['series'][0].map(function(num) {
return num / devideBy;
// Show the chart
chart = new Chartist.Line('#server-chart-'+server_id, data, chartOptions);
chart.on('created', function(context) {
// Make sure to add this as the first child so it's at the bottom
context.svg.elem('rect', {
x: context.chartRect.x1,
y: context.chartRect.y2-1,
width: context.chartRect.width(),
height: context.chartRect.height()+2,
fill: 'none',
stroke: '#B9B9B9',
'stroke-width': '1px'
}, '', context.svg, true)
\$('#server-chart-'+server_id+' .ct-label.ct-vertical').each(function(index, elmn) {
elmn.innerHTML = filesize(elmn.innerHTML, {round: 1}).replace(' ','')
})
});
})
// Show the chart
chart = new Chartist.Line('#server-chart-'+server_id, data, chartOptions);
chart.on('created', function(context) {
// Make sure to add this as the first child so it's at the bottom
context.svg.elem('rect', {
x: context.chartRect.x1,
y: context.chartRect.y2-1,
width: context.chartRect.width(),
height: context.chartRect.height()+2,
fill: 'none',
stroke: '#B9B9B9',
'stroke-width': '1px'
}, '', context.svg, true)
\$('#server-chart-'+server_id+' .ct-label.ct-vertical').each(function(index, elmn) {
elmn.innerHTML += axisLabel
})
});
}
// Need to mitigate timezone effects!
@@ -389,14 +410,17 @@
/**
Update charts when changed
**/
\$('.chart-selector').on('change', function(elemn) {
showChart(\$(elemn.target).data('id'), \$(elemn.target).val())
\$('#chart-selector').on('change', function(elemn) {
showCharts()
// Lets us leave (needs to be called after the change event)
setTimeout(function() {
formWasSubmitted = true;
formHasChanged = false;
}, 100)
})
// And on page-load
showCharts()
/**
Click events
@@ -407,10 +431,10 @@
}
\$(this).parent().next().toggle();
\$(this).parent().next().next().toggle();
if (\$(this).attr("value") == "$T('showDetails')") {
\$(this).attr("value", "$T('hideDetails')");
if (\$(this).text().indexOf("$T('showDetails')") > 0) {
\$(this).html(\$(this).html().replace("$T('showDetails')", "$T('hideDetails')"));
} else {
\$(this).attr("value", "$T('showDetails')");
\$(this).html(\$(this).html().replace("$T('hideDetails')", "$T('showDetails')"));
}
});

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Sorting"#-->
<!--#set global $help_uri="configuration/2.2/sorting"#-->
<!--#set global $help_uri="configuration/2.3/sorting"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Special"#-->
<!--#set global $help_uri="configuration/2.2/special"#-->
<!--#set global $help_uri="configuration/2.3/special"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Switches"#-->
<!--#set global $help_uri="configuration/2.2/switches"#-->
<!--#set global $help_uri="configuration/2.3/switches"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">

View File

@@ -1023,19 +1023,14 @@ input[type="checkbox"] {
color: black;
}
.Servers .chart-selector {
position: absolute;
display: block;
top: -7px;
left: 50%;
width: 120px;
margin-left: -40px;
min-width: initial;
opacity: 0.8;
.Servers .chart-selector-container {
float: right;
}
.Servers .chart-selector:hover {
opacity: 1;
.Servers .chart-selector-container .glyphicon {
font-size: 1.3em;
padding-right: 4px;
top: 5px;
}
.Servers .ct-grid.ct-vertical:first-of-type {
@@ -1082,6 +1077,12 @@ input[type="checkbox"] {
color: #666;
}
.host-warning {
color: #404040;
margin-left: 7px;
top: 3px;
}
.fileBrowser .glyphicon {
margin-right: 2px;
top: 1px;
@@ -1219,7 +1220,8 @@ input[type="checkbox"] {
margin-bottom: 0;
}
.Servers .server-chart {
.Servers .server-chart,
.Servers .chart-selector-container {
display: none;
}

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,36 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
width="608.000000pt" height="608.000000pt" viewBox="0 0 608.000000 608.000000"
preserveAspectRatio="xMidYMid meet">
<g transform="translate(0.000000,608.000000) scale(0.100000,-0.100000)"
fill="#000000" stroke="none">
<path d="M1295 5818 c-46 -17 -81 -45 -107 -86 l-23 -37 -5 -1160 -5 -1160
-386 -5 -386 -5 -40 -28 c-80 -56 -113 -173 -70 -257 9 -19 91 -113 182 -209
91 -96 165 -177 165 -180 -1 -3 -18 -18 -39 -32 -21 -15 -48 -46 -60 -71 -21
-43 -21 -54 -21 -514 0 -441 1 -472 19 -507 18 -36 18 -38 0 -74 -17 -33 -19
-61 -19 -236 0 -222 6 -245 74 -305 60 -53 76 -54 851 -50 706 3 710 3 751 25
26 13 45 18 51 12 5 -5 32 -17 60 -27 46 -15 77 -44 336 -317 157 -165 300
-309 319 -320 24 -14 51 -20 98 -20 47 0 74 6 98 20 19 11 162 155 319 320
200 211 295 304 321 315 20 8 46 20 56 26 15 9 26 7 55 -10 36 -21 39 -21 781
-21 l745 0 45 25 c24 14 58 45 75 68 l30 44 3 746 2 746 -25 51 c-14 29 -40
63 -60 77 l-35 25 170 179 c94 98 178 195 188 214 41 84 9 202 -71 257 l-40
28 -386 5 -386 5 -5 1162 -5 1161 -30 43 c-16 23 -48 52 -70 63 l-40 21 -1725
2 c-1202 1 -1734 -2 -1755 -9z m3215 -1488 l0 -1080 -284 0 -284 0 -53 -28
c-39 -20 -62 -41 -84 -77 l-30 -48 -3 -199 -4 -198 -736 0 c-703 0 -739 -1
-779 -19 -41 -19 -42 -19 -79 0 -36 18 -64 19 -510 19 l-472 0 -122 128 -122
127 239 5 c258 5 269 8 325 67 61 64 58 -6 58 1243 l0 1140 1470 0 1470 0 0
-1080z m32 -1562 l3 -273 408 -3 407 -2 0 -690 0 -690 -690 0 -690 0 0 965 0
965 280 0 280 0 2 -272z m558 155 c-19 -21 -75 -80 -125 -130 l-90 -93 -67 0
-68 0 0 130 0 130 192 0 192 0 -34 -37z m-3010 -573 l0 -140 -410 0 -410 0 0
-130 0 -130 408 -2 407 -3 0 -415 0 -415 -692 -3 -693 -2 0 145 0 145 410 0
410 0 0 130 0 130 -410 0 -410 0 0 415 0 415 695 0 695 0 0 -140z m1630 -550
l0 -690 -690 0 -690 0 0 420 0 420 410 0 410 0 0 130 0 130 -410 0 -410 0 0
140 0 140 690 0 690 0 0 -690z m-611 -967 c-35 -38 -66 -68 -69 -68 -3 0 -34
30 -69 68 l-63 67 132 0 132 0 -63 -67z"/>
<path d="M4547 2203 c-4 -3 -7 -186 -7 -405 l0 -398 130 0 130 0 0 405 0 405
-123 0 c-68 0 -127 -3 -130 -7z"/>
<path d="M2902 1533 l3 -128 128 -3 127 -3 0 131 0 130 -130 0 -131 0 3 -127z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1,6 @@
/*
2017 Jason Mulligan <jason.mulligan@avoidwork.com>
@version 3.5.11
*/
"use strict";!function(i){function e(i){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=[],d=0,r=void 0,a=void 0,s=void 0,f=void 0,u=void 0,l=void 0,v=void 0,B=void 0,c=void 0,p=void 0,y=void 0,m=void 0,x=void 0,g=void 0;if(isNaN(i))throw new Error("Invalid arguments");return s=!0===e.bits,y=!0===e.unix,a=e.base||2,p=void 0!==e.round?e.round:y?1:2,m=void 0!==e.spacer?e.spacer:y?"":" ",g=e.symbols||e.suffixes||{},x=2===a?e.standard||"jedec":"jedec",c=e.output||"string",u=!0===e.fullform,l=e.fullforms instanceof Array?e.fullforms:[],r=void 0!==e.exponent?e.exponent:-1,B=Number(i),v=B<0,f=a>2?1e3:1024,v&&(B=-B),(-1===r||isNaN(r))&&(r=Math.floor(Math.log(B)/Math.log(f)))<0&&(r=0),r>8&&(r=8),0===B?(n[0]=0,n[1]=y?"":t[x][s?"bits":"bytes"][r]):(d=B/(2===a?Math.pow(2,10*r):Math.pow(1e3,r)),s&&(d*=8)>=f&&r<8&&(d/=f,r++),n[0]=Number(d.toFixed(r>0?p:0)),n[1]=10===a&&1===r?s?"kb":"kB":t[x][s?"bits":"bytes"][r],y&&(n[1]="jedec"===x?n[1].charAt(0):r>0?n[1].replace(/B$/,""):n[1],o.test(n[1])&&(n[0]=Math.floor(n[0]),n[1]=""))),v&&(n[0]=-n[0]),n[1]=g[n[1]]||n[1],"array"===c?n:"exponent"===c?r:"object"===c?{value:n[0],suffix:n[1],symbol:n[1]}:(u&&(n[1]=l[r]?l[r]:b[x][r]+(s?"bit":"byte")+(1===n[0]?"":"s")),n.join(m))}var o=/^(b|B)$/,t={iec:{bits:["b","Kib","Mib","Gib","Tib","Pib","Eib","Zib","Yib"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["b","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},b={iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]};e.partial=function(i){return function(o){return e(o,i)}},"undefined"!=typeof exports?module.exports=e:"function"==typeof define&&define.amd?define(function(){return e}):i.filesize=e}("undefined"!=typeof window?window:global);
//# sourceMappingURL=filesize.min.js.map

View File

@@ -170,6 +170,10 @@
<div class="col-sm-2">$T('category')</div>
<div class="col-sm-10" data-bind="text: historyStatus.category() == '*' ? glitterTranslate.defaultText : historyStatus.category"></div>
</div>
<div class="row" data-bind="visible: historyStatus.password">
<div class="col-sm-2">$T('srv-password')</div>
<div class="col-sm-10" data-bind="text: historyStatus.password"></div>
</div>
<div class="row">
<div class="col-sm-2">$T('msg-path')</div>
<div class="col-sm-10" data-bind="text: historyStatus.storage() == '' ? historyStatus.path : historyStatus.storage"></div>

View File

@@ -18,7 +18,7 @@
<tr>
<td class="table-messages-label">
<span class="label" data-bind="css: 'label-' + css, text: type"></span>
<strong data-bind="text: date, attr: { 'data-timestamp': timestamp }"></strong>
<strong data-bind="text: displayDateTime(timestamp, \$parent.dateFormat(), 'X'), attr: { 'data-timestamp': timestamp }"></strong>
<span class="queue-message-text" data-bind="html: text"></span>
</td>
</tr>

View File

@@ -59,15 +59,9 @@
<div id="feedback-slider-inner">
<p><strong>If anything is not working as expected, or could be improved, let us know!</strong></p>
<p><strong>If you encounter an error, please include the log file (click on <span class="glyphicon glyphicon-wrench"></span> ) when contacting us.</strong></p>
<h4>General</h4>
<span class="glyphicon glyphicon-home"></span> <a href="https://forums.sabnzbd.org/" target="_blank">SABnzbd Forum</a><br />
<span class="glyphicon glyphicon-home"></span> <a href="https://forums.sabnzbd.org/viewforum.php?f=11" target="_blank">SABnzbd Forum</a><br />
<span class="glyphicon glyphicon-plane"></span> <a href="https://github.com/sabnzbd/sabnzbd/" target="_blank">SABnzbd on Github</a><br />
<span class="glyphicon glyphicon-globe"></span> <a href="https://translations.launchpad.net/sabnzbd" target="_blank">Translations of SABnzbd</a><br />
<span class="glyphicon glyphicon-envelope"></span> <a href="mailto:bugs@sabnzbd.org?body=Version:%20$version%20Skin:%20Glitter">Email bugs@sabnzbd.org</a>
<h4>Interface (Glitter)</h4>
<span class="glyphicon glyphicon-home"></span> <a href="https://forums.sabnzbd.org/viewtopic.php?f=5&amp;t=18880" target="_blank">Glitter at SABnzbd Forum</a><br />
<span class="glyphicon glyphicon-envelope"></span> <a href="mailto:safihre@sabnzbd.org?body=Version:%20$version">Email safihre@sabnzbd.org</a>
</div>
</div>
@@ -156,7 +150,9 @@
</div>
<div class="row options-function-box">
<div class="col-sm-6">
<a href="./status/showlog?session=$session" target="_blank" class="btn btn-default"><span class="glyphicon glyphicon-file"></span> $T('link-showLog')</a>
<a href="./status/showlog?session=$session" target="_blank" class="btn btn-default" data-tooltip="true" data-placement="top" title="$T('Glitter-logText')">
<span class="glyphicon glyphicon-file"></span> $T('link-showLog')
</a>
</div>
<div class="col-sm-6">
<div class="input-group" data-tooltip="true" data-placement="top" title="$T('logging')">
@@ -179,7 +175,6 @@
</div>
<div data-bind="foreach: statusInfo.servers">
<div class="options-server-box">
<div class="row">
<div class="col-sm-6">$T('swtag-server')</div>
<div class="col-sm-6">
@@ -656,7 +651,6 @@
<button type="button" class="btn btn-danger" data-bind="click: history.emptyHistory" data-action="history-purgeremove-failed"><span class="glyphicon glyphicon-floppy-remove"></span> $T('purgeFailed-Files')</button><hr />
<button type="button" class="btn btn-danger" data-bind="click: history.emptyHistory" data-action="history-purge-completed"><span class="glyphicon glyphicon-floppy-saved"></span> $T('purgeCompl')</button><hr />
<button type="button" class="btn btn-danger" data-bind="click: history.emptyHistory" data-action="history-purge-page"><span class="glyphicon glyphicon-check"></span> $T('purgePage') <span class="label label-default" data-bind="text: history.historyItems().length"></span></button>
</div>
</div>
</div>

View File

@@ -92,21 +92,21 @@
</a>
</td>
<td class="name">
<div class="row-wrap-text" data-bind="visible: !editingName()">
<span data-bind="text: name, attr: { 'title': name() }"></span>
<div class="row-wrap-text" data-bind="visible: !editingName(), css: { 'direct-unpack-text': direct_unpack }">
<span data-bind="text: name, attr: { 'title': name_title }"></span>
<!-- ko if: password() -->
<small class="queue-item-password">
<span class="glyphicon glyphicon-lock"></span>
<span data-bind="text: password"></span>
</small>
<!-- /ko -->
<div class="name-icons direct-unpack hover-button" data-bind="visible: direct_unpack" title="$T('opt-direct_unpack')">
<span class="glyphicon glyphicon-compressed"></span> <span data-bind="text: direct_unpack"></span>
</div>
</div>
<form data-bind="submit: editingNameSubmit">
<input type="text" data-bind="value: nameForEdit, visible: editingName(), hasfocus: editingName" />
</form>
<div class="name-icons direct-unpack hover-button" data-bind="visible: direct_unpack">
<span class="glyphicon glyphicon-compressed"></span> <span data-bind="text: direct_unpack"></span>
</div>
<div class="name-options" data-bind="visible: !editingName(), css: { disabled: isGrabbing() }">
<a href="#" data-bind="click: \$parent.queue.moveButton" class="hover-button buttonMoveToTop" title="$T('Glitter-top')"><span class="glyphicon glyphicon-chevron-up"></span></a>
<a href="#" data-bind="click: \$parent.queue.moveButton" class="hover-button buttonMoveToBottom" title="$T('Glitter-bottom')"><span class="glyphicon glyphicon-chevron-down"></span></a>
@@ -133,8 +133,8 @@
<label data-bind="visible: parent.isMultiEditing()">
<input type="checkbox" name="multiedit" title="$T('Glitter-multiSelect')" data-bind="click: parent.addMultiEdit, attr: { 'id': 'multiedit_' + id } " />
</label>
<!-- ko if: !isGrabbing() -->
<div class="dropdown" data-bind="visible: !isGrabbing() && !parent.isMultiEditing()">
<!-- ko if: !isGrabbing() -->
<div class="dropdown" data-bind="visible: !parent.isMultiEditing()">
<a href="#" data-toggle="dropdown" data-bind="click: toggleDropdown">
<span class="caret"></span>
</a>
@@ -144,7 +144,7 @@
<span class="glyphicon glyphicon-tag"></span>
<select name="Category" class="form-control" data-bind="options: parent.categoriesList, optionsValue: 'catValue', optionsText: 'catText', value: category, event: { change: changeCat }"></select>
</li>
<!-- ko if: (status() != 'Fetching') -->
<!-- ko if: !isFetchingBlocks -->
<li title="$T('priority')" data-tooltip="true" data-placement="left">
<span class="glyphicon glyphicon-sort-by-attributes-alt"></span>
<select name="Priority" class="form-control" data-bind="options: parent.priorityOptions, optionsValue: 'value', optionsText: 'name', value: priority, event: { change: changePriority }"></select>

View File

@@ -30,6 +30,7 @@
<link rel="apple-touch-icon" sizes="152x152" href="./staticcfg/ico/apple-touch-icon-152x152-precomposed.png" />
<link rel="apple-touch-icon" sizes="180x180" href="./staticcfg/ico/apple-touch-icon-180x180-precomposed.png" />
<link rel="apple-touch-icon" sizes="192x192" href="./staticcfg/ico/android-192x192.png" />
<link rel="mask-icon" href="./staticcfg/ico/safari-pinned-tab.svg" color="#383F45">
<link rel="shortcut icon" type="image/ico" href="./staticcfg/ico/favicon.ico?v=$version" data-bind="attr: { 'href': SABIcon }" />
<link rel="stylesheet" type="text/css" href="./static/bootstrap/css/bootstrap.min.css?v=$version" />
@@ -46,7 +47,7 @@
var sabSpeedHistory = [$bytespersec_list];
var newRelease = "$new_release";
var newReleaseUrl = "$new_rel_url";
var glitterIsBeta = ("$version".search(/Alpa|Beta|x/)) > 0;
var glitterIsBeta = ("$version".search(/[develop|Alpha|Beta|RC]/)) > 0;
var glitterPreLoadQueue = $preload_queue;
var glitterPreLoadHistory = $preload_history;
@@ -63,6 +64,7 @@
glitterTranslate.removeDown = "$T('Glitter-confirmClearDownloads')";
glitterTranslate.removeDow1 = "$T('Glitter-confirmClear1Download')";
glitterTranslate.retryAll = "$T('link-retryAll')?";
glitterTranslate.fetch = "$T('Glitter-fetch')";
glitterTranslate.encrypted = "$T('Glitter-encrypted')";
glitterTranslate.duplicate = "$T('Glitter-duplicate')";
glitterTranslate.tooLarge = "$T('Glitter-tooLarge')";
@@ -85,6 +87,7 @@
glitterTranslate.moreText = "$T('Glitter-more')";
glitterTranslate.status = [];
glitterTranslate.status['DirectUnpack'] = "$T('opt-direct_unpack')";
glitterTranslate.status['Completed'] = "$T('post-Completed')";
glitterTranslate.status['Failed'] = "$T('post-Failed')";
glitterTranslate.status['Queued'] = "$T('post-Queued')";

View File

@@ -128,13 +128,13 @@ function displayDateTime(inDate, outFormat, inFormat) {
if(inDate == '') {
var theMoment = moment()
} else {
var theMoment = moment(inDate, inFormat)
var theMoment = moment.utc(inDate, inFormat)
}
// Special format or regular format?
if(outFormat == 'fromNow') {
return theMoment.fromNow()
} else {
return theMoment.format(outFormat)
return theMoment.local().format(outFormat)
}
}

View File

@@ -536,6 +536,7 @@ function ViewModel() {
callAPI({
mode: 'warnings'
}).then(function(response) {
// Reset it all
self.allWarnings.removeAll();
if(response) {
@@ -544,20 +545,16 @@ function ViewModel() {
// Go over all warnings and add
$.each(response.warnings, function(index, warning) {
// Split warning into parts
var warningSplit = convertHTMLtoText(warning).split(/\n/);
// Reformat CSS label and date
// Replaces spaces by non-breakable spaces and newlines with br's
var warningData = {
index: index,
type: glitterTranslate.status[warningSplit[1]].slice(0, -1),
text: warningSplit.slice(2).join('<br/>').replace(/ /g, '\u00A0'), // Recombine if multiple lines
date: displayDateTime(warningSplit[0], self.dateFormat(), 'YYYY-MM-DD HH:mm'),
timestamp: moment(warningSplit[0], 'YYYY-MM-DD HH:mm').unix(),
css: (warningSplit[1] == "ERROR" ? "danger" : warningSplit[1] == "WARNING" ? "warning" : "info"),
type: glitterTranslate.status[warning.type].slice(0, -1),
text: convertHTMLtoText(warning.text).replace(/ /g, '\u00A0').replace(/(?:\r\n|\r|\n)/g, '<br />'),
timestamp: warning.time,
css: (warning.type == "ERROR" ? "danger" : warning.type == "WARNING" ? "warning" : "info"),
clear: self.clearWarnings
};
self.allWarnings.push(warningData)
})
}
@@ -788,15 +785,28 @@ function ViewModel() {
}
// Update the servers
if(self.statusInfo.servers().length == 0) {
if(self.statusInfo.servers().length != data.status.servers.length) {
// Only now we can subscribe to the log-level-changes! (only at start)
if(self.statusInfo.servers().length == 0) {
self.statusInfo.loglevel.subscribe(function(newValue) {
// Update log-level
callSpecialAPI('./status/change_loglevel/', {
loglevel: newValue
});
})
}
// Empty them, in case of update
self.statusInfo.servers([])
// Initial add
$.each(data.status.servers, function() {
self.statusInfo.servers.push({
'servername': this.servername,
'serveroptional': this.serveroptional,
'serverpriority': this.serverpriority,
'servertotalconn': this.servertotalconn,
'serverssl': this.serverssl,
'servername': ko.observable(this.servername),
'serveroptional': ko.observable(this.serveroptional),
'serverpriority': ko.observable(this.serverpriority),
'servertotalconn': ko.observable(this.servertotalconn),
'serverssl': ko.observable(this.serverssl),
'serversslinfo': ko.observable(this.serversslinfo),
'serveractiveconn': ko.observable(this.serveractiveconn),
'servererror': ko.observable(this.servererror),
@@ -804,23 +814,20 @@ function ViewModel() {
'serverconnections': ko.observableArray(this.serverconnections)
})
})
// Only now we can subscribe to the log-level-changes!
self.statusInfo.loglevel.subscribe(function(newValue) {
// Update log-level
callSpecialAPI('./status/change_loglevel/', {
loglevel: newValue
});
})
} else {
// Update
$.each(data.status.servers, function(index) {
var activeServer = self.statusInfo.servers()[index];
activeServer.serveractiveconn(this.serveractiveconn)
activeServer.servererror(this.servererror)
activeServer.serveractive(this.serveractive)
activeServer.servername(this.servername),
activeServer.serveroptional(this.serveroptional),
activeServer.serverpriority(this.serverpriority),
activeServer.servertotalconn(this.servertotalconn),
activeServer.serverssl(this.serverssl),
activeServer.serversslinfo(this.serversslinfo),
activeServer.serveractiveconn(this.serveractiveconn),
activeServer.servererror(this.servererror),
activeServer.serveractive(this.serveractive),
activeServer.serverconnections(this.serverconnections)
activeServer.serversslinfo(this.serversslinfo)
})
}

View File

@@ -479,6 +479,7 @@ function QueueModel(parent, data) {
self.index = ko.observable(data.index);
self.status = ko.observable(data.status);
self.isGrabbing = ko.observable(data.status == 'Grabbing' || data.avg_age == '-')
self.isFetchingBlocks = data.status == 'Fetching' || data.priority == 'Repair' // No need to update
self.totalMB = ko.observable(parseFloat(data.mb));
self.remainingMB = ko.observable(parseFloat(data.mbleft))
self.missingMB = ko.observable(parseFloat(data.mbmissing))
@@ -521,7 +522,14 @@ function QueueModel(parent, data) {
})
// Texts
self.missingText= ko.pureComputed(function() {
self.name_title = ko.pureComputed(function() {
// When hovering over the job
if(self.direct_unpack()) {
return self.name() + ' - ' + glitterTranslate.status['DirectUnpack'] + ': ' + self.direct_unpack()
}
return self.name()
})
self.missingText = ko.pureComputed(function() {
// Check for missing data, the value is arbitrary! (1%)
if(self.missingMB()/self.totalMB() > 0.01) {
return self.missingMB().toFixed(0) + ' MB ' + glitterTranslate.misingArt
@@ -533,6 +541,10 @@ function QueueModel(parent, data) {
if(self.status() == 'Checking') {
return glitterTranslate.checking
}
// Grabbing
if(self.status() == 'Grabbing') {
return glitterTranslate.fetch
}
// Pausing status
if((self.parent.parent.downloadsPaused() && self.priority() != 2) || self.pausedStatus()) {
return glitterTranslate.paused;
@@ -688,7 +700,7 @@ function QueueModel(parent, data) {
}
self.changePriority = function(item, event) {
// Not if we are fetching extra blocks for repair!
if(item.status() == 'Fetching') return
if(item.isFetchingBlocks) return
callAPI({
mode: 'queue',
name: 'priority',

View File

@@ -184,6 +184,7 @@ td.name .name-icons span,
.navbar-nav .open .dropdown-menu>li>a,
.dropdown-header,
#modal-help small,
.hover-button.glyphicon-forward,
pre {
color: #EBEBEB !important;
opacity: 1 !important;

View File

@@ -360,7 +360,7 @@ li.dropdown {
#feedback-slider:hover {
left: 0px;
height: 340px;
height: 200px;
opacity: 1;
}
@@ -404,7 +404,6 @@ thead {
tr th {
border-bottom: none !important;
visibility: hidden;
padding: 0px !important;
height: 0px;
}
@@ -634,9 +633,17 @@ td.name .row-wrap-text {
margin-left: 3px;
}
.queue-table td.name .direct-unpack-text {
max-width: calc(100% - 75px);
}
.queue-table td.name:hover .row-wrap-text {
max-width: calc(100% - 125px);
/* Change for each size! */
/* Change for each size! */
}
.queue-table td.name:hover .direct-unpack {
display: none;
}
.queue-table td.name:hover .name-options {
@@ -765,8 +772,8 @@ tr.queue-item>td:first-child>a {
line-height: 24px;
overflow: visible;
margin-bottom: 0;
box-shadow: inset 0 0px 1px rgba(0, 0, 0, 0.3);
-webkit-box-shadow: inset 0 0px 1px rgba(0, 0, 0, 0.3);
box-shadow: inset 0 0px 2px rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 0px 2px rgba(0, 0, 0, 0.2);
}
.progress>span,
@@ -1860,7 +1867,6 @@ input[name="nzbURL"] {
td.name .name-icons {
margin-left: 0px;
margin-right: -5px;
display: block;
}
td.name .row-wrap-text {
@@ -1888,7 +1894,6 @@ input[name="nzbURL"] {
.history-queue-swicher .nav-tabs>li>a {
border-bottom: inherit;
}
}
@media screen and (min-width: 768px) {
@@ -1900,7 +1905,6 @@ input[name="nzbURL"] {
min-width: 715px;
}
.queue .sortable-placeholder td {
padding: 9px 0px 8px !important;
}

View File

@@ -141,8 +141,12 @@ tr.queue-item>td:first-child>a {
margin-top: 3px;
}
.queue-table td.name .direct-unpack {
display: none;
}
.queue-table td.name .name-options {
display: block;
display: inline-block;
}
.queue-table td.name .name-options small {

View File

@@ -28,6 +28,7 @@
<link rel="apple-touch-icon" sizes="152x152" href="${path}staticcfg/ico/apple-touch-icon-152x152-precomposed.png" />
<link rel="apple-touch-icon" sizes="180x180" href="${path}staticcfg/ico/apple-touch-icon-180x180-precomposed.png" />
<link rel="apple-touch-icon" sizes="192x192" href="${path}staticcfg/ico/android-192x192.png" />
<link rel="mask-icon" href="${path}staticcfg/ico/safari-pinned-tab.svg" color="#383F45">
<script type="text/javascript" src="${path}static/javascripts/lib.js?$version"></script>
@@ -99,9 +100,8 @@
#if $loadavg#$T('ft-sysload'):&nbsp;<span id="loadavg">$loadavg</span>#end if#
</div>
<div id="nav_text_left">
<span id="warning_box"><b><a href="${path}status/#tabs-warnings" id="last_warning" title="#echo $last_warning.replace("\n"," ").replace('"',"'") #"><span id="have_warnings">$have_warnings</span> $T('warnings')</a></b></span>
<span id="warning_box"><b><a href="${path}status/#tabs-warnings" id="last_warning"><span id="have_warnings">$have_warnings</span> $T('warnings')</a></b></span>
#if $pane=="Main"#
&sdot; <a href="${path}config/general#web_dir">#echo $T('useGlitter').split('.')[0]#.</a>
#if $new_release#&sdot; <a href="$new_rel_url" id="new_release" target="_blank">$T('Plush-updateAvailable').replace(' ','&nbsp;')</a>#end if#
#end if#
</div>

View File

@@ -6,7 +6,7 @@
$.plush.queuenoofslots = $noofslots;
$.plush.SetQueueSpeedLimit('$speedlimit', '$speedlimit_abs');
$.plush.SetQueueFinishAction('$finishaction');
$.plush.SetWarnings($have_warnings,"<!--#echo $last_warning.replace("\n"," ").replace('"',"'").replace('\\','\\\\') #-->");
$.plush.SetWarnings($have_warnings,"");
$.plush.SetQueuePauseInfo(<!--#if $paused#-->true<!--#else#-->false<!--#end if#-->,'$pause_int');
$.plush.SetQueueETAStats("<!--#if float($kbpersec) > 1023 #-->$speed<!--#else#--><!--#echo "%.0f" % float($kbpersec)#--> K<!--#end if#-->",<!--#echo "%.0f" % float($kbpersec)#-->,'$timeleft','$T('eta'): $eta');

View File

@@ -146,7 +146,7 @@ jQuery(function($){
$("#plush_options").colorbox({ inline:true, href:"#plush_options_modal", title:$("#plush_options").text(),
innerWidth:"375px", innerHeight:"350px", initialWidth:"375px", initialHeight:"350px", speed:0, opacity:0.7
});
// Save the type of speedlimit display
$('#maxSpeed-label').change(function() {
$.plush.speedLimitType = $(this).val();
@@ -159,19 +159,19 @@ jQuery(function($){
$('#maxSpeed-label').val($.plush.speedLimitType)
// Max Speed main menu input -- don't change value on refresh when focused
$("#maxSpeed-option").focus(function(){
$.plush.focusedOnSpeedChanger = true;
}).blur(function(){
$.plush.focusedOnSpeedChanger = false;
$("#maxSpeed-option").focus(function(){
$.plush.focusedOnSpeedChanger = true;
}).blur(function(){
$.plush.focusedOnSpeedChanger = false;
}).keyup(function (e) {
// Catch the enter
if (e.keyCode == 13) {
$("#maxSpeed-enable").click()
}
})
// Submit the new speedlimit
$("#maxSpeed-enable, #maxSpeed-disable").click( function(e) {
$("#maxSpeed-enable, #maxSpeed-disable").click( function(e) {
// Remove
if ($(e.target).attr('id')=="maxSpeed-disable") {
$('#maxSpeed-option').val('');
@@ -496,7 +496,7 @@ jQuery(function($){
};
// static-element tooltips
$('body').delegate('#pausefor_title, #last_warning, #time-left, #multi_delete, #explain-blockRefresh, #pause_resume, #hist_purge, #queueTable td.download-title a, #queueTable td.eta span, #queueTable td.options .icon_nzb_remove, #historyTable td.options .icon_nzb_remove, #historyTable td div.icon_history_verbose', 'mouseover mouseout mousemove', function(event) {
$('body').delegate('#pausefor_title, #time-left, #multi_delete, #explain-blockRefresh, #pause_resume, #hist_purge, #queueTable td.download-title a, #queueTable td.eta span, #queueTable td.options .icon_nzb_remove, #historyTable td.options .icon_nzb_remove, #historyTable td div.icon_history_verbose', 'mouseover mouseout mousemove', function(event) {
var link = this,
$link = $(this);
@@ -1095,7 +1095,7 @@ $("a","#multiops_inputs").click(function(e){
title:function(){return $(this).text().replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;");},
innerWidth:"80%", innerHeight:"300px", initialWidth:"80%", initialHeight:"300px", speed:0, opacity:0.7 });
// modal for reporting issues
// modal for reporting issues
$("#historyTable .modal-report").colorbox({ inline:true,
href: function(){return "#report-"+$(this).parent().parent().parent().attr('id');},
title:function(){return $(this).text();},
@@ -1252,7 +1252,7 @@ $.plush.histprevslots = $.plush.histnoofslots; // for the next refresh
$('#queue-pagination span').removeClass('loading'); // Remove spinner graphic from pagination
$('#manual_refresh_wrapper').removeClass('refreshing'); // Refresh state notification
},
error: function(xhr){
error: function(xhr){
// Only reason for a 404 error could be a login failure -> redirect
if(xhr.status == 404) {
document.location=document.location;
@@ -1320,7 +1320,7 @@ $.plush.histprevslots = $.plush.histnoofslots; // for the next refresh
$('#history .avg_rate').rateit({readonly: true, resetable: false, step: 0.5});
$('#history .avg_rate').each(function() { $(this).rateit('value', $(this).attr('value') / 2); });
$('#history .user_combo option').filter(function() {
return $(this).attr('value') == $(this).parent().parent().find('input.user_combo').attr('value');
return $(this).attr('value') == $(this).parent().parent().find('input.user_combo').attr('value');
}).attr('selected', true);
$('#history-pagination span').removeClass('loading'); // Remove spinner graphic from pagination
}
@@ -1342,11 +1342,11 @@ $.plush.histprevslots = $.plush.histnoofslots; // for the next refresh
// For switching using the select
if(!speedLimit) speedLimit = $.plush.speedLimit;
if(speedLimitAbs == undefined) speedLimitAbs = $.plush.speedLimitAbs;
// Save
// Save
$.plush.speedLimit = speedLimit;
$.plush.speedLimitAbs = speedLimitAbs;
// How do we format?
switch($.plush.speedLimitType) {
case '%':
@@ -1360,11 +1360,11 @@ $.plush.histprevslots = $.plush.histnoofslots; // for the next refresh
speedlimitDisplay = speedLimitAbs/1024/1024;
break;
}
// In case nothing and we make the displaying of the float more pretty
speedlimitDisplay = (isNaN(speedlimitDisplay) || speedlimitDisplay == '0') ? '' : speedlimitDisplay;
speedlimitDisplay = Math.round(speedlimitDisplay*10)/10;
// Update
if ($("#maxSpeed-option").val() != speedlimitDisplay && !$.plush.focusedOnSpeedChanger)
$("#maxSpeed-option").val(speedlimitDisplay);

View File

@@ -109,6 +109,11 @@ body {
font-weight: bold;
}
#new_release {
color: green;
font-weight: bold;
}
#livetip {
position: absolute;
background-color: #cfc;
@@ -338,7 +343,6 @@ body {
clear:left;
padding: 0 20px 0 25px;
font-size:90%;
font-weight: bold;
}
#nav_text_left a, #nav_text_right a {
color:#000;
@@ -1079,7 +1083,7 @@ tr:hover .history_added { color: black; }
color: red;
margin-left: 10px;
}
.rating_icon_vision {
width: 16px;
height: 16px;

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 729 B

After

Width:  |  Height:  |  Size: 726 B

View File

@@ -1,7 +1,7 @@
<!--#set global $pane="Status"#-->
<!--#set global $help_uri="GUI+Status-0-7"#-->
<!--#include $webdir + "/_inc_header.tmpl"#-->
<!--#import datetime#-->
<div class="tabs">
<ul>
<li><a href="#tabs-warnings">$T('lastWarnings')</a></li>
@@ -33,7 +33,11 @@
<!--#for $warn in $warnings#-->
<!--#set $odd = not $odd#-->
<tr class="<!--#if $odd then "odd" else "even"#-->">
<td>$warn.replace("\n","</td><td>", 2)</td></tr>
<!--#set when = datetime.datetime.fromtimestamp($warn.time) #-->
<td>$when</td>
<td>$warn.type</td>
<td>$warn.text</td>
</tr>
<!--#end for#-->
</table>
<!--#else#-->

View File

@@ -20,6 +20,7 @@
<link rel="apple-touch-icon" sizes="152x152" href="./staticcfg/ico/apple-touch-icon-152x152-precomposed.png" />
<link rel="apple-touch-icon" sizes="180x180" href="./staticcfg/ico/apple-touch-icon-180x180-precomposed.png" />
<link rel="apple-touch-icon" sizes="192x192" href="./staticcfg/ico/android-192x192.png" />
<link rel="mask-icon" href="./staticcfg/ico/safari-pinned-tab.svg" color="#383F45">
<script type="text/javascript" src="static/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="static/PlotKit/PlotKit.js"></script>

View File

@@ -1,3 +1,4 @@
<!--#import datetime#-->
<script type="text/javascript">
window.onload = function() {
location = "../#/status"
@@ -36,7 +37,10 @@ $T('logging'):
<!--#if $warnings#-->
<h2>$T('lastWarnings') (<a class="config" onClick="lr('status/clearwarnings','', '-1', this.parentNode.id);">$T('clearWarnings')</a>)</h2>
<!--#for $warn in $warnings#-->
$warn<br/>
<!--#set when = datetime.datetime.fromtimestamp($warn.time) #-->
$when<br>
$warn.type<br>
$warn.text<br>
<!--#end for#-->
<!--#end if#-->

View File

@@ -16,6 +16,10 @@
<input type="radio" name="lang" id="$l" value="$l" <!--#if $lang == $l then 'checked="checked"' else ''#--> />
</label>
<!--#end for#-->
<!--#if not $languages#-->
<hr>
No language files detected. Please run <code>python tools/make_mo.py</code> once and restart SABnzbd, or contact your package provider.
<!--#end if#-->
<div class="spacer"></div>
</div>
</div>

View File

@@ -5,14 +5,14 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-2.3.0-develop\n"
"Project-Id-Version: SABnzbd-2.4.0-develop\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: shypike@sabnzbd.org\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=ASCII\n"
"Content-Transfer-Encoding: 7bit\n"
"POT-Creation-Date: 2017-09-04 13:27+W. Europe Daylight Time\n"
"POT-Creation-Date: 2017-11-17 22:23+W. Europe Standard Time\n"
"Generated-By: pygettext.py 1.5\n"
@@ -212,15 +212,6 @@ msgstr ""
msgid "&nbsp;Resolving address"
msgstr ""
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr ""
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr ""
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr ""
@@ -381,10 +372,6 @@ msgstr ""
msgid "SQL Command Failed, see log"
msgstr ""
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr ""
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr ""
@@ -401,10 +388,6 @@ msgstr ""
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr ""
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr ""
@@ -551,6 +534,12 @@ msgstr ""
msgid "Email succeeded"
msgstr ""
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr ""
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr ""
@@ -621,7 +610,7 @@ msgstr ""
msgid "Authentication missing, please enter username/password from Config->General into your 3rd party program:"
msgstr ""
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid "Try our new skin Glitter! Fresh new design that is optimized for desktop and mobile devices. Go to Config -> General to change your skin."
msgstr ""
@@ -685,10 +674,18 @@ msgstr ""
msgid "Incorrect parameter"
msgstr ""
#: sabnzbd/interface.py
msgid "Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr ""
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -737,6 +734,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -912,6 +913,7 @@ msgstr ""
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -937,10 +939,6 @@ msgstr ""
msgid "[%s] Verified in %s, repair is required"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
msgstr ""
@@ -983,12 +981,12 @@ msgid "Verifying"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Checking extra files"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
msgstr ""
#: sabnzbd/newsunpack.py [Error message]
@@ -1047,11 +1045,6 @@ msgstr ""
msgid "Not available"
msgstr ""
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr ""
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr ""
@@ -1060,7 +1053,7 @@ msgstr ""
msgid "Bad response from Pushover (%s): %s"
msgstr ""
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr ""
@@ -1397,7 +1390,7 @@ msgstr ""
msgid "Unable to bind to port %s on %s. Some other software uses the port or SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr ""
@@ -1417,6 +1410,10 @@ msgstr ""
msgid "Completed Download Folder %s is on FAT file system, limiting maximum file size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid "Module subprocessww missing. Expect problems with Unicoded file and directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1445,10 +1442,6 @@ msgstr ""
msgid "Failed to move files"
msgstr ""
#: sabnzbd/postproc.py
msgid "Running script"
msgstr ""
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr ""
@@ -1469,7 +1462,7 @@ msgstr ""
msgid "Post Processing Failed for %s (%s)"
msgstr ""
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr ""
@@ -2601,6 +2594,10 @@ msgstr ""
msgid "Optional authentication password."
msgstr ""
#: sabnzbd/skintext.py
msgid "If the SABnzbd Host or Port is exposed to the internet, your current settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3249,7 +3246,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr ""
@@ -3705,6 +3702,22 @@ msgstr ""
msgid "Device(s) to which message should be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr ""
@@ -4101,6 +4114,14 @@ msgstr ""
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr ""
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr ""
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr ""
@@ -4265,6 +4286,10 @@ msgstr ""
msgid "Refresh"
msgstr ""
#: sabnzbd/skintext.py
msgid "All usernames, passwords and API-keys are automatically removed from the log and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr ""
@@ -4409,10 +4434,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr ""
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr ""
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr ""

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"PO-Revision-Date: 2017-06-22 07:07+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-10-27 21:53+0000\n"
"Last-Translator: Søren <Unknown>\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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:47+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -29,11 +29,14 @@ msgstr "Kan ikke finde webskabeloner: %s, forsøger med standardskabelon"
msgid ""
"SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
msgstr ""
"SABYenc deaktiveret: Der blev ikke fundet nogen korrekt version (Fandt v%s, "
"forventede v%s)"
#: SABnzbd.py [Warning message]
msgid ""
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
msgstr ""
"SABYenc modul... IKKE fundet! Forventede v%s - https://sabnzbd.org/sabyenc"
#: SABnzbd.py [Error message]
msgid "_yenc module... NOT found!"
@@ -45,11 +48,11 @@ msgstr "par2 binær... IKKE fundet!"
#: SABnzbd.py [Error message] # SABnzbd.py [Error message]
msgid "Verification and repair will not be possible."
msgstr ""
msgstr "Verificering og reperation er ikke muligt."
#: SABnzbd.py [Error message]
msgid "MultiPar binary... NOT found!"
msgstr ""
msgstr "MultiPar binær... IKKE fundet!"
#: SABnzbd.py [Warning message]
msgid "Your UNRAR version is %s, we recommend version %s or higher.<br />"
@@ -57,7 +60,7 @@ msgstr "Din Unrar version er %s, vi anbefaler version %s eller højere.<br />"
#: SABnzbd.py [Error message]
msgid "Downloads will not unpacked."
msgstr ""
msgstr "Downloads vil ikke blive udpakket."
#: SABnzbd.py [Error message]
msgid "unrar binary... NOT found"
@@ -226,15 +229,6 @@ msgstr "Afprøv notifikation"
msgid "&nbsp;Resolving address"
msgstr "&nbsp; Server løsning"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEJL:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ADVARSEL:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ingen"
@@ -407,10 +401,6 @@ msgstr "Beskadigede historik database, skabte tom udskiftning"
msgid "SQL Command Failed, see log"
msgstr "SQL Kommando mislykkedes, se logg"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL Commit mislykkedes, se logg"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Det lykkedes ikke at lukke databasen, se logg"
@@ -427,10 +417,6 @@ msgstr "Afkodning af %s mislykkedes"
msgid "Decoder failure: Out of memory"
msgstr "Dekoder fejl: Ikke mere hukommelse"
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC Fejl i %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Forkert udformet yEnc artikel i %s"
@@ -581,6 +567,12 @@ msgstr "Det lykkedes ikke at lukke e-mail tilslutning"
msgid "Email succeeded"
msgstr "E-mail afsendelse mislykkedes"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Kan ikke sende, mangler nødvendige data"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Kan ikke finde e-mail skabeloner i %s"
@@ -673,7 +665,7 @@ msgstr ""
"Brugeroplysninger mangler, indtast brugernavn / password fra Konfiguration-> "
"Generelt i dit tredjepartsprogram:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -748,10 +740,19 @@ msgstr "Udefineret server"
msgid "Incorrect parameter"
msgstr "Fejl parameter"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Tilbage"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEJL:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -802,6 +803,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Det lykkedes ikke at ændre rettigheder på %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Køre script"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -977,6 +982,7 @@ msgstr "Starter reparation"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Par verificering mislykkedes på %s, mens QuickCheck lykkedes"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1005,10 +1011,6 @@ msgstr "[%s] Bekræftelse i %s, alle filer er ok"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Bekræftelse i %s, kræver reparation"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Hovedarkiv mangler..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1051,6 +1053,10 @@ msgstr "Disk fuld"
msgid "Verifying"
msgstr "Bekræfter"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1114,11 +1120,6 @@ msgstr "Andre beskeder"
msgid "Not available"
msgstr "Ikke tilgængelig"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Kan ikke sende, mangler nødvendige data"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Kunne ikke sende Prowl besked"
@@ -1127,7 +1128,7 @@ msgstr "Kunne ikke sende Prowl besked"
msgid "Bad response from Pushover (%s): %s"
msgstr "Dårlig respons fra pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Det lykkedes ikke at sende pushover besked"
@@ -1498,7 +1499,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Alvorlig fejl"
@@ -1520,6 +1521,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "Overførslen kan mislykkes, kun %s af det krævede %s tilgængelig"
@@ -1548,10 +1555,6 @@ msgstr "Det lykkedes ikke at omdøbe \"%s\" til \"%s\""
msgid "Failed to move files"
msgstr "Kunne ikke flytte filer"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Køre script"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Kør bruger script %s"
@@ -1572,7 +1575,7 @@ msgstr "Mere"
msgid "Post Processing Failed for %s (%s)"
msgstr "Efterbehandling mislykkedes for %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "se logfil"
@@ -2739,6 +2742,12 @@ msgstr "SABnzbd password"
msgid "Optional authentication password."
msgstr "Valgfrit password."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr "Sikkerhed"
@@ -3493,7 +3502,7 @@ msgstr "SSL-chifre"
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr "Øge ydeevnen ved at tvinge en lavere SSL-kryptering styrke."
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Maksimalt antal forsøg"
@@ -3970,6 +3979,22 @@ msgstr "Enhed(er)"
msgid "Device(s) to which message should be sent"
msgstr "Enhed(er) som meddelelse skal sendes til"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4385,6 +4410,14 @@ msgstr "Mistet forbindelsen til SABnzbd.."
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr "I tilfælde af SABnzbd genstart vil denne skærm forsvinde automatisk!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ADVARSEL:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Hent"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Opdateringsfrekvens"
@@ -4553,6 +4586,12 @@ msgstr "Pause i..."
msgid "Refresh"
msgstr "Opdatere"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sortere efter alder <small>Ældst&rarr;Nyeste</small>"
@@ -4701,10 +4740,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Bloker genopfriskninger ved at hænge over"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Hent"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Upload"
@@ -4969,6 +5004,12 @@ msgstr "URL hentning mislykkedes; %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Mappen \"%s\" findes ikke"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL Commit mislykkedes, se logg"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC Fejl i %s (%s -> %s)"
#~ msgid "Error: No secondary interface defined."
#~ msgstr "Fejl: Ingen sekundær bruger grænseflade defineret."
@@ -5024,6 +5065,9 @@ msgstr "URL hentning mislykkedes; %s"
#~ msgid "Unpacking failed, an expected file was not unpacked"
#~ msgstr "Udpakning mislykkedes, en ventet fil er ikke udpakket"
#~ msgid "Main packet not found..."
#~ msgstr "Hovedarkiv mangler..."
#~ msgid "Error importing OpenSSL module. Connecting with NON-SSL"
#~ msgstr "Mislykkedes med importering af OpenSSL modul. Tilslutter uden SSL"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"PO-Revision-Date: 2017-08-24 15:39+0000\n"
"Last-Translator: jcfp <Unknown>\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-10-10 19:03+0000\n"
"Last-Translator: Robin Munkittrick <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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "MultiPar binary... NOT found!"
@@ -237,15 +237,6 @@ msgstr "Benachrichtigungen testen"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Adresse wird aufgelöst …"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEHLER:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "WARNUNG:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Nichts"
@@ -425,10 +416,6 @@ msgstr "Verlaufsdatenbank geschädigt, eine leere neue wurde erstellt"
msgid "SQL Command Failed, see log"
msgstr "SQL-Befehl fehlgeschlagen. Beachten Sie das Nachrichtenprotokoll."
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL-Commit fehlgeschlagen. Beachten Sie das Nachrichtenprotokoll."
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr ""
@@ -446,10 +433,6 @@ msgstr "Fehler beim Dekodieren von %s."
msgid "Decoder failure: Out of memory"
msgstr "Decoder Fehler: Nicht genügend Speicher"
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC-Fehler in %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Ungültiger yEnc-Artikel in %s"
@@ -603,6 +586,12 @@ msgstr "Schliessen der Mail-Verbindung fehlgeschlagen"
msgid "Email succeeded"
msgstr "E-Mail erfolgreich versendet"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Absenden nicht möglich, benötigte Daten fehlen"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "In %s konnten keine E-Mail-Vorlagen gefunden werden"
@@ -698,7 +687,7 @@ msgstr ""
"Authentifizierung fehlt. Bitte Benutzernamen und Passwort aus Einstellungen-"
">Allgemein in die externe Anwendung eingeben:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -772,10 +761,19 @@ msgstr "Undefinierter Server!"
msgid "Incorrect parameter"
msgstr "Fehlerhafter Parameter"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Zurück"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEHLER:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -829,6 +827,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Rechte von %s konnten nicht geändert werden"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Ausführen des Skripts"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -1008,6 +1010,7 @@ msgstr ""
"Par-Verifikation für \"%s\" fehlgeschlagen, obwohl der QuickCheck "
"erfolgreich war"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1036,10 +1039,6 @@ msgstr "[%s] Überprüft in %s. Alle Dateien fehlerfrei."
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Überprüft in %s. Reparatur wird benötigt."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Hauptpaket nicht gefunden …"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1086,6 +1085,10 @@ msgstr "Festplatte voll"
msgid "Verifying"
msgstr "Überprüfen"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr "Überprüfe zusätzliche Dateien"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1093,7 +1096,7 @@ msgstr "Wird überprüft"
#: sabnzbd/newsunpack.py [Error message]
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Dem Pythonskript \"%s\" fehlen die Ausführenrechte (+x)"
msgstr "Dem Pythonskript \"%s\" fehlen die Ausführungsrechte (+x)"
#: sabnzbd/newswrapper.py
msgid "This server does not allow SSL on this port"
@@ -1152,11 +1155,6 @@ msgstr "Andere Nachrichten"
msgid "Not available"
msgstr "Nicht verfügbar"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Absenden nicht möglich, benötigte Daten fehlen"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Konnte Prowl-Nachricht nicht versenden"
@@ -1165,7 +1163,7 @@ msgstr "Konnte Prowl-Nachricht nicht versenden"
msgid "Bad response from Pushover (%s): %s"
msgstr "Fehlerhafte Antwort von Pushbullet (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Konnte Pushover-Nachricht nicht versenden"
@@ -1550,7 +1548,7 @@ msgstr ""
"Konnte nicht an Port %s auf %s starten. Eine andere Software nutzt diesen "
"Port oder SABnzbd läuft bereits."
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Schwerwiegender Fehler"
@@ -1577,6 +1575,14 @@ msgstr ""
"Download-Ordner %s für abgeschlossene Downloads auf FAT Dateisystem, ist "
"auf maximale Dateigröße von 4GB begrenzt."
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
"Modul subprocessww fehlt. Fehler mit Unikodierter Datei und Verzeichnisnamen "
"in den Downloads sind zu erwarten."
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1606,10 +1612,6 @@ msgstr "Fehler beim Umbenennen von \"%s\" nach \"%s\""
msgid "Failed to move files"
msgstr "Dateien verschieben fehlgeschlagen"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Ausführen des Skripts"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Ausführen des Benutzer-Skripts %s"
@@ -1630,7 +1632,7 @@ msgstr "Mehr"
msgid "Post Processing Failed for %s (%s)"
msgstr "Nachbearbeitung von %s fehlgeschlagen (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "Beachten Sie die Protokolldatei"
@@ -2800,6 +2802,14 @@ msgstr "SABnzbd-Passwort"
msgid "Optional authentication password."
msgstr "Optionale Anmeldung mit Passwort"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
"Wenn der SABnzbd Host oder Port im Netz freigegeben ist, lassen die "
"gegenwärtigen Einstellung vollen zugriff auf die SABnzbd Oberfläche zu."
#: sabnzbd/skintext.py
msgid "Security"
msgstr "Sicherheit"
@@ -3590,7 +3600,7 @@ msgstr ""
"Die Performanz verbessern, indem eine schwächere SSL-Verschlüsselung "
"erzwungen wird."
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Maximale Wiederholungen"
@@ -3871,7 +3881,7 @@ msgstr "Höchstens"
#: sabnzbd/skintext.py [Config->RSS filter-type selection menu "From Season/Episode"]
msgid "From SxxEyy"
msgstr "Von SxxExx"
msgstr "Von SxxEyy"
#: sabnzbd/skintext.py [Config->RSS filter-type selection menu "From Show Season/Episode"]
msgid "From Show SxxEyy"
@@ -4075,6 +4085,22 @@ msgstr "Gerät(e)"
msgid "Device(s) to which message should be sent"
msgstr "Geräte, welche die Nachrichten empfangen sollen"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr "Wie oft die selbe benachrichtigung (in Sekunden) geschickt wird."
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4493,6 +4519,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"Wenn SABnzbd neustartet, wird diese Anzeige automatisch verschwinden!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "WARNUNG:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Abrufen"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Aktualisierungsrate"
@@ -4661,6 +4695,12 @@ msgstr "Anhalten für …"
msgid "Refresh"
msgstr "Neu laden"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sortieren nach Alter <small>Älteste&rarr;Neuste</small>"
@@ -4809,10 +4849,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Aktualisierung durch Mauszeiger verhindern"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Abrufen"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Hochladen"
@@ -5083,6 +5119,12 @@ msgstr "Abrufen der URL fehlgeschlagen; %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Ordner \"%s\" existiert nicht"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL-Commit fehlgeschlagen. Beachten Sie das Nachrichtenprotokoll."
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC-Fehler in %s (%s -> %s)"
#~ msgid "Error: No secondary interface defined."
#~ msgstr "Fehler: Keine sekundäre Oberfläche angegeben."
@@ -5608,6 +5650,9 @@ msgstr "Abrufen der URL fehlgeschlagen; %s"
#~ "Benachrichtigung für Nachrichtengruppen aktivieren (keine, eine oder "
#~ "mehrere)"
#~ msgid "Main packet not found..."
#~ msgstr "Hauptpaket nicht gefunden …"
#~ msgid "Initiating restart...<br />"
#~ msgstr "Neustart wird durchgeführt …<br />"

View File

@@ -117,3 +117,5 @@ msgstr "unrar binary... NOT found!"
msgid "Downloads will not unpacked."
msgstr "Downloads will not be unpacked."
msgid "Seperate multiple URLs by a comma"
msgstr "Separate multiple URLs with a comma"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-06-22 07:07+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>\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-09-03 05:50+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -226,15 +226,6 @@ msgstr "Notificación de prueba"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Resolviendo sitio"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ERROR:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "AVISO:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ninguno"
@@ -408,10 +399,6 @@ msgstr ""
msgid "SQL Command Failed, see log"
msgstr "Comando SQL ha fallado, vea el registro"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "Compromiso SQL ha fallado, vea el registro"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "No se pudo cerrar el base de datos, vea el registro"
@@ -428,10 +415,6 @@ msgstr "Descodificación %s fallo"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "Error CRC en %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Articulo yEnc corrupto en %s"
@@ -583,6 +566,12 @@ msgstr "No se pudo cerrar la conexión de correo"
msgid "Email succeeded"
msgstr "Email exitoso"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "No se ha podido enviar, faltan datos"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "No se pudo encontrar plantillas de email en %s"
@@ -675,7 +664,7 @@ msgstr ""
"Faltaron datos de cuenta, favor ingresar usuario/contraseña desde Config-"
">General en tu aplicacion externa:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -750,10 +739,19 @@ msgstr "¡Servidor no definido!"
msgid "Incorrect parameter"
msgstr "Parámetro incorrecto"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Atrás"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ERROR:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -804,6 +802,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "No se puede cambiar los permisos de %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Ejecutando script"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -983,6 +985,7 @@ msgstr ""
"La verificación PAR ha fallado en %s, ¡aunque el QuickCheck ha sido "
"satisfactorio!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1011,10 +1014,6 @@ msgstr "[%s] Verificado en %s, todos los archivos correctos"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Verificado en %s, se necesita reparar"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Paquete principal no encontrado..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1059,6 +1058,10 @@ msgstr "Disco lleno"
msgid "Verifying"
msgstr "Verificando"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1122,11 +1125,6 @@ msgstr "Otros mensajes"
msgid "Not available"
msgstr "No disponible"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "No se ha podido enviar, faltan datos"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "No se pudo enviar el mensaje de Prowl"
@@ -1135,7 +1133,7 @@ msgstr "No se pudo enviar el mensaje de Prowl"
msgid "Bad response from Pushover (%s): %s"
msgstr "Mala respuesta de Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "No se pudo enviar el mensaje de Pushover"
@@ -1514,7 +1512,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Error grave"
@@ -1537,6 +1535,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "La descarga fallo, solo %s de los %s requeridos estan disponibles"
@@ -1565,10 +1569,6 @@ msgstr "Error al renombrar \"%s\" a \"%s\""
msgid "Failed to move files"
msgstr "Error al mover ficheros"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Ejecutando script"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Ejecutando script de usuario %s"
@@ -1589,7 +1589,7 @@ msgstr "Más"
msgid "Post Processing Failed for %s (%s)"
msgstr "Error al post-procesar %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "ver fichero de log"
@@ -2753,6 +2753,12 @@ msgstr "Contraseña de SABnzbd"
msgid "Optional authentication password."
msgstr "Contraseña opcional"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3515,7 +3521,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Reintentos máximos"
@@ -3997,6 +4003,22 @@ msgstr "Dispositivo(s)"
msgid "Device(s) to which message should be sent"
msgstr "Dispositivo(s) a los que enviar el mensaje"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4409,6 +4431,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"Esta ventana desaparecerá automáticamente una vez SABnzbd se haya reiniciado."
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "AVISO:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Obtener"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Frecuencia de actualización"
@@ -4578,6 +4608,12 @@ msgstr "Pausar durante..."
msgid "Refresh"
msgstr "Actualizar"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Ordenar por Fecha <small>Más viejo&rarr;Más nuevo</small>"
@@ -4726,10 +4762,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Bloquear actualizaciones al pasar por encima"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Obtener"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Subir"
@@ -5008,9 +5040,15 @@ msgstr "Error al recuperar la URL; %s"
#~ msgid "Try again"
#~ msgstr "Inténtelo de nuevo"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "Compromiso SQL ha fallado, vea el registro"
#~ msgid "WARNING: Paused job \"%s\" because of encrypted RAR file"
#~ msgstr "NOTICIA: Transferencia \"%s\" pausado por archivo cifrado"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "Error CRC en %s (%s -> %s)"
#~ msgid "No UNRAR program found, unpacking RAR files is not possible<br />"
#~ msgstr ""
#~ "Programa Unrar no encontrado, descomprimir de archivos RAR no posible<br />"
@@ -5057,6 +5095,9 @@ msgstr "Error al recuperar la URL; %s"
#~ msgid "Missing expected file: %s => unrar error?"
#~ msgstr "Falta el siguiente archivo: %s => ¿Error al descomprimir?"
#~ msgid "Main packet not found..."
#~ msgstr "Paquete principal no encontrado..."
#~ msgid "Invalid par2 files, cannot verify or repair"
#~ msgstr "Ficheros par2 inválidos, no se puede verificar o reparar"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-06-22 07:07+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>\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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -229,15 +229,6 @@ msgstr "Testaa ilmoitusta"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Selvitetään osoitetta"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "VIRHE:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "VAROITUS:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ei mitään"
@@ -407,10 +398,6 @@ msgstr ""
msgid "SQL Command Failed, see log"
msgstr "SQL komento epäonnistui, katso loki"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL muutos epäonnistui, katso loki"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Tietokannan sulkeminen epäonnistui, katso loki"
@@ -427,10 +414,6 @@ msgstr "Kohteen %s dekoodaus epäonnistui"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC virhe tiedostossa %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Huonosti muotoiltu yEnc artikkeli %s"
@@ -580,6 +563,12 @@ msgstr "Sähköpostiyhteyden sulkeminen epäonnistui"
msgid "Email succeeded"
msgstr "Sähköpostitus onnistui"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Ei voida lähettää, vaaditut tiedot ovat puutteelliset"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Sähköpostipohjia ei löydy hakemistosta %s"
@@ -672,7 +661,7 @@ msgstr ""
"Authentikointi puuttuu, ole hyvä ja syötä käyttäjänimi/salasana Asetukset-"
">Yleiset kolmannen osapuolen ohjelmaasi:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -746,10 +735,19 @@ msgstr "Määrittämätön palvelin!"
msgid "Incorrect parameter"
msgstr "Virheellinen parametri"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Takaisin"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "VIRHE:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -800,6 +798,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Käyttöoikeuksien muuttaminen epäonnistui kohteelle %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Ajetaan skripti"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -976,6 +978,7 @@ msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr ""
"Par varmennus epäonnistui kohteessa %s, mutta Pikatarkistus onnistui!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1003,10 +1006,6 @@ msgstr "[%s] Varmennettiin ajassa %s, kaikki tiedostot kelvollisia"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Varmennetiin ajassa %s, vaatii korjauksen"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Pääpakettia ei löydy..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1049,6 +1048,10 @@ msgstr "Levy täynnä"
msgid "Verifying"
msgstr "Varmennetaan"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1112,11 +1115,6 @@ msgstr "Muut viestit"
msgid "Not available"
msgstr "Ei saatavilla"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Ei voida lähettää, vaaditut tiedot ovat puutteelliset"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Prowl viestin lähetys epäonnistui"
@@ -1125,7 +1123,7 @@ msgstr "Prowl viestin lähetys epäonnistui"
msgid "Bad response from Pushover (%s): %s"
msgstr "Virheellinen vastaus Pushoverilta (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Pushover viestin lähetys epäonnistui"
@@ -1502,7 +1500,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Vakava virhe"
@@ -1524,6 +1522,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "Lataaminen saattaa epäonnistua, vain %s osaa %s osasta saatavilla"
@@ -1552,10 +1556,6 @@ msgstr "Virhe uudelleennimettäessä \"%s\" nimelle \"%s\""
msgid "Failed to move files"
msgstr "Tiedostojen siirto epäonnistui"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Ajetaan skripti"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Ajetaan käyttäjän skripti %s"
@@ -1576,7 +1576,7 @@ msgstr "Lisää"
msgid "Post Processing Failed for %s (%s)"
msgstr "Jälkikäsittely epäonnistui kohteelle %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "katso lokitiedosto"
@@ -2741,6 +2741,12 @@ msgstr "SABnzbd salasana"
msgid "Optional authentication password."
msgstr "Vaihtoehtoinen salasana todennukseen."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3504,7 +3510,7 @@ msgstr "SSL-salaus"
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr "Lisää suorituskykyä pakottamalla alhaisempi SSL-suojaustaso."
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Enimmäismäärä uudelleenyrityksille"
@@ -3982,6 +3988,22 @@ msgstr "Laitteet"
msgid "Device(s) to which message should be sent"
msgstr "Laitteet joihin viesti lähetetään"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4400,6 +4422,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"Mikäli SABnzbd käynnistetään uudelleen, tämä ruutu häviää automaattisesti!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "VAROITUS:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Nouda"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Päivitysväli"
@@ -4569,6 +4599,12 @@ msgstr "Keskeytä ajaksi..."
msgid "Refresh"
msgstr "Päivitä"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Järjestä iän mukaan <small>Vanhin&rarr;Uusin</small>"
@@ -4716,10 +4752,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Estä päivitykset kun hiiri on päällä"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Nouda"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Lähetä"
@@ -4982,6 +5014,9 @@ msgstr "NZB tiedostoa ei voida käyttää"
msgid "URL Fetching failed; %s"
msgstr "Osoitteen nouto epäonnistui; %s"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC virhe tiedostossa %s (%s -> %s)"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Kansiota \"%s\" ei ole olemassa"
@@ -5095,6 +5130,12 @@ msgstr "Osoitteen nouto epäonnistui; %s"
#~ msgid "Remain/Total"
#~ msgstr "Jäljellä/Yhteensä"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL muutos epäonnistui, katso loki"
#~ msgid "Main packet not found..."
#~ msgstr "Pääpakettia ei löydy..."
#~ msgid "No UNRAR program found, unpacking RAR files is not possible<br />"
#~ msgstr ""
#~ "UNRAR ohjelmaa ei löydy, RAR-tiedostojen purkaminen ei ole mahdollista<br />"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"PO-Revision-Date: 2017-08-21 19:45+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-11-15 19:29+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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -38,7 +38,7 @@ msgstr ""
msgid ""
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
msgstr ""
"Module SABYenc... NON trouvé! v%s attendue - https://sabnzbd.org/sabyenc"
"Module SABYenc... NON trouvé ! v%s attendue - https://sabnzbd.org/sabyenc"
#: SABnzbd.py [Error message]
msgid "_yenc module... NOT found!"
@@ -238,15 +238,6 @@ msgstr "Test de Notification"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Résolution de l'adresse"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ERREUR:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "AVERTISSEMENT :"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Aucun"
@@ -428,10 +419,6 @@ msgstr ""
msgid "SQL Command Failed, see log"
msgstr "Echec de la commande SQL, voir le journal"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "Echec du commit SQL, voir le journal"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Impossible de fermer la base de données, voir le journal"
@@ -448,10 +435,6 @@ msgstr "Échec du décodage de %s"
msgid "Decoder failure: Out of memory"
msgstr "Échec du décodeur : mémoire insuffisante"
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "Erreur CRC dans %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Article yEnc mal construit dans %s"
@@ -607,6 +590,12 @@ msgstr "Échec de la fermeture de la connexion à la messagerie"
msgid "Email succeeded"
msgstr "L'envoi de l'e-mail a réussi"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Impossible d'envoyer, données requises manquantes"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Impossible de trouver les modèles d'email dans %s"
@@ -701,7 +690,7 @@ msgstr ""
"Authentification manquante, entrez vos identifiant/mot de passe de la "
"configuration générale dans votre application tierce :"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -776,10 +765,21 @@ msgstr "Serveur non défini !"
msgid "Incorrect parameter"
msgstr "Paramètre incorrect"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
"Le dossier de catégorie ne peut pas être un sous-dossier du dossier de "
"téléchargement temporaire."
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Retour"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ERREUR:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -833,6 +833,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Impossible de changer les permissions pour %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Exécution du script"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -1015,6 +1019,7 @@ msgstr ""
"Echec de la vérification Par sur %s, mais QuickCheck (vérification rapide) "
"réussi !"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1044,10 +1049,6 @@ msgstr "[%s] Vérifié dans %s, tous les fichiers sont corrects"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Vérifié dans %s, réparation nécessaire"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Paquet principal introuvable..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1091,6 +1092,10 @@ msgstr "Disque plein"
msgid "Verifying"
msgstr "Vérification en cours"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr "Vérification des fichiers supplémentaires"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1159,11 +1164,6 @@ msgstr "Autres messages"
msgid "Not available"
msgstr "Non disponible"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Impossible d'envoyer, données requises manquantes"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Echec d'envoi du message Prowl"
@@ -1172,7 +1172,7 @@ msgstr "Echec d'envoi du message Prowl"
msgid "Bad response from Pushover (%s): %s"
msgstr "Mauvaise réponse de Pushover (%s) : %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Échec de l'envoi du message Pushover"
@@ -1555,7 +1555,7 @@ msgstr ""
"Impossible de lier le port %s sur %s. Un autre logiciel utilise le port ou "
"SABnzbd est déjà en cours d'exécution."
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Erreur fatale"
@@ -1580,6 +1580,14 @@ msgstr ""
"Le système de fichiers du dossier de téléchargements terminés %s est au "
"format FAT, limitant la taille maximale d'un fichier à 4 Go"
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
"Le module subprocessww est manquant. Attendez-vous à des problèmes avec les "
"noms de fichiers et de répertoires Unicode dans les téléchargements."
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1610,10 +1618,6 @@ msgstr "Erreur lors du renommage de \"%s\" en \"%s\""
msgid "Failed to move files"
msgstr "Impossible de déplacer les fichiers"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Exécution du script"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Exécution du script utilisateur %s"
@@ -1634,7 +1638,7 @@ msgstr "Plus"
msgid "Post Processing Failed for %s (%s)"
msgstr "Échec du post-traitement pour %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "voir le journal"
@@ -2808,6 +2812,14 @@ msgstr "Mot de passe SABnzbd"
msgid "Optional authentication password."
msgstr "Mot de passe pour l'authentification (facultatif)."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
"Vos paramètres actuels permettent un accès externe complet à l'interface "
"SABnzbd si l'hôte ou le port SABnzbd est ouvert vers l'internet."
#: sabnzbd/skintext.py
msgid "Security"
msgstr "Sécurité"
@@ -3597,7 +3609,7 @@ msgstr "Chiffrements SSL"
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr "Augmenter les performances en forçant un cryptage SSL plus faible."
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Nombre de tentatives maximum"
@@ -4086,6 +4098,23 @@ msgstr "Appareil(s)"
msgid "Device(s) to which message should be sent"
msgstr "Appareil(s) auxquels doivent être envoyés les messages"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr "Nouvelle tentative d'urgence"
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr "À quelle fréquence la même notification sera envoyée (en secondes)"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr "Expiration d'urgence"
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
"Tenter à nouveau votre notification pendant combien de temps (en secondes)"
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4506,6 +4535,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"En cas de redémarrage de SABnzbd cet écran disparaîtra automatiquement!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "AVERTISSEMENT :"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Charger"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Taux de rafraîchissement"
@@ -4676,6 +4713,14 @@ msgstr "Mettre en pause pour…"
msgid "Refresh"
msgstr "Rafraîchir"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
"Tous les noms d'utilisateur, mots de passe et clés API sont automatiquement "
"supprimés du journal et de la copie de vos réglages."
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Trier par Age <small>Moins récent&rarr;Plus récent</small>"
@@ -4824,10 +4869,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Bloquer rafraîchissements au survol"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Charger"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Envoyer"
@@ -5093,6 +5134,9 @@ msgstr "Fichier NZB inutilisable"
msgid "URL Fetching failed; %s"
msgstr "Échec de récupération de l'URL ; %s"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "Erreur CRC dans %s (%s -> %s)"
#~ msgid "Error: No secondary interface defined."
#~ msgstr "Erreur : Pas d'interface secondaire définie."
@@ -5451,6 +5495,9 @@ msgstr "Échec de récupération de l'URL ; %s"
#~ msgid "Show files"
#~ msgstr "Afficher les fichiers"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "Echec du commit SQL, voir le journal"
#~ msgid "Downloaded so far"
#~ msgstr "Téléchargé jusqu'à présent"
@@ -5566,6 +5613,9 @@ msgstr "Échec de récupération de l'URL ; %s"
#~ msgid "pyopenssl module missing, please install for https access"
#~ msgstr "module pyopenssl manquant, veuillez l'installer pour l'accès HTTPS"
#~ msgid "Main packet not found..."
#~ msgstr "Paquet principal introuvable..."
#~ msgid ""
#~ "\n"
#~ " SABnzbd needs a free tcp/ip port for its internal web server.<br>\n"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"PO-Revision-Date: 2017-09-01 23:03+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-11-15 20:06+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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -222,15 +222,6 @@ msgstr "בחן התראה"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;פותר כתובת"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "שגיאה:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "אזהרה:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "ללא"
@@ -401,10 +392,6 @@ msgstr "מסד-נתונים היסטוריה פגום, נוצר תחליף רי
msgid "SQL Command Failed, see log"
msgstr "נכשלה, ראה יומן SQL פקודת"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "נכשל, ראה יומן SQL חיוב"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "נכשל בסגירת מסד-נתונים, ראה יומן"
@@ -421,10 +408,6 @@ msgstr "נכשל %s פענוח"
msgid "Decoder failure: Out of memory"
msgstr "כישלון מפענח: אין זיכרון"
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "%s (%s -> %s)-ב CRC שגיאת"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "%s-נוצר באופן גרוע ב yEnc מאמר"
@@ -453,7 +436,7 @@ msgstr "הושלם"
#: sabnzbd/directunpacker.py # sabnzbd/newsunpack.py
msgid "Unpacked %s files/folders in %s"
msgstr "%s-פורקו %s קבצים/תיקיות ב"
msgstr "פורקו %s קבצים/תיקיות תוך %s"
#: sabnzbd/directunpacker.py [Warning message]
msgid "Direct Unpack was automatically enabled."
@@ -464,7 +447,7 @@ msgid ""
"Jobs will start unpacking during the downloading to reduce post-processing "
"time. Only works for jobs that do not need repair."
msgstr ""
".עבודות יתחילו להיפרק במהלך ההורדה כדי להפחית זמן לאחר-עיבוד. עובד רק עבור "
".עבודות יתחילו להיפרק במהלך ההורדה כדי להפחית זמן בתר-עיבוד. עובד רק עבור "
"עבודות שאינן צריכות תיקון"
#: sabnzbd/dirscanner.py # sabnzbd/dirscanner.py # sabnzbd/dirscanner.py
@@ -575,6 +558,12 @@ msgstr "נכשל בסגירת חיבור דוא\"ל"
msgid "Email succeeded"
msgstr "דוא\"ל הצליח"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "לא ניתן לשלוח, נתונים דרושים חסרים"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "%s-לא ניתן למצוא תבניות דוא\"ל"
@@ -665,7 +654,7 @@ msgstr ""
":אימות חסר, אנא הכנס שם משתמש/סיסמה מתוך תצורה->כללי לתוך תכנית הצד השלישי "
"שלך"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -738,10 +727,19 @@ msgstr "!שרת בלתי מוגדר"
msgid "Incorrect parameter"
msgstr "משתנה לא נכון"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ".תיקיית מדור אינה יכולה להיות תת-תיקייה של תיקיית ההורדות הזמניות"
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "הקודם"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "שגיאה:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -794,11 +792,15 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "%s לא יכול לשנות הרשאות של"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "מריץ תסריט"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
msgid "PostProcessing was aborted (%s)"
msgstr "(%s) לאחר-עיבוד בוטל"
msgstr "(%s) בתר-עיבוד בוטל"
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP phase "script"] # sabnzbd/skintext.py
#: sabnzbd/skintext.py [Notification Script settings]
@@ -969,6 +971,7 @@ msgstr "מתחיל תיקון"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "!בעוד שבדיקה זריזה הצליחה ,%s-נכשל ב Par וידוא"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -995,10 +998,6 @@ msgstr "כל הקבצים נכונים ,%s-[%s] וודאו ב"
msgid "[%s] Verified in %s, repair is required"
msgstr "תיקון דרוש ,%s-[%s] וודאו ב"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "...חפיסה ראשית לא נמצאה"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1042,6 +1041,10 @@ msgstr "דיסק מלא"
msgid "Verifying"
msgstr "מוודא"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr "בודק קבצי תוספת"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1085,7 +1088,7 @@ msgstr "התווסף NZB"
#: sabnzbd/notifier.py
msgid "Post-processing started"
msgstr "לאחר-עיבוד התחיל"
msgstr "בתר-עיבוד התחיל"
#: sabnzbd/notifier.py [Notification]
msgid "Job finished"
@@ -1107,11 +1110,6 @@ msgstr "הודעות אחרות"
msgid "Not available"
msgstr "לא זמין"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "לא ניתן לשלוח, נתונים דרושים חסרים"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Prowl נכשל בשליחת הודעת"
@@ -1120,7 +1118,7 @@ msgstr "Prowl נכשל בשליחת הודעת"
msgid "Bad response from Pushover (%s): %s"
msgstr "Pushover (%s): %s-תגובה רעה מ"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "pushover נכשל בשליחת הודעת"
@@ -1492,7 +1490,7 @@ msgstr ""
".כבר רץ SABnzbd איזשהי תוכנה אחרת משתמשת בפתחה או %s לא היה ניתן לקשר את "
"פתחה %s על"
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "שגיאה חמורה"
@@ -1516,6 +1514,13 @@ msgstr ""
"המגבילה גודל מרבי של קובץ אל 4 ג\"ב ,FAT היא במערכת קבצים %s תיקיית ההורדות "
"השלמות"
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
".של קבצים וספריות בהורדות Unicode חסר. צפה לבעיות עם שמות subprocessww פירקן"
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "הורדה עשויה להיכשל, רק %s מתוך %s דרושים זמינים"
@@ -1526,7 +1531,7 @@ msgstr "הורדה נכשלה - לא בשרת(ים) שלך"
#: sabnzbd/postproc.py
msgid "No post-processing because of failed verification"
msgstr "אין לאחר-עיבוד בגלל וידוא כושל"
msgstr "אין בתר-עיבוד בגלל וידוא כושל"
#: sabnzbd/postproc.py
msgid "Moving"
@@ -1544,10 +1549,6 @@ msgstr "\"%s\" אל \"%s\" שגיאה בשינוי שם"
msgid "Failed to move files"
msgstr "נכשל בהעברת קבצים"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "מריץ תסריט"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "%s מריץ תסריט משתמש"
@@ -1566,9 +1567,9 @@ msgstr "עוד"
#: sabnzbd/postproc.py [Error message]
msgid "Post Processing Failed for %s (%s)"
msgstr "%s (%s) לאחר-עיבוד נכשל עבור"
msgstr "%s (%s) בתר-עיבוד נכשל עבור"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "ראה קובץ יומן"
@@ -1594,7 +1595,7 @@ msgstr "%s לא יכול ליצור תיקייה סופית"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "לאחר-עיבוד"
msgstr "בתר-עיבוד"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
@@ -1830,11 +1831,11 @@ msgstr "השהה הכל"
#: sabnzbd/skintext.py [#: Config->Scheduler]
msgid "Pause post-processing"
msgstr "השהה לאחר-עיבוד"
msgstr "השהה בתר-עיבוד"
#: sabnzbd/skintext.py [#: Config->Scheduler]
msgid "Resume post-processing"
msgstr "המשך לאחר-עיבוד"
msgstr "המשך בתר-עיבוד"
#: sabnzbd/skintext.py [#: Config->Scheduler]
msgid "Read RSS feeds"
@@ -2727,6 +2728,14 @@ msgstr "SABnzbd סיסמת"
msgid "Optional authentication password."
msgstr "סיסמת אימות רשותית"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
".SABnzbd חשופים לאינטרנט, ההגדרות הנוכחיות שלך מאפשרות גישה חיצונית מלאה אל "
"ממשק SABnzbd אם המארח או הפתחה של"
#: sabnzbd/skintext.py
msgid "Security"
msgstr "אבטחה"
@@ -2960,7 +2969,7 @@ msgid ""
"<em>NOTE:</em> Folders will be created automatically when Saving. You may "
"use absolute paths to save outside of the default folders."
msgstr ""
"<em>הערה:</em> .תיקיות יווצרו באופן אוטומטי בעת שמירה. אתה יכול להשתמש "
"<em>הערה:</em> תיקיות יווצרו באופן אוטומטי בעת שמירה. אתה יכול להשתמש "
"בנתיבים מוחלטים כדי לשמור מחוץ לתיקיות ברירת המחדל"
#: sabnzbd/skintext.py
@@ -3146,11 +3155,11 @@ msgstr ""
#: sabnzbd/skintext.py
msgid "Post-Process Only Verified Jobs"
msgstr "בצע לאחר-עיבוד רק על עבודות שוודאו"
msgstr "בצע בתר-עיבוד רק על עבודות שוודאו"
#: sabnzbd/skintext.py
msgid "Only perform post-processing on jobs that passed all PAR2 checks."
msgstr ".PAR2-בצע לאחר-עיבוד רק בעבודות שעברו את כל בדיקות ה"
msgstr ".PAR2-בצע בתר-עיבוד רק בעבודות שעברו את כל בדיקות ה"
#: sabnzbd/skintext.py
msgid "Action when encrypted RAR is downloaded"
@@ -3277,8 +3286,8 @@ msgid ""
"Use temporary names during post processing. Disable when your system doesn't "
"handle that properly."
msgstr ""
".השתמש בשמות זמניים במהלך לאחר-עיבוד. השבת כאשר המערכת שלך אינה מתמודדת עם "
"זה כראוי"
".השתמש בשמות זמניים במהלך בתר-עיבוד. השבת כאשר המערכת שלך אינה מתמודדת עם זה "
"כראוי"
#: sabnzbd/skintext.py
msgid "Pre-queue user script"
@@ -3370,12 +3379,12 @@ msgstr ".SABnzbd הפעל את דפדפן ברירת המחדל בעת התחל
#: sabnzbd/skintext.py
msgid "Pause Downloading During Post-Processing"
msgstr "השהה הורדה במהלך לאחר-עיבוד"
msgstr "השהה הורדה במהלך בתר-עיבוד"
#: sabnzbd/skintext.py
msgid ""
"Pauses downloading at the start of post processing and resumes when finished."
msgstr ".משהה הורדה בתחילת לאחר-עיבוד וממשיך בסיום"
msgstr ".משהה הורדה בתחילת בתר-עיבוד וממשיך בסיום"
#: sabnzbd/skintext.py
msgid "Ignore Samples"
@@ -3404,7 +3413,7 @@ msgstr "שרת"
#: sabnzbd/skintext.py
msgid "Post processing"
msgstr "לאחר-עיבוד"
msgstr "בתר-עיבוד"
#: sabnzbd/skintext.py
msgid "Naming"
@@ -3466,7 +3475,7 @@ msgstr "SSL צפני"
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ".חלש יותר SSL הגבר ביצועים ע\"י אילוץ חוזק הצפנת"
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "ניסיונות חוזרים מרביים"
@@ -3944,6 +3953,22 @@ msgstr "התקן(ים)"
msgid "Device(s) to which message should be sent"
msgstr "התקנים אליהם הודעה תישלח"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr "ניסיון חוזר חרום"
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr "באיזו תדירות (בשניות) אותה ההתראה תישלח"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr "תפוגת חרום"
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr "כמה שניות ההתראה שלך תמשיך להיות מנוסה שוב"
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4357,6 +4382,14 @@ msgstr "..SABnzbd אבד חיבור אל"
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr "!המסך יעלם באופן אוטומטי SABnzbd במקרה של הפעלה מחדש של"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "אזהרה:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "משוך"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "קצב רענון"
@@ -4525,6 +4558,14 @@ msgstr "...השהה למשך"
msgid "Refresh"
msgstr "רענן"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
".מוסרים באופן אוטומטי מהיומן ומהעותק הכלול של ההגדרות שלך API-כל שמות "
"המשתמש, הסיסמאות ומפתחות ה"
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "מיין לפי גיל <small>החדש ביותר&rarr;הישן ביותר</small>"
@@ -4671,10 +4712,6 @@ msgstr "זה ימנע רענון תוכן כשסמן העכבר שלך מרחף
msgid "Block Refreshes on Hover"
msgstr "חסום רענונים בריחוף"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "משוך"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "העלה"
@@ -4980,5 +5017,14 @@ msgstr "%s ;משיכת כתובת נכשלה"
#~ msgid "Invalid par2 files, cannot verify or repair"
#~ msgstr "בלתי תקפים, לא יכול לוודא או לתקן par2 קבצי"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "%s (%s -> %s)-ב CRC שגיאת"
#~ msgid "Main packet not found..."
#~ msgstr "...חפיסה ראשית לא נמצאה"
#~ msgid "It is likely that you are using ZoneAlarm on Vista.<br>"
#~ msgstr ".Vista על ZoneAlarm-סביר להניח שאתה משתמש ב<br>"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "נכשל, ראה יומן SQL חיוב"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-09-03 14:07+0000\n"
"Last-Translator: Steffen Bærø <steffen.baro@gmail.com>\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-09-04 05:51+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -228,15 +228,6 @@ msgstr "Test varslingen"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Løs adresse"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEIL:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ADVARSEL:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ingen"
@@ -403,10 +394,6 @@ msgstr "Skadet historikkdatabase, opprettet ny database"
msgid "SQL Command Failed, see log"
msgstr "SQL-kommando mislyktes, se logg"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL Innsetting mislyktes, se logg"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Kunne ikke stenge databasen, se logg"
@@ -423,10 +410,6 @@ msgstr "Dekoding av %s mislyktes"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC-feil i %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Feilaktigt utformet yEnc artikkel i %s"
@@ -576,6 +559,12 @@ msgstr "Kunne ikke stenge e-post-tilkobling"
msgid "Email succeeded"
msgstr "E-post sendning lykkes"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Kan ikke sendes, mangler nødvendig data"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Kan ikke finne e-post-maler i %s"
@@ -668,7 +657,7 @@ msgstr ""
"Autentisering mangler, angi brukernavn/passord fra Konfigurasjon->Generelt i "
"ditt tredjepartsprogram:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -742,10 +731,19 @@ msgstr "Udefinert server!"
msgid "Incorrect parameter"
msgstr "Feil parameter"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Tilbake"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEIL:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -796,6 +794,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Kunne ikke endre rettigheter på %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Kjører skript"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -971,6 +973,7 @@ msgstr "Starter reparasjon"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Par verifisering feilet på %s, mens hurtigsjekk var vellykket!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -998,10 +1001,6 @@ msgstr "[%s] Verifiseing tok %s, alle filer er ok"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Verifisering tok %s, krever reparasjon"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Hovedarkiv mangler..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1045,6 +1044,10 @@ msgstr "Harddisken er full"
msgid "Verifying"
msgstr "Verifiserer"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1108,11 +1111,6 @@ msgstr "Andre meldinger"
msgid "Not available"
msgstr "Ikke tilgjengelig"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Kan ikke sendes, mangler nødvendig data"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Klarte ikke å sende Prowl melding"
@@ -1121,7 +1119,7 @@ msgstr "Klarte ikke å sende Prowl melding"
msgid "Bad response from Pushover (%s): %s"
msgstr "Ukorrekt svar fra Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Klarte ikke å sende pushover-melding"
@@ -1494,7 +1492,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Kritisk feil"
@@ -1516,6 +1514,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "Nedlasting kan feile, kun %s av kravet på %s tilgjengelig"
@@ -1544,10 +1548,6 @@ msgstr "Kunne ikke endre navn fra \"%s\" til \"%s\""
msgid "Failed to move files"
msgstr "Klarte ikke å flytte filer"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Kjører skript"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Kjør brukerskript %s"
@@ -1568,7 +1568,7 @@ msgstr "Mer"
msgid "Post Processing Failed for %s (%s)"
msgstr "Etterbehandling mislyktes for %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "se loggfil"
@@ -2727,6 +2727,12 @@ msgstr "SABnzbd Passord"
msgid "Optional authentication password."
msgstr "Kan velge autentiserings passord."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3468,7 +3474,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Maksimum antall forsøk"
@@ -3942,6 +3948,22 @@ msgstr "Enhet(er)"
msgid "Device(s) to which message should be sent"
msgstr "Enhet(er) som meldingen skal sendes til"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4355,6 +4377,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"Hvis SABnzbd skulle starte på nytt vil denne skjermen forsvinne automatisk!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ADVARSEL:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Hent"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Oppdateringsfrekvens"
@@ -4521,6 +4551,12 @@ msgstr "Pause i..."
msgid "Refresh"
msgstr "Oppdatere"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sorter etter alder <small>Eldst&rarr;Ny</small>"
@@ -4667,10 +4703,6 @@ msgstr "Dette vil hindre oppfrisking av innhold når muspekeren er over køen"
msgid "Block Refreshes on Hover"
msgstr "Blokker oppfrisking når musen svever over"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Hent"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Last Opp"
@@ -4937,6 +4969,9 @@ msgstr "URL henting mislyktes; %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Mappen \"%s\" finnes ikke"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL Innsetting mislyktes, se logg"
#~ msgid "No UNRAR program found, unpacking RAR files is not possible<br />"
#~ msgstr "Kunne ikke finne noen UNRAR program, utpakking er ikke mulig<br />"
@@ -4982,6 +5017,9 @@ msgstr "URL henting mislyktes; %s"
#~ msgid "Unpacking failed, an expected file was not unpacked"
#~ msgstr "Utpakking mislyktes, en forventet fil er ikke utpakket"
#~ msgid "Main packet not found..."
#~ msgstr "Hovedarkiv mangler..."
#~ msgid "Error importing OpenSSL module. Connecting with NON-SSL"
#~ msgstr "Mislyktes med importering av OpenSSL modul. Kobler til uten SSL"
@@ -5313,6 +5351,9 @@ msgstr "URL henting mislyktes; %s"
#~ msgid "WARNING: Paused job \"%s\" because of encrypted RAR file"
#~ msgstr "ADVARSEL: Jobb \"%s\" satt på pause pga. kryptert RAR-fil"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC-feil i %s (%s -> %s)"
#~ msgid ""
#~ "Your UNRAR version is not recommended, get it from "
#~ "http://www.rarlab.com/rar_add.htm<br />"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"PO-Revision-Date: 2017-09-04 13:02+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-11-01 09:08+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-09-05 04:59+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -233,15 +233,6 @@ msgstr "Test melding"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Adres opzoeken"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FOUT:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "WAARSCHUWING:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Geen"
@@ -421,10 +412,6 @@ msgstr ""
msgid "SQL Command Failed, see log"
msgstr "SQL-commando mislukt, zie logbestand"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL-opslagopdracht mislukt, zie logbestand"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Het lukt niet om de database te sluiten, zie log"
@@ -441,10 +428,6 @@ msgstr "Decoderen van %s mislukt"
msgid "Decoder failure: Out of memory"
msgstr "Decoder fout: onvoldoende geheugen"
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC-fout in %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Slecht opgemaakt yEnc-artikel in %s"
@@ -598,6 +581,12 @@ msgstr "Beëindigen e-mailverbinding mislukt"
msgid "Email succeeded"
msgstr "E-mail verzonden"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Versturen kan niet, vereiste gegevens ontbreken"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Geen e-mailsjablonen te vinden in %s"
@@ -690,7 +679,7 @@ msgstr ""
"Autenticatie ontbreekt; vul gebruikersnaam en wachtwoord van 'Configuratie' "
"=> 'Algemeen' in bij het externe programma:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -765,10 +754,21 @@ msgstr "Onbekende server."
msgid "Incorrect parameter"
msgstr "Incorrecte parameter"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
"Een Categorie specifieke map mag niet een map in de Tijdelijke download map "
"zijn."
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Terug"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FOUT:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -822,6 +822,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Toegangsrechten van %s niet aan te passen"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Script uitvoeren"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -997,6 +1001,7 @@ msgstr "Reparatie starten"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Par-verificatie van %s misgelukt, maar QuickCheck wel gelukt."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1024,10 +1029,6 @@ msgstr "[%s] %s geverifieerd, alle bestanden zijn goed"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Geverifieerd in %s, reparatie is nodig"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Hoofdpakket niet gevonden..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1072,6 +1073,10 @@ msgstr "Schijf is vol"
msgid "Verifying"
msgstr "Verifiëren"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr "Controleren van extra bestanden"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1138,11 +1143,6 @@ msgstr "Andere berichten"
msgid "Not available"
msgstr "Niet beschikbaar"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Versturen kan niet, vereiste gegevens ontbreken"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Verzenden van Prowl-bericht mislukt"
@@ -1151,7 +1151,7 @@ msgstr "Verzenden van Prowl-bericht mislukt"
msgid "Bad response from Pushover (%s): %s"
msgstr "Slecht antwoord van Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Pushover-bericht sturen mislukt"
@@ -1526,7 +1526,7 @@ msgstr ""
"Kan niet binden aan poort %s van %s. Andere software gebruikt deze poort of "
"SABnzbd is al actief."
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Fatale fout"
@@ -1550,6 +1550,14 @@ msgstr ""
"De map voor voltooide downloads %s staat op een FAT systeem, de maximale "
"file omvang is dan maar 4G"
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
"De module subprocessww ontbreekt. Je kunt problemen krijgen met Unicode "
"namen van bestanden en mappen."
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1579,10 +1587,6 @@ msgstr "Fout bij hernoemen van \"%s\" tot \"%s\""
msgid "Failed to move files"
msgstr "Verplaatsen van bestanden mislukt"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Script uitvoeren"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Gebruiker script %s loopt"
@@ -1603,7 +1607,7 @@ msgstr "Meer"
msgid "Post Processing Failed for %s (%s)"
msgstr "Nabewerking van %s mislukt (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "zie logbestand"
@@ -2772,6 +2776,15 @@ msgstr "Wachtwoord"
msgid "Optional authentication password."
msgstr "Wachtwoord voor web login."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
"Als de Host of Poort open is gesteld naar het internet zorgen de huidige "
"instellingen ervoor dat de webinterface volledig beschikbaar is voor "
"externen."
#: sabnzbd/skintext.py
msgid "Security"
msgstr "Beveiliging"
@@ -3542,7 +3555,7 @@ msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
"Verhoog de prestaties door een eenvoudigere SSL versleuteling toe te passen."
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Maximum aantal pogingen"
@@ -4032,6 +4045,22 @@ msgstr "Apparaten"
msgid "Device(s) to which message should be sent"
msgstr "Apparaat of apparaten die het bericht moeten ontvangen"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr "Noodgeval herhaling"
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr "Hoevaak moet de notification herhaald worden (in seconden)"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr "Einde van noodgeval"
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr "Hoeveel seconden moet de notificatie herhaald worden"
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4449,6 +4478,14 @@ msgstr "Verbinding met SABnzbd verbroken"
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr "Wanneer SABnzbd opnieuw is gestart, gaat dit venster vanzelf weg!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "WAARSCHUWING:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Ophalen"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Ververssnelheid"
@@ -4617,6 +4654,12 @@ msgstr "Pauzeer..."
msgid "Refresh"
msgstr "Ververs"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sorteer op Leeftijd <small>Oud&rarr;Nieuw</small>"
@@ -4764,10 +4807,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Geen verversing bij popups"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Ophalen"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Ophalen"
@@ -5075,6 +5114,9 @@ msgstr "URL ophalen mislukt; %s"
#~ msgid "pyopenssl module missing, please install for https access"
#~ msgstr "Module \"pyopenssl\" ontbreekt, geen HTTPS mogelijk"
#~ msgid "Main packet not found..."
#~ msgstr "Hoofdpakket niet gevonden..."
#~ msgid "Failed to remove nzo from postproc queue (id)"
#~ msgstr "Verwijderen van nzo van nabewerkingswachtrij mislukt"
@@ -5559,6 +5601,12 @@ msgstr "URL ophalen mislukt; %s"
#~ msgstr ""
#~ "WAARSCHUWING: Taak '%s' is afgebroken vanwege een versleuteld RAR-bestand"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC-fout in %s (%s -> %s)"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL-opslagopdracht mislukt, zie logbestand"
#~ msgid "No UNRAR program found, unpacking RAR files is not possible<br />"
#~ msgstr ""
#~ "Geen UNRAR-programma gevonden, uitpakken van RAR-bestanden niet mogelijk<br "

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2015-12-28 10:22+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -226,15 +226,6 @@ msgstr "Powiadomienie testowe"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Rozwiązywanie adresu"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "BŁĄD:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "UWAGA:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Brak"
@@ -403,10 +394,6 @@ msgstr "Uszkodzona baza danych historii, utworzono w jej miejscu nową, pustą"
msgid "SQL Command Failed, see log"
msgstr "Błąd polecenia SQL, sprawdź logi"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "Błąd wykonania polecenia SQL, sprawdź logi"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Błąd zamykania bazy danych, sprawdź logi"
@@ -423,10 +410,6 @@ msgstr "Błąd dekodowania %s"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "Błąd CRC w %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Źle zbudowany artykuł yEnc w %s"
@@ -578,6 +561,12 @@ msgstr "Nie udało się zamknąć połączenia z serwerem pocztowym"
msgid "Email succeeded"
msgstr "Wiadomość wysłana"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Nie można wysłać wiadomości, brak wymaganych danych"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Brak szablonów wiadomości email w %s"
@@ -670,7 +659,7 @@ msgstr ""
"Brak danych uwierzytelniających, wprowadź nazwę użytkownika/hasło z sekcji "
"Konfiguracja->Ogólne do zewnętrznego programu:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -745,10 +734,19 @@ msgstr "Niezdefiniowany serwer!"
msgid "Incorrect parameter"
msgstr "Błędny parametr"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Powrót"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "BŁĄD:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -799,6 +797,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Nie można zmienić uprawnień %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Uruchamianie skryptu"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -974,6 +976,7 @@ msgstr "Rozpoczynanie naprawy"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Weryfikacja %s nieudana, choć szybkie sprawdzenie powiodło się!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1002,10 +1005,6 @@ msgstr "[%s] Zweryfikowano w %s, wszystkie pliki prawidłowe"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Zweryfikowano w %s, wymagana naprawa"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Główny pakiet nieznaleziony..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1050,6 +1049,10 @@ msgstr "Dysk pełny"
msgid "Verifying"
msgstr "Weryfikowanie"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1113,11 +1116,6 @@ msgstr "Inne komunikaty"
msgid "Not available"
msgstr "Niedostępne"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Nie można wysłać wiadomości, brak wymaganych danych"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Błąd wysyłania wiadomości Prowl"
@@ -1126,7 +1124,7 @@ msgstr "Błąd wysyłania wiadomości Prowl"
msgid "Bad response from Pushover (%s): %s"
msgstr "Zła odpowiedź od Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Nie udało się wysłać wiadomości Pushover"
@@ -1500,7 +1498,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Błąd krytyczny"
@@ -1523,6 +1521,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "Pobieranie może się nie udać, dostępne jedynie %s z wymaganych %s"
@@ -1552,10 +1556,6 @@ msgstr "Błąd zmiany nazwy \"%s\" na \"%s\""
msgid "Failed to move files"
msgstr "Nie udało się przenieść plików"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Uruchamianie skryptu"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Uruchamianie skryptu użytkownika %s"
@@ -1576,7 +1576,7 @@ msgstr "Więcej"
msgid "Post Processing Failed for %s (%s)"
msgstr "Przetwarzanie końcowe nie powiodło się dla %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "sprawdź logi"
@@ -2733,6 +2733,12 @@ msgstr "Hasło SABnzbd"
msgid "Optional authentication password."
msgstr "Opcjonalne hasło"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3485,7 +3491,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Maksymalna ilość prób"
@@ -3960,6 +3966,22 @@ msgstr "Urządzenie(-a)"
msgid "Device(s) to which message should be sent"
msgstr "Urządzenie(-a), do którego(-ych) mają być wysyłane powiadomienia"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4373,6 +4395,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"W razie ponownego uruchomienia SABnzbd ten ekran zniknie automatycznie!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "UWAGA:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Pobierz"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Częstotliwość odświeżania"
@@ -4539,6 +4569,12 @@ msgstr "Wstrzymaj na..."
msgid "Refresh"
msgstr "Odśwież"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sortuj według wieku <small>Najstarsze&rarr;Najnowsze</small>"
@@ -4685,10 +4721,6 @@ msgstr "Blokuje odświeżanie zawartości po najechaniu kursorem na kolejkę"
msgid "Block Refreshes on Hover"
msgstr "Zablokuj odświeżanie podczas wskazywania"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Pobierz"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Wczytaj"
@@ -4950,6 +4982,9 @@ msgstr "Bezużyteczny plik NZB"
msgid "URL Fetching failed; %s"
msgstr "Pobieranie URL nie powiodło się; %s"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "Błąd CRC w %s (%s -> %s)"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Folder \"%s\" nie istnieje"
@@ -4966,6 +5001,9 @@ msgstr "Pobieranie URL nie powiodło się; %s"
#~ msgid "Downloaded so far"
#~ msgstr "Dotychczas pobrano"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "Błąd wykonania polecenia SQL, sprawdź logi"
#~ msgid "Not matched"
#~ msgstr "Nie dopasowano"
@@ -5245,6 +5283,9 @@ msgstr "Pobieranie URL nie powiodło się; %s"
#~ msgid "Missing expected file: %s => unrar error?"
#~ msgstr "Brak oczekiwanego pliku: %s => błąd rozpakowywania archiwum RAR?"
#~ msgid "Main packet not found..."
#~ msgstr "Główny pakiet nieznaleziony..."
#~ msgid "Error importing OpenSSL module. Connecting with NON-SSL"
#~ msgstr "Błąd importu modułu OpenSSL. Łączenie bez SSL"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2016-01-01 22:58+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-09-03 05:50+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:49+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -226,15 +226,6 @@ msgstr "Notificação de teste"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Resolvendo endereço"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ERRO:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "AVISO:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Nenhum"
@@ -405,10 +396,6 @@ msgstr "Dados de histórico danificados, criado um substituto vazio"
msgid "SQL Command Failed, see log"
msgstr "O comando SQL falhou. Consulte o log"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "O commit do SQL falhou. Consulte o log"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Falha ao fechar o banco de dados. Consulte o log"
@@ -425,10 +412,6 @@ msgstr "Falha ao decodificar %s"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "Erro de CRC em %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Artigo yEnc mal formado em %s"
@@ -579,6 +562,12 @@ msgstr "Falha ao fechar a conexão de e-mail"
msgid "Email succeeded"
msgstr "E-mail enviado com sucesso"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Não foi possível enviar, faltam dados obrigatórios"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Não é possível encontrar modelos de e-mail em %s"
@@ -671,7 +660,7 @@ msgstr ""
"Autenticação faltando. Por favor insira usuário/senha de Configuração->Geral "
"em seu programa de terceiros:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -745,10 +734,19 @@ msgstr "Servidor não definido!"
msgid "Incorrect parameter"
msgstr "Parâmetro incorreto"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Voltar"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ERRO:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -799,6 +797,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Não é possível alterar permissões de %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Executando script"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -974,6 +976,7 @@ msgstr "Iniciando reparação"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Validação de par falhou em %s, enquanto QuickCheck foi completo!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1001,10 +1004,6 @@ msgstr "[%s] Verificado em %s. Todos os arquivos corretos"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Verificado em %s. É necessário reparar"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Pacote principal não encontrado..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1047,6 +1046,10 @@ msgstr "Disco cheio"
msgid "Verifying"
msgstr "Verificando"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1110,11 +1113,6 @@ msgstr "Outras Mensagens"
msgid "Not available"
msgstr "Não disponível"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Não foi possível enviar, faltam dados obrigatórios"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Falha ao enviar mensagem Prowl"
@@ -1123,7 +1121,7 @@ msgstr "Falha ao enviar mensagem Prowl"
msgid "Bad response from Pushover (%s): %s"
msgstr "Resposta incorreta do Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Falha ao enviar mensagem pushover"
@@ -1499,7 +1497,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Erro fatal"
@@ -1521,6 +1519,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1550,10 +1554,6 @@ msgstr "Erro ao renomear \"%s\" para \"%s\""
msgid "Failed to move files"
msgstr "Falha ao mover arquivos"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Executando script"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Executando script de usuário %s"
@@ -1574,7 +1574,7 @@ msgstr "Mais"
msgid "Post Processing Failed for %s (%s)"
msgstr "O pós-processamento falhou para %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "veja o arquivo de log"
@@ -2733,6 +2733,12 @@ msgstr "Senha do SABnzbd"
msgid "Optional authentication password."
msgstr "Senha de autenticação opcional."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3482,7 +3488,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Máximo de tentativas"
@@ -3958,6 +3964,22 @@ msgstr "Dispositivo(s)"
msgid "Device(s) to which message should be sent"
msgstr "Dispositivo(s) para qual a mensagem deve ser enviada"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4371,6 +4393,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"No caso de reinício do SABnzbd, esta janela irá desaparecer automaticamente!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "AVISO:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Obter"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Taxa de atualização"
@@ -4537,6 +4567,12 @@ msgstr "Pausar por..."
msgid "Refresh"
msgstr "Atualizar"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Ordenar por Idade <small>Mais antigo&rarr;Mais novo</small>"
@@ -4685,10 +4721,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Impedir Atualizações no Foco"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Obter"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Enviar"
@@ -4955,9 +4987,15 @@ msgstr "A busca da URL falhou; %s"
#~ msgstr ""
#~ "ATENÇÃO: Tarefa \"%s\" em pausa por causa de arquivo RAR criptografado"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "Erro de CRC em %s (%s -> %s)"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "A pasta \"%s\" não existe"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "O commit do SQL falhou. Consulte o log"
#~ msgid ""
#~ "Your UNRAR version is not recommended, get it from "
#~ "http://www.rarlab.com/rar_add.htm<br />"
@@ -5010,6 +5048,9 @@ msgstr "A busca da URL falhou; %s"
#~ msgid "Missing expected file: %s => unrar error?"
#~ msgstr "Faltando arquivo esperado: %s => erro no unrar?"
#~ msgid "Main packet not found..."
#~ msgstr "Pacote principal não encontrado..."
#~ msgid "Invalid par2 files, cannot verify or repair"
#~ msgstr "Arquivos PAR2 inválidos. Não é possível verificar ou reparar"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2016-07-29 16:20+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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -229,15 +229,6 @@ msgstr "Notificări Test"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Reolvare adresă"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "EROARE:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ATENŢIE:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Niciunul"
@@ -407,10 +398,6 @@ msgstr "Bază de date Istoric coruptă, creat un nou fişier gol"
msgid "SQL Command Failed, see log"
msgstr "Comandă SQL Nereuşită, vedeţi jurnal"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "Modificare SQL Nereuşită, vedeţi jurnal"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Închidere bază de date nereuşită, vedeţi jurnal"
@@ -427,10 +414,6 @@ msgstr "Decodarea %s nereuşită"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "Eroare CRC în %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Articoul yEnc invalid în %s"
@@ -581,6 +564,12 @@ msgstr "Închidere conexiune mail nereuşită"
msgid "Email succeeded"
msgstr "Email reuşit"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Nu pot trimite, informații necesare lipsă"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Nu pot gasi şabloane email în %s"
@@ -673,7 +662,7 @@ msgstr ""
"Autentificare lipsă, vă rugăm să introduceţi numele de utilizator/parola de "
"la Configurare->General în programul dumneavoastră terţ:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -748,10 +737,19 @@ msgstr "Server nedefinit!"
msgid "Incorrect parameter"
msgstr "Parametru Incorect"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Înapoi"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "EROARE:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -802,6 +800,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Nu pot schimba permisiunile lui %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Rulare script"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -977,6 +979,7 @@ msgstr "Pornire Reparare"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Verificarea Par eșuată pentru %s, dar VerificareaRapidă reușită!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -1005,10 +1008,6 @@ msgstr "[%s] Verificat în %s, toate fişierele sunt corecte"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Verificat în %s, reparare necesară"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Pachet principal negăsit..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1051,6 +1050,10 @@ msgstr "Disc plin"
msgid "Verifying"
msgstr "Se verifică"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1114,11 +1117,6 @@ msgstr "Alte Mesaje"
msgid "Not available"
msgstr "Indisponibil"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Nu pot trimite, informații necesare lipsă"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Nu am putu trimite mesajul Prowl"
@@ -1127,7 +1125,7 @@ msgstr "Nu am putu trimite mesajul Prowl"
msgid "Bad response from Pushover (%s): %s"
msgstr "Răspuns greșit de la Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Nu am putut trimite mesajul de pushover"
@@ -1506,7 +1504,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Eroare fatală"
@@ -1528,6 +1526,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "Descărcarea ar putea eşua, doar %s din %s disponibil"
@@ -1556,10 +1560,6 @@ msgstr "Eroare redenumire \"%s\" în \"%s\""
msgid "Failed to move files"
msgstr "Nu am putu muta fişier"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Rulare script"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Rulare script utilizator %s"
@@ -1580,7 +1580,7 @@ msgstr "Mai mult"
msgid "Post Processing Failed for %s (%s)"
msgstr "Post Procesare Nereuşită pentru %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "vezi fişier jurnal"
@@ -2740,6 +2740,12 @@ msgstr "Parolă SABnzbd"
msgid "Optional authentication password."
msgstr "Parolă autentificare opţională"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3484,7 +3490,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Număr Maxim reîncercări"
@@ -3963,6 +3969,22 @@ msgstr "Dispozitiv(e)"
msgid "Device(s) to which message should be sent"
msgstr "Dispozitiv(e) la care să se trimită mesajul"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4374,6 +4396,14 @@ msgstr "Am pierdut conexiunea cu SABnzbd.."
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr "În cazul repornirii SABnzbd acest ecran va dispărea în mod automat!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ATENŢIE:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Descarcă"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Rată actualizare"
@@ -4542,6 +4572,12 @@ msgstr "Pauză timp de..."
msgid "Refresh"
msgstr "Reîmprospătează"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sortează după Vârstă <small>Cel mai Vechi&rarr;Cel mai Nou</small>"
@@ -4690,10 +4726,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Blochează Reîmprospătarea Hover"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Descarcă"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Încarcă"
@@ -4960,9 +4992,15 @@ msgstr "Descărcare URL nereuşită; %s"
#~ msgstr ""
#~ "ATENŢIE: Sarcina \"%s\" întreruptă din cauza fişierelor RAR encriptate"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "Eroare CRC în %s (%s -> %s)"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Dosarul \"%s\" nu există"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "Modificare SQL Nereuşită, vedeţi jurnal"
#~ msgid "No UNRAR program found, unpacking RAR files is not possible<br />"
#~ msgstr ""
#~ "Nici un program UNRAR găsit, dezarhivarea fişierelor RAR imposibilă<br />"
@@ -5044,6 +5082,9 @@ msgstr "Descărcare URL nereuşită; %s"
#~ msgid "Missing expected file: %s => unrar error?"
#~ msgstr "Fişiere aşteptate lipsă: %s => eroare unrar?"
#~ msgid "Main packet not found..."
#~ msgstr "Pachet principal negăsit..."
#~ msgid "Error importing OpenSSL module. Connecting with NON-SSL"
#~ msgstr "Eroare importare modul OpenSSL . Se conectează folosind NON-SSL"

View File

@@ -2,15 +2,15 @@ msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-0.7.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2013-05-05 14:50+0000\n"
"Last-Translator: Pavel Maryanov <Unknown>\n"
"Language-Team: Russian <gmu@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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
"Generated-By: pygettext.py 1.5\n"
#: SABnzbd.py [Error message]
@@ -221,15 +221,6 @@ msgstr "Тестовое уведомление"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Разрешение адреса"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ОШИБКА"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ПРЕДУПРЕЖДЕНИЕ"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ничего"
@@ -396,10 +387,6 @@ msgstr ""
msgid "SQL Command Failed, see log"
msgstr "Ошибка команды SQL (см. журнал)"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "Ошибка фиксации SQL (см. журнал)"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Не удалось закрыть базу данных (см. журнал)"
@@ -416,10 +403,6 @@ msgstr "Ошибка декодирования %s"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "Ошибка CRC в %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Неверно сформированная статья yEnc в %s"
@@ -568,6 +551,12 @@ msgstr "Не удалось разорвать соединение с почт
msgid "Email succeeded"
msgstr "Электронное письмо успешно отправлено"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr ""
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Не удаётся найти шаблонны электронных писем в %s"
@@ -663,7 +652,7 @@ msgstr ""
"Отсутствуют учётные данные. Введите в сторонней программе имя пользователя и "
"пароль из раздела «Настройка -> Общие»:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -735,10 +724,19 @@ msgstr ""
msgid "Incorrect parameter"
msgstr "Неправильный параметр"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Назад"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ОШИБКА"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -789,6 +787,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Не удаётся изменить права доступа %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Запуск сценария"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -964,6 +966,7 @@ msgstr "запуск исправления"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -992,10 +995,6 @@ msgstr "[%s] Проверено за %s. Ошибок нет"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Проверено за %s. Требуется исправление"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Главный пакет не найден..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1039,6 +1038,10 @@ msgstr ""
msgid "Verifying"
msgstr "Проверка"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1102,11 +1105,6 @@ msgstr "Другие сообщения"
msgid "Not available"
msgstr ""
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr ""
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr ""
@@ -1115,7 +1113,7 @@ msgstr ""
msgid "Bad response from Pushover (%s): %s"
msgstr ""
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr ""
@@ -1492,7 +1490,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Критическая ошибка"
@@ -1514,6 +1512,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1542,10 +1546,6 @@ msgstr "Ошибка переименования «%s» и «%s»"
msgid "Failed to move files"
msgstr "Не удалось переместить файлы"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Запуск сценария"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Запуск пользовательского сценария %s"
@@ -1566,7 +1566,7 @@ msgstr "Подробнее"
msgid "Post Processing Failed for %s (%s)"
msgstr "Ошибка пост-обработки для %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "см. журнал"
@@ -2723,6 +2723,12 @@ msgstr "Пароль SABnzbd"
msgid "Optional authentication password."
msgstr "Необязательный пароль для входа."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3461,7 +3467,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Число попыток"
@@ -3941,6 +3947,22 @@ msgstr ""
msgid "Device(s) to which message should be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr ""
@@ -4352,6 +4374,14 @@ msgstr ""
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ПРЕДУПРЕЖДЕНИЕ"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Загрузить"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Частота обновления"
@@ -4518,6 +4548,12 @@ msgstr "Приостановить на..."
msgid "Refresh"
msgstr "Обновить"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Сортировать по возрасту <small>от старых к новым</small>"
@@ -4666,10 +4702,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Блокировать обновление при наведении мыши"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Загрузить"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Отправить"
@@ -4941,6 +4973,12 @@ msgstr "Не удалось загрузить URL: %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Папка «%s» не существует"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "Ошибка фиксации SQL (см. журнал)"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "Ошибка CRC в %s (%s -> %s)"
#~ msgid "Error: No secondary interface defined."
#~ msgstr "Ошибка: дополнительный интерфейс не определён."
@@ -4998,6 +5036,9 @@ msgstr "Не удалось загрузить URL: %s"
#~ msgid "Unpacking failed, these file(s) are missing:"
#~ msgstr "Ошибка распаковки: отсутствуют следующие файлы:"
#~ msgid "Main packet not found..."
#~ msgstr "Главный пакет не найден..."
#~ msgid "Invalid par2 files, cannot verify or repair"
#~ msgstr "Недопустимые PAR2-файлы. Нельзя выполнить проверку или исправление"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: ОZZII <ozzii.translate@gmail.com>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2015-12-28 10:25+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>\n"
"Language-Team: Serbian <sr@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-09-03 05:49+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -223,15 +223,6 @@ msgstr "Probno obaveštenje"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Решавање адресе"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ГРЕШКА:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ПАЖЊА:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ниједно"
@@ -400,10 +391,6 @@ msgstr "Baza dnevnika je oštećena, kreirana prazna zamena"
msgid "SQL Command Failed, see log"
msgstr "Neuspešna SQL komanda, videti izveštaj"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "Погрешно SQL извршавање, видети извештај"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Неуспешно затварање базе, видети извештај"
@@ -420,10 +407,6 @@ msgstr "Dešifrovanje %s neuspešno"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC грешка у %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Лоше формиран yEnc артикал у %s"
@@ -573,6 +556,12 @@ msgstr "Неуспешно затварање везе е-поште"
msgid "Email succeeded"
msgstr "Упешно слање е-поште"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Nemoguće poslati, nedostaju obavezni podaci"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Немогуће наћи модел е-поруке у %s"
@@ -663,7 +652,7 @@ msgstr ""
"Недостаје аутентификација, унети у спољни програм име/лозинку из Подешавања-"
">Опште:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -737,10 +726,19 @@ msgstr "Server nije definisan!"
msgid "Incorrect parameter"
msgstr "Погрешан параметар"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Назад"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "ГРЕШКА:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -791,6 +789,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Не може да се промене дозволе од %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Покретање скрипта"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -966,6 +968,7 @@ msgstr "Покретање пооправљања"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Par provera neuspešna na %s, dok je QuickCheck uspešan!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -994,10 +997,6 @@ msgstr "[%s] Проверено за %s, све датотеке су добре
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Проверено за %s, потребна је поправка"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Главни пакет није нађен..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1040,6 +1039,10 @@ msgstr "Диск је пун"
msgid "Verifying"
msgstr "Проверавање"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1103,11 +1106,6 @@ msgstr "Остале поруке"
msgid "Not available"
msgstr "Недоступно"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Nemoguće poslati, nedostaju obavezni podaci"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Неуспешно слање Prowl поруке"
@@ -1116,7 +1114,7 @@ msgstr "Неуспешно слање Prowl поруке"
msgid "Bad response from Pushover (%s): %s"
msgstr "Neodgovarajući odgovor od strane Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Neuspešno slanje Pushover poruke"
@@ -1486,7 +1484,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Фатална грешка"
@@ -1508,6 +1506,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "Преузимање је можда погрешно. има %s од потребних %s"
@@ -1536,10 +1540,6 @@ msgstr "Грешка преименовања \"%s\" у \"%s\""
msgid "Failed to move files"
msgstr "Неуспешно премештање датотека"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Покретање скрипта"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Покретање скрипта %s"
@@ -1560,7 +1560,7 @@ msgstr "Више"
msgid "Post Processing Failed for %s (%s)"
msgstr "Грешка пост-процесирања за %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "видети извештај"
@@ -2715,6 +2715,12 @@ msgstr "Лозинка SABnzbd-а"
msgid "Optional authentication password."
msgstr "Лозинка за аутентификацију (опционо)"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3453,7 +3459,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Макс покушаја"
@@ -3927,6 +3933,22 @@ msgstr "Uređaj(i)"
msgid "Device(s) to which message should be sent"
msgstr "Uređaj(i) na koje bi poruke trebale biti poslate"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4339,6 +4361,14 @@ msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr ""
"U slučaju ponovnog pokretanja SABnzbd-a ovaj prozor će nestati automatski!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "ПАЖЊА:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Преузми"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Брзина освежавања"
@@ -4505,6 +4535,12 @@ msgstr "Паузирај за..."
msgid "Refresh"
msgstr "Освежи"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Среди по старост <small>Старије&rarr;Новије</small>"
@@ -4651,10 +4687,6 @@ msgstr "При прелазу миша преко рада, зауставља
msgid "Block Refreshes on Hover"
msgstr "Блокирати обнове на прелаз миша"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Преузми"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Слање"
@@ -5189,6 +5221,12 @@ msgstr "Погрешно учитавање УРЛ-а; %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "фасцикла \"%s\" не постоји"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "Погрешно SQL извршавање, видети извештај"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC грешка у %s (%s -> %s)"
#~ msgid "Not matched"
#~ msgstr "Не одговара"
@@ -5238,6 +5276,9 @@ msgstr "Погрешно учитавање УРЛ-а; %s"
#~ msgid "Unpacking failed, these file(s) are missing:"
#~ msgstr "Неуспешан издвој, ове датотеке недостају:"
#~ msgid "Main packet not found..."
#~ msgstr "Главни пакет није нађен..."
#~ msgid "KB/s"
#~ msgstr "КБ/с"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2016-02-20 20:34+0000\n"
"Last-Translator: shypike <Unknown>\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-09-03 05:50+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:48+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -224,15 +224,6 @@ msgstr "Testa notifikation"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;Lösa adress"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEL:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "VARNING:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "Ingen"
@@ -401,10 +392,6 @@ msgstr "Skadad hitsotrikdatabas, skapade en tom ersättare"
msgid "SQL Command Failed, see log"
msgstr "SQL Kommando misslyckades, se logg"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL Commit misslyckades, se logg"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "Det gick inte att stänga databasen, se logg"
@@ -421,10 +408,6 @@ msgstr "Avkodning av %s misslyckades"
msgid "Decoder failure: Out of memory"
msgstr ""
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC Fel i %s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "Felaktigt utformad yEnc artikel i %s"
@@ -573,6 +556,12 @@ msgstr "Det gick inte att stänga e-mail anslutning"
msgid "Email succeeded"
msgstr "E-mail sändning lyckades"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Kunde inte skicka, saknar nödvändig data"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "Kan ej finna e-mail mallar i %s"
@@ -666,7 +655,7 @@ msgstr ""
"Autentisering saknas, ange användarnamn / lösenord från Konfiguration-> "
"Allmänt i ditt tredjepartsprogram:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -741,10 +730,19 @@ msgstr "Odefinerad server!"
msgid "Incorrect parameter"
msgstr "Fel parameter"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "Bakåt"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "FEL:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -795,6 +793,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "Det gick inte att ändra rättigheter på %s"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "Kör skript"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -970,6 +972,7 @@ msgstr "Startar reparation"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Par verifiering misslyckades på %s, medans QuickCheck lyckades!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -998,10 +1001,6 @@ msgstr "[%s] Verifierad i %s, alla filer är ok"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] Verifiering i %s, kräver reparation"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "Huvudarkiv saknas..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1045,6 +1044,10 @@ msgstr "Disken är full"
msgid "Verifying"
msgstr "Verifierar"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1108,11 +1111,6 @@ msgstr "Andra meddelanden"
msgid "Not available"
msgstr "Ej tillgänglig"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "Kunde inte skicka, saknar nödvändig data"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "Misslyckades att skicka Prowlmeddelande"
@@ -1121,7 +1119,7 @@ msgstr "Misslyckades att skicka Prowlmeddelande"
msgid "Bad response from Pushover (%s): %s"
msgstr "Dålig respons från Pushover (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "Misslyckades att skicka pushovermeddelande"
@@ -1496,7 +1494,7 @@ msgid ""
"SABnzbd is already running."
msgstr ""
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "Allvarligt fel"
@@ -1518,6 +1516,12 @@ msgid ""
"size to 4GB"
msgstr ""
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr ""
@@ -1547,10 +1551,6 @@ msgstr "Det gick inte att döpa om \"%s\" till \"%s\""
msgid "Failed to move files"
msgstr "Misslyckades med att flytta filer"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "Kör skript"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "Kör användarskript %s"
@@ -1571,7 +1571,7 @@ msgstr "Mer"
msgid "Post Processing Failed for %s (%s)"
msgstr "Efterbehandling misslyckades för %s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "se loggfil"
@@ -2728,6 +2728,12 @@ msgstr "SABnzbd Lösenord"
msgid "Optional authentication password."
msgstr "Väljbart autentiserings lösenord."
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr ""
@@ -3468,7 +3474,7 @@ msgstr ""
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr ""
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "Max antal omförsök"
@@ -3942,6 +3948,22 @@ msgstr "Enhet(er)"
msgid "Device(s) to which message should be sent"
msgstr "Enhet(er) där medellandet skall skickas"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4353,6 +4375,14 @@ msgstr "Förlorade förbindelse till SABnzbd.."
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr "Om SABnzbd startar om kommer denna skärm att försvinna automatiskt!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "VARNING:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Hämta"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "Uppdateringsfrekvens"
@@ -4519,6 +4549,12 @@ msgstr "Pausa i..."
msgid "Refresh"
msgstr "Uppdatera"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "Sortera efter ålder <small>Äldst&rarr;Nyast</small>"
@@ -4667,10 +4703,6 @@ msgstr ""
msgid "Block Refreshes on Hover"
msgstr "Block uppdaterar vid svävande"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "Hämta"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "Ladda upp"
@@ -4938,6 +4970,12 @@ msgstr "URL hämtning misslyckades; %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "Mappen \"%s\" finns inte"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL Commit misslyckades, se logg"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC Fel i %s (%s -> %s)"
#~ msgid "Error: No secondary interface defined."
#~ msgstr "Fel: Inget andrainterface definierat."
@@ -4993,6 +5031,9 @@ msgstr "URL hämtning misslyckades; %s"
#~ msgid "Unpacking failed, an expected file was not unpacked"
#~ msgstr "Uppackning misslyckades, en väntad fil är inte uppackad"
#~ msgid "Main packet not found..."
#~ msgstr "Huvudarkiv saknas..."
#~ msgid "Error importing OpenSSL module. Connecting with NON-SSL"
#~ msgstr "Misslyckades med importering av OpenSSL modul. Ansluter utan SSL"

View File

@@ -7,15 +7,15 @@ msgid ""
msgstr ""
"Project-Id-Version: sabnzbd\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2017-09-02 13:51+0000\n"
"POT-Creation-Date: 2017-11-20 21:21+0000\n"
"PO-Revision-Date: 2017-06-22 07:06+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>\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-09-03 05:50+0000\n"
"X-Generator: Launchpad (build 18446)\n"
"X-Launchpad-Export-Date: 2017-11-21 05:49+0000\n"
"X-Generator: Launchpad (build 18505)\n"
#: SABnzbd.py [Error message]
msgid "Failed to start web-interface"
@@ -220,15 +220,6 @@ msgstr "测试通知"
msgid "&nbsp;Resolving address"
msgstr "&nbsp;正在解析地址"
#: sabnzbd/api.py # sabnzbd/api.py # sabnzbd/interface.py
#: sabnzbd/skintext.py
msgid "ERROR:"
msgstr "错误:"
#: sabnzbd/api.py # sabnzbd/skintext.py
msgid "WARNING:"
msgstr "警告:"
#: sabnzbd/api.py # sabnzbd/skintext.py [No value, used in dropdown menus] # sabnzbd/skintext.py [Job details page, select no files]
msgid "None"
msgstr "无"
@@ -395,10 +386,6 @@ msgstr "“历史记录”数据库已损坏,已创建空数据库代替"
msgid "SQL Command Failed, see log"
msgstr "SQL 命令执行失败,参见日志"
#: sabnzbd/database.py [Error message]
msgid "SQL Commit Failed, see log"
msgstr "SQL 保存失败,参见日志"
#: sabnzbd/database.py [Error message]
msgid "Failed to close database, see log"
msgstr "无法关闭数据库,参见日志"
@@ -415,10 +402,6 @@ msgstr "%s 解码失败"
msgid "Decoder failure: Out of memory"
msgstr "解码器失败:内存不足"
#: sabnzbd/decoder.py
msgid "CRC Error in %s (%s -> %s)"
msgstr "CRC 错误:%s (%s -> %s)"
#: sabnzbd/decoder.py
msgid "Badly formed yEnc article in %s"
msgstr "yEnc 文章格式错误:%s"
@@ -567,6 +550,12 @@ msgstr "无法关闭邮件连接"
msgid "Email succeeded"
msgstr "成功发送电子邮件"
#: sabnzbd/emailer.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/rating.py
#: sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "无法发送,缺少必要的数据"
#: sabnzbd/emailer.py [Error message]
msgid "Cannot find email templates in %s"
msgstr "无法找到 email 模板:%s"
@@ -653,7 +642,7 @@ msgid ""
"into your 3rd party program:"
msgstr "缺身份认证信息,请在第三方程序中输入“配置”->“常规”中的用户名/密码:"
#: sabnzbd/interface.py [Warning message] # sabnzbd/skintext.py
#: sabnzbd/interface.py [Warning message]
msgid ""
"Try our new skin Glitter! Fresh new design that is optimized for desktop and "
"mobile devices. Go to Config -> General to change your skin."
@@ -724,10 +713,19 @@ msgstr "未定义服务器!"
msgid "Incorrect parameter"
msgstr "参数不正确"
#: sabnzbd/interface.py
msgid ""
"Category folder cannot be a subfolder of the Temporary Download Folder."
msgstr ""
#: sabnzbd/interface.py # sabnzbd/interface.py
msgid "Back"
msgstr "返回"
#: sabnzbd/interface.py # sabnzbd/skintext.py
msgid "ERROR:"
msgstr "错误:"
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
#: sabnzbd/interface.py # sabnzbd/interface.py
@@ -778,6 +776,10 @@ msgstr ""
msgid "Cannot change permissions of %s"
msgstr "无法更改 %s 的权限"
#: sabnzbd/newsunpack.py # sabnzbd/postproc.py
msgid "Running script"
msgstr "正在执行脚本"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/postproc.py
@@ -953,6 +955,7 @@ msgstr "正在开始修复"
msgid "Par verify failed on %s, while QuickCheck succeeded!"
msgstr "Par 验证失败:%s但快速检查成功!"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Repairing failed, %s"
@@ -979,10 +982,6 @@ msgstr "[%s] 验证耗时 %s所有文件均完好无损"
msgid "[%s] Verified in %s, repair is required"
msgstr "[%s] 验证耗时 %s需要修复"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Main packet not found..."
msgstr "主数据包未找到..."
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid ""
"Invalid par2 files or invalid PAR2 parameters, cannot verify or repair"
@@ -1025,6 +1024,10 @@ msgstr "磁盘空间已满"
msgid "Verifying"
msgstr "正在验证"
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
msgid "Checking extra files"
msgstr ""
#: sabnzbd/newsunpack.py # sabnzbd/newsunpack.py
#: sabnzbd/newsunpack.py # sabnzbd/skintext.py [PP status]
msgid "Checking"
@@ -1088,11 +1091,6 @@ msgstr "其他信息"
msgid "Not available"
msgstr "不可用"
#: sabnzbd/notifier.py # sabnzbd/notifier.py # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/rating.py # sabnzbd/rating.py
msgid "Cannot send, missing required data"
msgstr "无法发送,缺少必要的数据"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send Prowl message"
msgstr "无法发送 Prowl 消息"
@@ -1101,7 +1099,7 @@ msgstr "无法发送 Prowl 消息"
msgid "Bad response from Pushover (%s): %s"
msgstr "Pushover 响应异常 (%s): %s"
#: sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
#: sabnzbd/notifier.py # sabnzbd/notifier.py [Warning message] # sabnzbd/notifier.py
msgid "Failed to send pushover message"
msgstr "无法发送 pushover 信息"
@@ -1470,7 +1468,7 @@ msgid ""
"SABnzbd is already running."
msgstr "绑定端口 %s 在 %s 上失败。其它的程序正在使用此端口或者说 SABnzbd 正在运行。"
#: sabnzbd/panic.py # sabnzbd/panic.py
#: sabnzbd/panic.py # sabnzbd/panic.py # sabnzbd/panic.py
msgid "Fatal error"
msgstr "致命错误"
@@ -1492,6 +1490,12 @@ msgid ""
"size to 4GB"
msgstr "已完成文件夹 %s 位于 FAT 文件系统上,这样会有最大文件为 4GB 的限制。"
#: sabnzbd/postproc.py [Warning message]
msgid ""
"Module subprocessww missing. Expect problems with Unicoded file and "
"directory names in downloads."
msgstr ""
#: sabnzbd/postproc.py
msgid "Download might fail, only %s of required %s available"
msgstr "下载可能会失败,只有 %s 块 (需要 %s) 可用"
@@ -1520,10 +1524,6 @@ msgstr "将 \"%s\" 重命名为 \"%s\" 出错"
msgid "Failed to move files"
msgstr "移动文件失败"
#: sabnzbd/postproc.py
msgid "Running script"
msgstr "正在执行脚本"
#: sabnzbd/postproc.py
msgid "Running user script %s"
msgstr "正在执行用户脚本 %s"
@@ -1544,7 +1544,7 @@ msgstr "更多"
msgid "Post Processing Failed for %s (%s)"
msgstr "后期处理失败:%s (%s)"
#: sabnzbd/postproc.py
#: sabnzbd/postproc.py [Error message] # sabnzbd/postproc.py
msgid "see logfile"
msgstr "查看日志文件"
@@ -2695,6 +2695,12 @@ msgstr "SABnzbd 密码"
msgid "Optional authentication password."
msgstr "可选身份验证密码。"
#: sabnzbd/skintext.py
msgid ""
"If the SABnzbd Host or Port is exposed to the internet, your current "
"settings allow full external access to the SABnzbd interface."
msgstr ""
#: sabnzbd/skintext.py
msgid "Security"
msgstr "安全"
@@ -3398,7 +3404,7 @@ msgstr "SSL 加密算法"
msgid "Increase performance by forcing a lower SSL encryption strength."
msgstr "降低 SSL 的加密难度以便获得更高的性能。"
#: sabnzbd/skintext.py
#: sabnzbd/skintext.py # sabnzbd/urlgrabber.py
msgid "Maximum retries"
msgstr "最多重试次数"
@@ -3869,6 +3875,22 @@ msgstr "设备"
msgid "Device(s) to which message should be sent"
msgstr "信息发送的目标设备"
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency retry"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How often (in seconds) the same notification will be sent"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "Emergency expire"
msgstr ""
#: sabnzbd/skintext.py [Pushover settings]
msgid "How many seconds your notification will continue to be retried"
msgstr ""
#: sabnzbd/skintext.py [Header for Pushbullet notification section]
msgid "Pushbullet"
msgstr "Pushbullet"
@@ -4279,6 +4301,14 @@ msgstr "失去与 SABnzbd 的连接.."
msgid "In case of SABnzbd restart this screen will disappear automatically!"
msgstr "SABnzbd 重启后本画面将自动消失!"
#: sabnzbd/skintext.py
msgid "WARNING:"
msgstr "警告:"
#: sabnzbd/skintext.py # sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "装取"
#: sabnzbd/skintext.py # sabnzbd/skintext.py
msgid "Refresh rate"
msgstr "刷新频率"
@@ -4445,6 +4475,12 @@ msgstr "暂停..."
msgid "Refresh"
msgstr "刷新"
#: sabnzbd/skintext.py
msgid ""
"All usernames, passwords and API-keys are automatically removed from the log "
"and the included copy of your settings."
msgstr ""
#: sabnzbd/skintext.py
msgid "Sort by Age <small>Oldest&rarr;Newest</small>"
msgstr "按发布时间排序 <small>最早&rarr;最新</small>"
@@ -4591,10 +4627,6 @@ msgstr "这将在您的鼠标指针处于队列上方时阻止内容刷新。"
msgid "Block Refreshes on Hover"
msgstr "指向时停止刷新"
#: sabnzbd/skintext.py [Fetch from URL button in "Add NZB" dialog box]
msgid "Fetch"
msgstr "装取"
#: sabnzbd/skintext.py [Upload button in "Add NZB" dialog box]
msgid "Upload"
msgstr "上传"
@@ -4856,6 +4888,12 @@ msgstr "URL 装取失败; %s"
#~ msgid "Folder \"%s\" does not exist"
#~ msgstr "文件夹 \"%s\" 不存在"
#~ msgid "SQL Commit Failed, see log"
#~ msgstr "SQL 保存失败,参见日志"
#~ msgid "CRC Error in %s (%s -> %s)"
#~ msgstr "CRC 错误:%s (%s -> %s)"
#~ msgid "Error: No secondary interface defined."
#~ msgstr "错误: 未定义第二界面。"
@@ -4909,6 +4947,9 @@ msgstr "URL 装取失败; %s"
#~ msgid "Unpacking failed, these file(s) are missing:"
#~ msgstr "解压失败,缺这些文件:"
#~ msgid "Main packet not found..."
#~ msgstr "主数据包未找到..."
#~ msgid "Invalid par2 files, cannot verify or repair"
#~ msgstr "par2 文件无效,无法验证或修复"

View File

@@ -108,7 +108,7 @@ import sabnzbd.lang as lang
import sabnzbd.par2file as par2file
import sabnzbd.api
import sabnzbd.directunpacker as directunpacker
from sabnzbd.decorators import synchronized, notify_downloader
from sabnzbd.decorators import synchronized
from sabnzbd.constants import NORMAL_PRIORITY, VALID_ARCHIVES, \
REPAIR_REQUEST, QUEUE_FILE_NAME, QUEUE_VERSION, QUEUE_FILE_TMPL
import sabnzbd.getipaddress as getipaddress
@@ -537,7 +537,7 @@ def guard_https_ver():
set_https_verification(cfg.enable_https_verification())
def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None, feed_name=None):
def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None):
""" Add NZB based on a URL, attributes optional """
if 'http' not in url:
return
@@ -551,8 +551,8 @@ def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None, fe
# Add feed name if it came from RSS
msg = T('Trying to fetch NZB from %s') % url
if feed_name:
msg = '%s - %s' % (feed_name, msg)
if nzbname:
msg = '%s - %s' % (nzbname, msg)
# Generate the placeholder
future_nzo = NzbQueue.do.generate_future(msg, pp, script, cat, url=url, priority=priority, nzbname=nzbname)
@@ -874,7 +874,7 @@ def get_new_id(prefix, folder, check_list=None):
def save_data(data, _id, path, do_pickle=True, silent=False):
""" Save data to a diskfile """
if not silent:
logging.debug("Saving data for %s in %s", _id, path)
logging.debug('[%s] Saving data for %s in %s', misc.caller_name(), _id, path)
path = os.path.join(path, _id)
# We try 3 times, to avoid any dict or access problems
@@ -906,11 +906,11 @@ def load_data(_id, path, remove=True, do_pickle=True, silent=False):
path = os.path.join(path, _id)
if not os.path.exists(path):
logging.info("%s missing", path)
logging.info("[%s] %s missing", misc.caller_name(), path)
return None
if not silent:
logging.debug("Loading data for %s from %s", _id, path)
logging.debug("[%s] Loading data for %s from %s", misc.caller_name(), _id, path)
try:
with open(path, 'rb') as data_file:
@@ -923,7 +923,7 @@ def load_data(_id, path, remove=True, do_pickle=True, silent=False):
data = data_file.read()
if remove:
os.remove(path)
misc.remove_file(path)
except:
logging.error(T('Loading %s failed'), path)
logging.info("Traceback: ", exc_info=True)
@@ -937,8 +937,7 @@ def remove_data(_id, path):
path = os.path.join(path, _id)
try:
if os.path.exists(path):
os.remove(path)
logging.info("%s removed", path)
misc.remove_file(path)
except:
logging.debug("Failed to remove %s", path)
@@ -946,7 +945,7 @@ def remove_data(_id, path):
def save_admin(data, _id):
""" Save data in admin folder in specified format """
path = os.path.join(cfg.admin_dir.get_path(), _id)
logging.info("Saving data for %s in %s", _id, path)
logging.debug("[%s] Saving data for %s in %s", misc.caller_name(), _id, path)
# We try 3 times, to avoid any dict or access problems
for t in xrange(3):
@@ -969,10 +968,10 @@ def save_admin(data, _id):
def load_admin(_id, remove=False, silent=False):
""" Read data in admin folder in specified format """
path = os.path.join(cfg.admin_dir.get_path(), _id)
logging.info("Loading data for %s from %s", _id, path)
logging.debug("[%s] Loading data for %s from %s", misc.caller_name(), _id, path)
if not os.path.exists(path):
logging.info("%s missing", path)
logging.info("[%s] %s missing", misc.caller_name(), path)
return None
try:
@@ -982,7 +981,7 @@ def load_admin(_id, remove=False, silent=False):
else:
data = cPickle.load(data_file)
if remove:
os.remove(path)
misc.remove_file(path)
except:
if not silent:
excepterror = str(sys.exc_info()[0])
@@ -1036,7 +1035,7 @@ def check_repair_request():
path = os.path.join(cfg.admin_dir.get_path(), REPAIR_REQUEST)
if os.path.exists(path):
try:
os.remove(path)
misc.remove_file(path)
except:
pass
return True
@@ -1107,7 +1106,7 @@ def pid_file(pid_path=None, pid_file=None, port=0):
f.write('%d\n' % os.getpid())
f.close()
else:
os.remove(DIR_PID)
misc.remove_file(DIR_PID)
except:
logging.warning('Cannot access PID file %s', DIR_PID)

View File

@@ -1277,11 +1277,7 @@ def build_status(skip_dashboard=False, output=None):
info['servers'].append((server.displayname, '', connected, serverconnections, server.ssl,
server.active, server.errormsg, server.priority, server.optional))
wlist = []
for w in sabnzbd.GUIHANDLER.content():
w = w.replace('WARNING', T('WARNING:')).replace('ERROR', T('ERROR:'))
wlist.insert(0, unicoder(w))
info['warnings'] = wlist
info['warnings'] = sabnzbd.GUIHANDLER.content()
return info
@@ -1362,7 +1358,7 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None):
slot['status'] = "%s" % (status)
if (Downloader.do.paused or Downloader.do.postproc or is_propagating or \
status not in (Status.DOWNLOADING, Status.QUEUED)) and priority != TOP_PRIORITY:
status not in (Status.DOWNLOADING, Status.FETCHING, Status.QUEUED)) and priority != TOP_PRIORITY:
slot['timeleft'] = '0:00:00'
slot['eta'] = 'unknown'
else:
@@ -1633,8 +1629,6 @@ def build_header(webdir='', output=None):
header['restart_req'] = sabnzbd.RESTART_REQ
header['pid'] = os.getpid()
header['last_warning'] = sabnzbd.GUIHANDLER.last().replace('WARNING', ('WARNING:')).replace('ERROR', T('ERROR:'))
header['active_lang'] = cfg.language()
header['my_lcldata'] = sabnzbd.DIR_LCLDATA
@@ -1693,7 +1687,7 @@ def build_queue_header(search=None, start=0, limit=0, output=None):
bytes = qnfo.bytes
header['kbpersec'] = "%.2f" % (bytespersec / KIBI)
header['speed'] = to_units(bytespersec, spaces=1, dec_limit=1)
header['speed'] = to_units(bytespersec, spaces=1)
header['mbleft'] = "%.2f" % (bytesleft / MEBI)
header['mb'] = "%.2f" % (bytes / MEBI)
header['sizeleft'] = format_bytes(bytesleft)

View File

@@ -22,6 +22,7 @@ sabnzbd.articlecache - Article cache handling
import sys
import logging
import threading
import struct
import sabnzbd
from sabnzbd.decorators import synchronized
@@ -40,6 +41,13 @@ class ArticleCache(object):
self.__cache_size = 0
self.__article_list = [] # List of buffered articles
self.__article_table = {} # Dict of buffered articles
# On 32 bit we only allow the user to set 1GB
# For 64 bit we allow up to 4GB, in case somebody wants that
self.__cache_upper_limit = GIGI
if sabnzbd.DARWIN or sabnzbd.WIN64 or (struct.calcsize("P") * 8) == 64:
self.__cache_upper_limit = 4*GIGI
ArticleCache.do = self
@synchronized(ARTICLE_LOCK)
@@ -51,9 +59,9 @@ class ArticleCache(object):
""" Called when cache limit changes """
self.__cache_limit_org = limit
if limit < 0:
self.__cache_limit = GIGI
self.__cache_limit = self.__cache_upper_limit
else:
self.__cache_limit = min(limit, GIGI)
self.__cache_limit = min(limit, self.__cache_upper_limit)
@synchronized(ARTICLE_LOCK)
def reserve_space(self, data):
@@ -74,23 +82,24 @@ class ArticleCache(object):
@synchronized(ARTICLE_LOCK)
def save_article(self, article, data):
nzf = article.nzf
nzo = nzf.nzo
if nzo.is_gone():
if article.nzf.nzo.is_gone():
# Do not discard this article because the
# file might still be processed at this moment!!
return
saved_articles = article.nzf.nzo.saved_articles
# Register article
if article not in article.nzf.nzo.saved_articles:
article.nzf.nzo.saved_articles.append(article)
if article not in saved_articles:
saved_articles.append(article)
if article.lowest_partnum and not article.nzf.import_finished:
# Write the first-fetched articles to disk
# Otherwise the cache could overflow
self.__flush_article(article, data)
return
if self.__cache_limit:
if self.__cache_limit < 0:
self.__add_to_cache(article, data)
else:
data_size = len(data)

View File

@@ -38,7 +38,7 @@ from sabnzbd.postproc import PostProcessor
import sabnzbd.downloader
import sabnzbd.par2file as par2file
import sabnzbd.utils.rarfile as rarfile
from sabnzbd.encoding import unicoder, is_utf8
from sabnzbd.encoding import unicoder
from sabnzbd.rating import Rating
@@ -76,7 +76,7 @@ class Assembler(Thread):
if not sabnzbd.downloader.Downloader.do.paused:
logging.warning(T('Too little diskspace forcing PAUSE'))
# Pause downloader, but don't save, since the disk is almost full!
sabnzbd.downloader.Downloader.do.pause(save=False)
sabnzbd.downloader.Downloader.do.pause()
sabnzbd.emailer.diskfull()
# Abort all direct unpackers, just to be sure
sabnzbd.directunpacker.abort_all()
@@ -97,15 +97,17 @@ class Assembler(Thread):
try:
filepath = self.assemble(nzf, filepath)
except IOError, (errno, strerror):
# If job was deleted, ignore error
if not nzo.is_gone():
# If job was deleted or in active post-processing, ignore error
if not nzo.deleted and not nzo.is_gone() and not nzo.pp_active:
# 28 == disk full => pause downloader
if errno == 28:
logging.error(T('Disk full! Forcing Pause'))
else:
logging.error(T('Disk error on creating file %s'), clip_path(filepath))
# Log traceback
logging.info('Traceback: ', exc_info=True)
# Pause without saving
sabnzbd.downloader.Downloader.do.pause(save=False)
sabnzbd.downloader.Downloader.do.pause()
continue
except:
logging.error(T('Fatal error in Assembler'), exc_info=True)
@@ -292,6 +294,9 @@ def check_encrypted_and_unwanted_files(nzo, filepath):
# Did any work?
if password_hit:
# We always trust the user's input
if not nzo.password:
nzo.password = password_hit
# Don't check other files
logging.info('Password "%s" matches for job "%s"', password_hit, nzo.final_name)
nzo.encrypted = -1
@@ -315,7 +320,8 @@ def check_encrypted_and_unwanted_files(nzo, filepath):
zf.close()
del zf
except:
logging.info('Error during inspection of RAR-file %s', filepath, exc_info=True)
logging.info('Error during inspection of RAR-file %s', filepath)
logging.debug('Traceback: ', exc_info=True)
return encrypted, unwanted

View File

@@ -261,6 +261,7 @@ fixed_ports = OptionBool('misc', 'fixed_ports', False)
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)
# Text values
rss_odd_titles = OptionList('misc', 'rss_odd_titles', ['nzbindex.nl/', 'nzbindex.com/', 'nzbclub.com/'])
@@ -374,6 +375,8 @@ prowl_prio_other = OptionNumber('prowl', 'prowl_prio_other', -3)
pushover_token = OptionStr('pushover', 'pushover_token')
pushover_userkey = OptionStr('pushover', 'pushover_userkey')
pushover_device = OptionStr('pushover', 'pushover_device')
pushover_emergency_expire = OptionNumber('pushover', 'pushover_emergency_expire', 3600)
pushover_emergency_retry = OptionNumber('pushover', 'pushover_emergency_retry', 60)
pushover_enable = OptionBool('pushover', 'pushover_enable')
pushover_cats = OptionList('pushover', 'pushover_cats', ['*'])
pushover_prio_startup = OptionNumber('pushover', 'pushover_prio_startup', -3)

View File

@@ -385,7 +385,7 @@ class ConfigServer(object):
self.displayname = OptionStr(name, 'displayname', '', add=False)
self.host = OptionStr(name, 'host', '', add=False)
self.port = OptionNumber(name, 'port', 119, 0, 2 ** 16 - 1, add=False)
self.timeout = OptionNumber(name, 'timeout', 120, 30, 240, add=False)
self.timeout = OptionNumber(name, 'timeout', 60, 20, 240, add=False)
self.username = OptionStr(name, 'username', '', add=False)
self.password = OptionPassword(name, 'password', '', add=False)
self.connections = OptionNumber(name, 'connections', 1, 0, 100, add=False)
@@ -395,7 +395,7 @@ class ConfigServer(object):
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, 100, 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)
@@ -859,7 +859,7 @@ def save_config(force=False):
logging.error(T('Cannot write to INI file %s'), filename)
logging.info("Traceback: ", exc_info=True)
try:
os.remove(filename)
sabnzbd.misc.remove_file(filename)
except:
pass
# Restore INI file from backup

View File

@@ -51,7 +51,7 @@ RENAMES_FILE = '__renames__'
ATTRIB_FILE = 'SABnzbd_attrib'
REPAIR_REQUEST = 'repair-all.sab'
SABYENC_VERSION_REQUIRED = '3.0.2'
SABYENC_VERSION_REQUIRED = '3.3.2'
DB_HISTORY_VERSION = 1
DB_HISTORY_NAME = 'history%s.db' % DB_HISTORY_VERSION
@@ -77,6 +77,7 @@ DEF_LOG_CHERRY = 'cherrypy.log'
DEF_CACHE_LIMIT = '450M'
DEF_TIMEOUT = 60
DEF_SCANRATE = 5
MAX_URL_RETRIES = 10
MAX_DECODE_QUEUE = 10
LIMIT_DECODE_QUEUE = 100
MAX_WARNINGS = 20

View File

@@ -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
from sabnzbd.misc import get_all_passwords, int_conv, remove_file, caller_name
DB_LOCK = threading.RLock()
@@ -126,7 +126,7 @@ class HistoryDB(object):
else:
self.c.execute(command)
if save:
self.save()
self.con.commit()
return True
except:
error = str(sys.exc_value)
@@ -143,7 +143,7 @@ class HistoryDB(object):
logging.info("Traceback: ", exc_info=True)
self.close()
try:
os.remove(HistoryDB.db_path)
remove_file(HistoryDB.db_path)
except:
pass
self.connect()
@@ -196,14 +196,6 @@ class HistoryDB(object):
""")
self.execute('PRAGMA user_version = 2;')
def save(self):
""" Save database to disk """
try:
self.con.commit()
except:
logging.error(T('SQL Commit Failed, see log'))
logging.info("Traceback: ", exc_info=True)
def close(self):
""" Close database connection """
try:
@@ -243,10 +235,8 @@ class HistoryDB(object):
jobs = [jobs]
for job in jobs:
self.execute("""DELETE FROM history WHERE nzo_id=?""", (job,))
logging.info('Removing job %s from history', job)
self.save()
self.execute("""DELETE FROM history WHERE nzo_id=?""", (job,), save=True)
logging.info('[%s] Removing job %s from history', caller_name(), job)
def auto_history_purge(self):
""" Remove history items based on the configured history-retention """
@@ -275,11 +265,10 @@ class HistoryDB(object):
""" Add a new job entry to the database """
t = build_history_info(nzo, storage, path, postproc_time, script_output, script_line)
if self.execute("""INSERT INTO history (completed, name, nzb_name, category, pp, script, report,
url, status, nzo_id, storage, path, script_log, script_line, download_time, postproc_time, stage_log,
downloaded, completeness, fail_message, url_info, bytes, series, md5sum, password)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", t):
self.save()
self.execute("""INSERT INTO history (completed, name, nzb_name, category, pp, script, report,
url, status, nzo_id, storage, path, script_log, script_line, download_time, postproc_time, stage_log,
downloaded, completeness, fail_message, url_info, bytes, series, md5sum, password)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""", t, save=True)
logging.info('Added job %s to history', nzo.final_name)
def fetch_history(self, start=None, limit=None, search=None, failed_only=0, categories=None):
@@ -504,15 +493,9 @@ def build_history_info(nzo, storage='', downpath='', postproc_time=0, script_out
if seriesname and season and episode:
series = u'%s/%s/%s' % (seriesname.lower(), season, episode)
# See whatever the first password was, for the Retry
password = ''
passwords = get_all_passwords(nzo)
if passwords:
password = passwords[0]
return (completed, name, nzb_name, category, pp, script, report, url, status, nzo_id, storage, path,
script_log, script_line, download_time, postproc_time, stage_log, downloaded, completeness,
fail_message, url_info, bytes, series, nzo.md5sum, password)
fail_message, url_info, bytes, series, nzo.md5sum, nzo.password)
def unpack_history_info(item):

View File

@@ -31,6 +31,7 @@ from sabnzbd.constants import Status, MAX_DECODE_QUEUE, LIMIT_DECODE_QUEUE, SABY
import sabnzbd.articlecache
import sabnzbd.downloader
import sabnzbd.nzbqueue
import sabnzbd.cfg as cfg
from sabnzbd.encoding import yenc_name_fixer
from sabnzbd.misc import match_str
@@ -47,8 +48,8 @@ try:
import sabyenc
SABYENC_ENABLED = True
SABYENC_VERSION = sabyenc.__version__
# Verify version
if SABYENC_VERSION != SABYENC_VERSION_REQUIRED:
# Verify version to at least match minor version
if SABYENC_VERSION[:3] != SABYENC_VERSION_REQUIRED[:3]:
raise ImportError
except ImportError:
SABYENC_ENABLED = False
@@ -79,6 +80,7 @@ class Decoder(Thread):
self.queue = queue
self.servers = servers
self.__log_decoding = cfg.debug_log_decoding()
def stop(self):
# Put multiple to stop all decoders
@@ -115,7 +117,9 @@ class Decoder(Thread):
if nzo.precheck:
raise BadYenc
register = True
logging.debug("Decoding %s", art_id)
if self.__log_decoding:
logging.debug("Decoding %s", art_id)
data = self.decode(article, lines, raw_data)
nzf.article_count += 1
@@ -127,8 +131,7 @@ class Decoder(Thread):
logging.info("Traceback: ", exc_info=True)
sabnzbd.downloader.Downloader.do.pause()
article.fetcher = None
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(nzf, nzo)
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article)
register = False
except MemoryError, e:
@@ -139,12 +142,11 @@ class Decoder(Thread):
logging.info("Traceback: ", exc_info=True)
sabnzbd.downloader.Downloader.do.pause()
article.fetcher = None
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(nzf, nzo)
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article)
register = False
except CrcError, e:
logme = T('CRC Error in %s (%s -> %s)') % (art_id, e.needcrc, e.gotcrc)
logme = 'CRC Error in %s' % art_id
logging.info(logme)
data = e.data
@@ -312,10 +314,10 @@ class Decoder(Thread):
for server in self.servers:
if server.active and not article.server_in_try_list(server):
if server.priority >= article.fetcher.priority:
article.fetcher = None
article.tries = 0
# Allow all servers for this nzo and nzf again (but not for this article)
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article.nzf, article.nzf.nzo)
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article, article_reset=False)
return True
msg = T('%s => missing from all servers, discarding') % article
@@ -333,7 +335,7 @@ class Decoder(Thread):
return
# Set the md5-of-16k if this is the first article
if article.partnum == nzf.lowest_partnum:
if article.lowest_partnum:
nzf.md5of16k = hashlib.md5(decoded_data[:16384]).digest()
# Try the rename

View File

@@ -20,21 +20,27 @@
##############################################################################
from threading import RLock, Condition
DOWNLOADER_CV = Condition(RLock())
# All operations that modify the queue need to happen in a lock
# Also used when importing NZBs to prevent IO-race conditions
# Names of wrapper-functions should be the same in misc.caller_name
# The NzbQueueLocker both locks and notifies the Downloader
NZBQUEUE_LOCK = RLock()
DOWNLOADER_CV = Condition(NZBQUEUE_LOCK)
def synchronized(lock):
def wrap(f):
def newFunction(*args, **kw):
def call_func(*args, **kw):
lock.acquire()
try:
return f(*args, **kw)
finally:
lock.release()
return newFunction
return call_func
return wrap
def notify_downloader(func):
def NzbQueueLocker(func):
global DOWNLOADER_CV
def call_func(*params, **kparams):
DOWNLOADER_CV.acquire()

View File

@@ -28,19 +28,23 @@ import logging
import sabnzbd
import sabnzbd.cfg as cfg
from sabnzbd.misc import int_conv, clip_path, remove_all, globber, format_time_string, has_win_device
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.encoding import TRANS, unicoder
from sabnzbd.newsunpack import build_command, EXTRACTFROM_RE, rar_volumelist
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
from sabnzbd.utils.diskspeed import diskspeedmeasure
if sabnzbd.WIN32:
# Load the POpen from the fixed unicode-subprocess
from sabnzbd.utils.subprocess_fix import Popen
else:
# Load the regular POpen
from subprocess import Popen
try:
# Use patched version of subprocess module for Unicode on Windows
import subprocessww
except ImportError:
pass
# Load the regular POpen (which is now patched on Windows)
from subprocess import Popen
MAX_ACTIVE_UNPACKERS = 10
ACTIVE_UNPACKERS = []
@@ -150,6 +154,7 @@ class DirectUnpacker(threading.Thread):
last_volume_linebuf = ''
unrar_log = []
rarfiles = []
extracted = []
start_time = time.time()
# Need to read char-by-char because there's no newline after new-disk message
@@ -172,10 +177,21 @@ class DirectUnpacker(threading.Thread):
logging.info('Error in DirectUnpack of %s', self.cur_setname)
self.abort()
if linebuf.startswith('Extracting from') and linebuf.endswith('\n'):
filename = TRANS((re.search(EXTRACTFROM_RE, linebuf.strip()).group(1)))
if filename not in rarfiles:
rarfiles.append(filename)
if linebuf.endswith('\n'):
# List files we used
if linebuf.startswith('Extracting from'):
filename = TRANS((re.search(EXTRACTFROM_RE, linebuf.strip()).group(1)))
if filename not in rarfiles:
rarfiles.append(filename)
# List files we extracted
m = re.search(EXTRACTED_RE, linebuf)
if m:
# In case of flat-unpack, UnRar still prints the whole path (?!)
unpacked_file = TRANS(m.group(2))
if cfg.flat_unpack():
unpacked_file = os.path.basename(unpacked_file)
extracted.append(real_path(self.unpack_dir_info[0], unpacked_file))
# Did we reach the end?
if linebuf.endswith('All OK'):
@@ -185,16 +201,23 @@ class DirectUnpacker(threading.Thread):
# Add to success
rarfile_path = os.path.join(self.nzo.downpath, self.rarfile_nzf.filename)
self.success_sets[self.cur_setname] = rar_volumelist(rarfile_path, self.nzo.password, rarfiles)
self.success_sets[self.cur_setname] = (rar_volumelist(rarfile_path, self.nzo.password, rarfiles), extracted)
logging.info('DirectUnpack completed for %s', self.cur_setname)
self.nzo.set_action_line(T('Direct Unpack'), T('Completed'))
# List success in history-info
msg = T('Unpacked %s files/folders in %s') % (len(extracted), format_time_string(self.unpack_time))
msg = '%s - %s' % (T('Direct Unpack'), msg)
self.nzo.set_unpack_info('Unpack', '[%s] %s' % (unicoder(self.cur_setname), msg))
# Write current log and clear
unrar_log.append(linebuf.strip())
linebuf = ''
last_volume_linebuf = ''
logging.debug('DirectUnpack Unrar output %s', '\n'.join(unrar_log))
unrar_log = []
rarfiles = []
extracted = []
# Are there more files left?
while self.nzo.files and not self.next_sets:
@@ -224,10 +247,15 @@ class DirectUnpacker(threading.Thread):
# Possible that the instance was deleted while locked
if not self.killed:
# Give unrar some time to do it's thing
self.active_instance.stdin.write('\n')
start_time = time.time()
time.sleep(0.1)
# If unrar stopped or is killed somehow, writing will cause a crash
try:
# Give unrar some time to do it's thing
self.active_instance.stdin.write('C\n')
start_time = time.time()
time.sleep(0.1)
except IOError:
self.abort()
break
# Did we unpack a new volume? Sometimes UnRar hangs on 1 volume
if not last_volume_linebuf or last_volume_linebuf != linebuf:
@@ -237,9 +265,12 @@ class DirectUnpacker(threading.Thread):
logging.info('DirectUnpacked volume %s for %s', self.cur_volume, self.cur_setname)
# If lines did not change and we don't have the next volume, this download is missing files!
if last_volume_linebuf == linebuf and not self.have_next_volume():
logging.info('DirectUnpack failed due to missing files %s', self.cur_setname)
self.abort()
if last_volume_linebuf == linebuf:
if not self.have_next_volume():
logging.info('DirectUnpack failed due to missing files %s', self.cur_setname)
self.abort()
else:
logging.debug('Duplicate output line detected: "%s"', last_volume_linebuf)
last_volume_linebuf = linebuf
@@ -252,14 +283,6 @@ class DirectUnpacker(threading.Thread):
unrar_log.append(linebuf.strip())
logging.debug('DirectUnpack Unrar output %s', '\n'.join(unrar_log))
# Save information if success
if self.success_sets:
# The number is wrong if one_folder, just leave empty
nr_files = '' if self.unpack_dir_info[3] else len(globber(self.unpack_dir_info[0]))
msg = T('Unpacked %s files/folders in %s') % (nr_files, format_time_string(self.unpack_time))
msg = '%s - %s' % (T('Direct Unpack'), msg)
self.nzo.set_unpack_info('Unpack', '[%s] %s' % (unicoder(self.cur_setname), msg))
# Make more space
self.reset_active()
if self in ACTIVE_UNPACKERS:
@@ -290,7 +313,14 @@ class DirectUnpacker(threading.Thread):
""" Start the unrar instance using the user's options """
# Generate extraction path and save for post-proc
if not self.unpack_dir_info:
self.unpack_dir_info = prepare_extraction_path(self.nzo)
try:
self.unpack_dir_info = prepare_extraction_path(self.nzo)
except:
# Prevent fatal crash if directory creation fails
self.abort()
return
# Get the information
extraction_path, _, _, one_folder, _ = self.unpack_dir_info
# Set options
@@ -310,13 +340,11 @@ class DirectUnpacker(threading.Thread):
# Generate command
rarfile_path = os.path.join(self.nzo.downpath, self.rarfile_nzf.filename)
if sabnzbd.WIN32:
if not has_win_device(rarfile_path):
command = ['%s' % sabnzbd.newsunpack.RAR_COMMAND, action, '-vp', '-idp', '-o+', '-ai', password_command,
'%s' % clip_path(rarfile_path), clip_path(extraction_path)]
else:
# Need long-path notation in case of forbidden-names
command = ['%s' % sabnzbd.newsunpack.RAR_COMMAND, action, '-vp', '-idp', '-o+', '-ai', password_command,
'%s' % clip_path(rarfile_path), '%s\\' % extraction_path]
# For Unrar to support long-path, we need to cricumvent Python's list2cmdline
# See: https://github.com/sabnzbd/sabnzbd/issues/1043
command = ['%s' % sabnzbd.newsunpack.RAR_COMMAND, action, '-vp', '-idp', '-o+', '-ai', password_command,
'%s' % clip_path(rarfile_path), '%s\\' % long_path(extraction_path)]
else:
# Don't use "-ai" (not needed for non-Windows)
command = ['%s' % sabnzbd.newsunpack.RAR_COMMAND, action, '-vp', '-idp', '-o+', password_command,
@@ -327,9 +355,9 @@ class DirectUnpacker(threading.Thread):
# Let's start from the first one!
self.cur_volume = 1
stup, need_shell, command, creationflags = build_command(command)
stup, need_shell, command, creationflags = build_command(command, flatten_command=True)
logging.debug('Running unrar for DirectUnpack %s', command)
self.active_instance = Popen(command, shell=need_shell, stdin=subprocess.PIPE,
self.active_instance = Popen(command, shell=False, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
startupinfo=stup, creationflags=creationflags)
# Add to runners
@@ -372,8 +400,7 @@ class DirectUnpacker(threading.Thread):
for rm_file in rar_contents:
# Flat-unpack, so remove foldername from RarFile output
f = os.path.join(extraction_path, os.path.basename(rm_file))
logging.debug('Removing file %s', f)
os.remove(f)
remove_file(f)
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)

View File

@@ -31,6 +31,7 @@ import sabnzbd
from sabnzbd.constants import SCAN_FILE_NAME, VALID_ARCHIVES
import sabnzbd.utils.rarfile as rarfile
from sabnzbd.encoding import platform_encode
from sabnzbd.decorators import NzbQueueLocker
from sabnzbd.newsunpack import is_sevenfile, SevenZip
import sabnzbd.nzbstuff as nzbstuff
import sabnzbd.misc as misc
@@ -96,6 +97,7 @@ def is_archive(path):
return 1, None, ''
@NzbQueueLocker
def ProcessArchiveFile(filename, path, pp=None, script=None, cat=None, catdir=None, keep=False,
priority=None, url='', nzbname=None, password=None, nzo_id=None):
""" Analyse ZIP file and create job(s).
@@ -160,7 +162,7 @@ def ProcessArchiveFile(filename, path, pp=None, script=None, cat=None, catdir=No
zf.close()
try:
if not keep:
os.remove(path)
misc.remove_file(path)
except:
logging.error(T('Error removing %s'), misc.clip_path(path))
logging.info("Traceback: ", exc_info=True)
@@ -172,6 +174,7 @@ def ProcessArchiveFile(filename, path, pp=None, script=None, cat=None, catdir=No
return status, nzo_ids
@NzbQueueLocker
def ProcessSingleFile(filename, path, pp=None, script=None, cat=None, catdir=None, keep=False,
priority=None, nzbname=None, reuse=False, nzo_info=None, dup_check=True, url='',
password=None, nzo_id=None):
@@ -246,7 +249,7 @@ def ProcessSingleFile(filename, path, pp=None, script=None, cat=None, catdir=Non
nzo.update_rating()
try:
if not keep:
os.remove(path)
misc.remove_file(path)
except:
logging.error(T('Error removing %s'), misc.clip_path(path))
logging.info("Traceback: ", exc_info=True)

View File

@@ -30,7 +30,7 @@ import sys
import Queue
import sabnzbd
from sabnzbd.decorators import synchronized, notify_downloader, DOWNLOADER_CV
from sabnzbd.decorators import synchronized, NzbQueueLocker, DOWNLOADER_CV
from sabnzbd.constants import MAX_DECODE_QUEUE, LIMIT_DECODE_QUEUE
from sabnzbd.decoder import Decoder
from sabnzbd.newswrapper import NewsWrapper, request_server_info
@@ -256,12 +256,12 @@ class Downloader(Thread):
return
@notify_downloader
@NzbQueueLocker
def set_paused_state(self, state):
""" Set downloader to specified paused state """
self.paused = state
@notify_downloader
@NzbQueueLocker
def resume(self):
# Do not notify when SABnzbd is still starting
if self.paused and sabnzbd.WEB_DIR:
@@ -269,8 +269,8 @@ class Downloader(Thread):
notifier.send_notification("SABnzbd", T('Resuming'), 'download')
self.paused = False
@notify_downloader
def pause(self, save=True):
@NzbQueueLocker
def pause(self):
""" Pause the downloader, optionally saving admin """
if not self.paused:
self.paused = True
@@ -280,14 +280,12 @@ class Downloader(Thread):
BPSMeter.do.reset()
if cfg.autodisconnect():
self.disconnect()
if save:
ArticleCache.do.flush_articles()
def delay(self):
logging.debug("Delaying")
self.delayed = True
@notify_downloader
@NzbQueueLocker
def undelay(self):
logging.debug("Undelaying")
self.delayed = False
@@ -296,7 +294,7 @@ class Downloader(Thread):
logging.info("Waiting for post-processing to finish")
self.postproc = True
@notify_downloader
@NzbQueueLocker
def resume_from_postproc(self):
logging.info("Post-processing finished, resuming download")
self.postproc = False
@@ -540,7 +538,7 @@ class Downloader(Thread):
# Check 10 seconds after enabling slowdown
if self.can_be_slowed_timer and time.time() > self.can_be_slowed_timer + 10:
# Now let's check if it was stable in the last 10 seconds
self.can_be_slowed = (BPSMeter.do.get_stable_speed(timespan=10) > 0)
self.can_be_slowed = BPSMeter.do.get_stable_speed(timespan=10)
self.can_be_slowed_timer = 0
logging.debug('Downloader-slowdown: %r', self.can_be_slowed)
@@ -794,11 +792,8 @@ class Downloader(Thread):
# Too many tries on this server, consider article missing
self.decode(article, None, None)
else:
# Remove this server from try_list
article.fetcher = None
# Allow all servers to iterate over each nzo/nzf again
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article.nzf, article.nzf.nzo)
sabnzbd.nzbqueue.NzbQueue.do.reset_try_lists(article)
if destroy:
nw.terminate(quit=quit)
@@ -863,7 +858,7 @@ class Downloader(Thread):
del self._timers[server_id]
self.init_server(server_id, server_id)
@notify_downloader
@NzbQueueLocker
@synchronized(TIMER_LOCK)
def unblock(self, server_id):
# Remove timer
@@ -882,7 +877,7 @@ class Downloader(Thread):
for server_id in self._timers.keys():
self.unblock(server_id)
@notify_downloader
@NzbQueueLocker
@synchronized(TIMER_LOCK)
def check_timers(self):
""" Make sure every server without a non-expired timer is active """
@@ -905,7 +900,7 @@ class Downloader(Thread):
def update_server(self, oldserver, newserver):
self.init_server(oldserver, newserver)
@notify_downloader
@NzbQueueLocker
def wakeup(self):
""" Just rattle the semaphore """
pass

View File

@@ -149,6 +149,8 @@ def send(message, email_to, test=None):
else:
logging.info("Notification e-mail successfully sent")
return T('Email succeeded')
else:
return T('Cannot send, missing required data')
def get_email_date():
@@ -218,7 +220,7 @@ def send_with_template(prefix, parm, test=None):
def endjob(filename, cat, status, path, bytes, fail_msg, stages, script, script_output, script_ret, test=None):
""" Send end-of-job email """
# Is it allowed?
if not check_cat('email', cat):
if not check_cat('misc', cat, keyword='email') and not test:
return None
# Translate the stage names

View File

@@ -70,19 +70,6 @@ def yenc_name_fixer(p):
return p.decode('cp1252', errors='replace').replace('?', '!')
def is_utf8(p):
""" Return True when p is UTF-8 or plain ASCII """
utf8 = True
try:
p.decode('ascii')
except:
try:
p.decode('utf-8')
except:
utf8 = False
return utf8
def special_fixer(p):
""" Return string appropriate for the platform.
Also takes care of the situation where a non-Windows/UTF-8 system
@@ -218,7 +205,11 @@ def TRANS(p):
"""
global gTABLE_850_LATIN
if sabnzbd.WIN32:
return p.translate(gTABLE_850_LATIN).decode('cp1252', 'replace')
if p:
return p.translate(gTABLE_850_LATIN).decode('cp1252', 'replace')
else:
# translate() fails on empty or None strings
return ''
else:
return unicoder(p)
@@ -229,7 +220,11 @@ def UNTRANS(p):
"""
global gTABLE_LATIN_850
if sabnzbd.WIN32:
return p.encode('cp1252', 'replace').translate(gTABLE_LATIN_850)
if p:
return p.encode('cp1252', 'replace').translate(gTABLE_LATIN_850)
else:
# translate() fails on empty or None strings
return ''
else:
return p

View File

@@ -39,7 +39,7 @@ import sabnzbd.scheduler as scheduler
from Cheetah.Template import Template
from sabnzbd.misc import real_path, to_units, from_units, \
time_format, long_path, calc_age, \
time_format, long_path, calc_age, same_file, \
cat_to_opts, int_conv, globber, globber_full, remove_all, get_base_url
from sabnzbd.newswrapper import GetServerParms
from sabnzbd.rating import Rating
@@ -325,7 +325,7 @@ class MainPage(object):
if not check_login():
raise NeedLogin()
if not cfg.notified_new_skin() and cfg.web_dir() not in ('Glitter', 'Plush'):
if not cfg.notified_new_skin() and cfg.web_dir() != 'Glitter':
logging.warning(T('Try our new skin Glitter! Fresh new design that is optimized for desktop and mobile devices. Go to Config -> General to change your skin.'))
if not cfg.notified_new_skin():
cfg.notified_new_skin.set(1)
@@ -1373,7 +1373,7 @@ class ConfigSwitches(object):
SPECIAL_BOOL_LIST = \
('start_paused', 'no_penalties', 'ignore_wrong_unrar', 'overwrite_files', 'enable_par_cleanup',
'queue_complete_pers', 'api_warnings', 'ampm', 'enable_unrar', 'enable_unzip', 'enable_7zip',
'enable_filejoin', 'enable_tsjoin', 'ignore_unrar_dates',
'enable_filejoin', 'enable_tsjoin', 'ignore_unrar_dates', 'debug_log_decoding',
'multipar', 'osx_menu', 'osx_speed', 'win_menu', 'use_pickle', 'allow_incomplete_nzb',
'rss_filenames', 'ipv6_hosting', 'keep_awake', 'empty_postproc', 'html_login', 'wait_for_dfolder',
'max_art_opt', 'warn_empty_nzb', 'enable_bonjour', 'reject_duplicate_files', 'warn_dupl_jobs',
@@ -2076,7 +2076,7 @@ class ConfigRss(object):
prio = att.get('prio')
if url:
sabnzbd.add_url(url, pp, script, cat, prio, nzbname, feed_name=feed)
sabnzbd.add_url(url, pp, script, cat, prio, nzbname)
# Need to pass the title instead
sabnzbd.rss.flag_downloaded(feed, url)
raise rssRaiser(self.__root, kwargs)
@@ -2349,12 +2349,17 @@ class ConfigCats(object):
else:
newname = re.sub('"', '', kwargs.get('newname', ''))
if newname:
if name:
config.delete('categories', name)
name = newname.lower()
if kwargs.get('dir'):
kwargs['dir'] = platform_encode(kwargs['dir'])
config.ConfigCat(name, kwargs)
# Check if this cat-dir is not sub-folder of incomplete
if same_file(cfg.download_dir.get_path(), real_path(cfg.complete_dir.get_path(), kwargs['dir'])):
return T('Category folder cannot be a subfolder of the Temporary Download Folder.')
# Delete current one and replace with new one
if name:
config.delete('categories', name)
config.ConfigCat(newname.lower(), kwargs)
config.save_config()
raise Raiser(self.__root)
@@ -2734,7 +2739,7 @@ LIST_PROWL = ('prowl_enable', 'prowl_cats', 'prowl_apikey',
LIST_PUSHOVER = ('pushover_enable', 'pushover_cats', 'pushover_token', 'pushover_userkey', 'pushover_device',
'pushover_prio_startup', 'pushover_prio_download', 'pushover_prio_pp', 'pushover_prio_complete', 'pushover_prio_failed',
'pushover_prio_disk_full', 'pushover_prio_warning', 'pushover_prio_error', 'pushover_prio_queue_done', 'pushover_prio_other',
'pushover_prio_new_login')
'pushover_prio_new_login', 'pushover_emergency_retry', 'pushover_emergency_expire')
LIST_PUSHBULLET = ('pushbullet_enable', 'pushbullet_cats', 'pushbullet_apikey', 'pushbullet_device',
'pushbullet_prio_startup', 'pushbullet_prio_download', 'pushbullet_prio_pp', 'pushbullet_prio_complete', 'pushbullet_prio_failed',
'pushbullet_prio_disk_full', 'pushbullet_prio_warning', 'pushbullet_prio_error', 'pushbullet_prio_queue_done', 'pushbullet_prio_other',

View File

@@ -32,6 +32,8 @@ import time
import datetime
import fnmatch
import stat
import inspect
import urllib2
from urlparse import urlparse
import sabnzbd
@@ -166,7 +168,7 @@ def cat_to_opts(cat, pp=None, script=None, priority=None):
if safe_lower(script) in ('', 'default'):
script = def_cat.script()
if priority is None or priority == DEFAULT_PRIORITY:
if priority is None or priority == '' or priority == DEFAULT_PRIORITY:
priority = my_cat.priority()
if priority == DEFAULT_PRIORITY:
priority = def_cat.priority()
@@ -736,12 +738,12 @@ def from_units(val):
return 0.0
def to_units(val, spaces=0, dec_limit=2, postfix=''):
def to_units(val, spaces=0, postfix=''):
""" Convert number to K/M/G/T/P notation
Add "spaces" if not ending in letter
dig_limit==1 show single decimal for M and higher
dig_limit==2 show single decimal for G and higher
Show single decimal for M and higher
"""
dec_limit = 1
decimals = 0
if val < 0:
sign = '-'
@@ -769,6 +771,31 @@ def to_units(val, spaces=0, dec_limit=2, postfix=''):
return fmt % (sign, val, unit, postfix)
def caller_name(skip=2):
"""Get a name of a caller in the format module.method
Originally used: https://gist.github.com/techtonik/2151727
Adapted for speed by using sys calls directly
"""
# Only do the tracing on Debug (function is always called)
if cfg.log_level() != 2:
return 'N/A'
parentframe = sys._getframe(skip)
function_name = parentframe.f_code.co_name
# Modulename not available in the binaries, we can use the filename instead
if getattr(sys, 'frozen', None):
module_name = inspect.getfile(parentframe)
else:
module_name = inspect.getmodule(parentframe).__name__
# For decorated functions we have to go deeper
if function_name in ('call_func', 'wrap') and skip == 2:
return caller_name(4)
return ".".join([module_name, function_name])
def same_file(a, b):
""" Return 0 if A and B have nothing in common
return 1 if A and B are actually the same path
@@ -819,6 +846,14 @@ def split_host(srv):
return (host, port)
def get_from_url(url):
""" Retrieve URL and return content """
try:
return urllib2.urlopen(url).read()
except:
return None
def check_mount(path):
""" Return False if volume isn't mounted on Linux or OSX
Retry 6 times with an interval of 1 sec.
@@ -922,7 +957,7 @@ def move_to_path(path, new_path):
new_path = os.path.abspath(new_path)
if overwrite and os.path.exists(new_path):
try:
os.remove(new_path)
remove_file(new_path)
except:
overwrite = False
if not overwrite:
@@ -940,7 +975,7 @@ def move_to_path(path, new_path):
if not os.path.exists(os.path.dirname(new_path)):
create_dirs(os.path.dirname(new_path))
shutil.copyfile(path, new_path)
os.remove(path)
remove_file(path)
except:
# Check if the old-file actually exists (possible delete-delays)
if not os.path.exists(path):
@@ -1055,12 +1090,11 @@ def renamer(old, new):
@synchronized(DIR_LOCK)
def remove_dir(path):
""" Remove directory with retries for Win32 """
logging.debug('Removing dir %s', path)
if sabnzbd.WIN32:
retries = 15
while retries > 0:
try:
os.rmdir(path)
remove_dir(path)
return
except WindowsError, err:
if err[0] == 32:
@@ -1071,7 +1105,7 @@ def remove_dir(path):
time.sleep(3)
raise WindowsError(err)
else:
os.rmdir(path)
remove_dir(path)
@synchronized(DIR_LOCK)
@@ -1085,20 +1119,30 @@ def remove_all(path, pattern='*', keep_folder=False, recursive=False):
for f in files:
if os.path.isfile(f):
try:
logging.debug('Removing file %s', f)
os.remove(f)
remove_file(f)
except:
logging.info('Cannot remove file %s', f)
elif recursive:
remove_all(f, pattern, False, True)
if not keep_folder:
try:
logging.debug('Removing dir %s', path)
os.rmdir(path)
remove_dir(path)
except:
logging.info('Cannot remove folder %s', path)
def remove_file(path):
""" Wrapper function so any file removal is logged """
logging.debug('[%s] Deleting file %s', caller_name(), path)
os.remove(path)
def remove_dir(dir):
""" Wrapper function so any dir removal is logged """
logging.debug('[%s] Deleting dir %s', caller_name(), dir)
os.rmdir(dir)
def trim_win_path(path):
""" Make sure Windows path stays below 70 by trimming last part """
if sabnzbd.WIN32 and len(path) > 69:

View File

@@ -33,7 +33,7 @@ from sabnzbd.encoding import TRANS, UNTRANS, unicoder, platform_encode, deunicod
import sabnzbd.utils.rarfile as rarfile
from sabnzbd.misc import format_time_string, find_on_path, make_script_path, int_conv, \
real_path, globber, globber_full, get_all_passwords, renamer, clip_path, \
has_win_device, calc_age, long_path
has_win_device, calc_age, long_path, remove_file
from sabnzbd.tvsort import SeriesSorter
import sabnzbd.cfg as cfg
from sabnzbd.constants import Status
@@ -43,10 +43,11 @@ if sabnzbd.WIN32:
import win32api
from win32con import SW_HIDE
from win32process import STARTF_USESHOWWINDOW, IDLE_PRIORITY_CLASS
# Use patched version of subprocess module for Unicode on Windows
import subprocessww
except ImportError:
pass
# Load the POpen from the fixed unicode-subprocess
from sabnzbd.utils.subprocess_fix import Popen
else:
# Define dummy WindowsError for non-Windows
class WindowsError(Exception):
@@ -55,8 +56,9 @@ else:
def __str__(self):
return repr(self.parameter)
# Load the regular POpen
from subprocess import Popen
# Load the regular POpen (which is now patched on Windows)
from subprocess import Popen
# Regex globals
RAR_RE = re.compile(r'\.(?P<ext>part\d*\.rar|rar|r\d\d|s\d\d|t\d\d|u\d\d|v\d\d|\d\d\d)$', re.I)
@@ -65,6 +67,7 @@ RAR_RE_V3 = re.compile(r'\.(?P<ext>part\d*)$', re.I)
LOADING_RE = re.compile(r'^Loading "(.+)"')
TARGET_RE = re.compile(r'^(?:File|Target): "(.+)" -')
EXTRACTFROM_RE = re.compile(r'^Extracting\sfrom\s(.+)')
EXTRACTED_RE = re.compile(r'^(Extracting|Creating|...)\s+(.*?)\s+OK\s*$')
SPLITFILE_RE = re.compile(r'\.(\d\d\d$)', re.I)
ZIP_RE = re.compile(r'\.(zip$)', re.I)
SEVENZIP_RE = re.compile(r'\.7z$', re.I)
@@ -107,7 +110,6 @@ def find_programs(curdir):
sabnzbd.newsunpack.MULTIPAR_COMMAND = check(curdir, 'win/par2/multipar/par2j.exe')
sabnzbd.newsunpack.RAR_COMMAND = check(curdir, 'win/unrar/UnRAR.exe')
sabnzbd.newsunpack.PAR2_COMMAND = check(curdir, 'win/par2/par2.exe')
sabnzbd.newsunpack.ZIP_COMMAND = check(curdir, 'win/unzip/unzip.exe')
sabnzbd.newsunpack.SEVEN_COMMAND = check(curdir, 'win/7zip/7za.exe')
else:
if not sabnzbd.newsunpack.PAR2_COMMAND:
@@ -139,12 +141,12 @@ ENV_NZO_FIELDS = ['bytes', 'bytes_downloaded', 'bytes_tried', 'cat', 'duplicate'
def external_processing(extern_proc, nzo, complete_dir, nicename, status):
""" Run a user postproc script, return console output and exit value """
command = [str(extern_proc), str(complete_dir), str(nzo.filename),
str(nicename), '', str(nzo.cat), str(nzo.group), str(status)]
failure_url = nzo.nzo_info.get('failure', '')
if failure_url:
command.append(str(failure_url))
command = [str(extern_proc), str(complete_dir), str(nzo.filename), str(nicename), '',
str(nzo.cat), str(nzo.group), str(status), str(failure_url)]
# Add path to original NZB
nzb_paths = globber_full(nzo.workpath, '*.gz')
# Fields not in the NZO directly
extra_env_fields = {'failure_url': failure_url,
@@ -153,6 +155,13 @@ def external_processing(extern_proc, nzo, complete_dir, nicename, status):
'download_time': nzo.nzo_info.get('download_time', ''),
'avg_bps': int(nzo.avg_bps_total / nzo.avg_bps_freq) if nzo.avg_bps_freq else 0,
'age': calc_age(nzo.avg_date),
'orig_nzb_gz': clip_path(nzb_paths[0]) if nzb_paths else '',
'program_dir': sabnzbd.DIR_PROG,
'par2_command': sabnzbd.newsunpack.PAR2_COMMAND,
'multipar_command': sabnzbd.newsunpack.MULTIPAR_COMMAND,
'rar_command': sabnzbd.newsunpack.RAR_COMMAND,
'zip_command': sabnzbd.newsunpack.ZIP_COMMAND,
'7zip_command': sabnzbd.newsunpack.SEVEN_COMMAND,
'version': sabnzbd.__version__}
try:
@@ -178,6 +187,9 @@ def external_processing(extern_proc, nzo, complete_dir, nicename, status):
line = line.strip()
lines.append(line)
# Show current line in history
nzo.set_action_line(T('Running script'), unicoder(line))
# Check if we should still continue
if not nzo.pp_active:
p.kill()
@@ -255,16 +267,6 @@ def unpack_magic(nzo, workdir, workdir_complete, dele, one_folder, joinables, zi
nzo.set_action_line()
rerun = not error
if cfg.enable_unzip():
new_zips = [zip for zip in xzips if zip not in zips]
if new_zips:
logging.info('Unzip starting on %s', workdir)
if unzip(nzo, workdir, workdir_complete, dele, one_folder, new_zips):
error = 1
logging.info('Unzip finished on %s', workdir)
nzo.set_action_line()
rerun = not error
if cfg.enable_7zip():
new_sevens = [seven for seven in xsevens if seven not in sevens]
if new_sevens:
@@ -275,6 +277,20 @@ def unpack_magic(nzo, workdir, workdir_complete, dele, one_folder, joinables, zi
nzo.set_action_line()
rerun = not error
if cfg.enable_unzip():
new_zips = [zip for zip in xzips if zip not in zips]
if new_zips:
logging.info('Unzip starting on %s', workdir)
if SEVEN_COMMAND:
if unseven(nzo, workdir, workdir_complete, dele, one_folder, new_zips):
error = True
else:
if unzip(nzo, workdir, workdir_complete, dele, one_folder, new_zips):
error = True
logging.info('Unzip finished on %s', workdir)
nzo.set_action_line()
rerun = not error
if cfg.enable_tsjoin():
new_ts = [_ts for _ts in xts if _ts not in ts]
if new_ts:
@@ -330,16 +346,14 @@ def clean_up_joinables(names):
""" Remove joinable files and their .1 backups """
for name in names:
if os.path.exists(name):
logging.debug("Deleting %s", name)
try:
os.remove(name)
remove_file(name)
except:
pass
name1 = name + ".1"
if os.path.exists(name1):
logging.debug("Deleting %s", name1)
try:
os.remove(name1)
remove_file(name1)
except:
pass
@@ -415,8 +429,7 @@ def file_join(nzo, workdir, workdir_complete, delete, joinables):
shutil.copyfileobj(f, joined_file, bufsize)
f.close()
if delete:
logging.debug("Deleting %s", joinable)
os.remove(joinable)
remove_file(joinable)
n += 1
# Remove any remaining .1 files
@@ -480,20 +493,30 @@ def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
# Is the direct-unpacker still running? We wait for it
if nzo.direct_unpacker:
wait_count = 0
last_stats = nzo.direct_unpacker.get_formatted_stats()
while nzo.direct_unpacker.is_alive():
logging.debug('DirectUnpacker still alive for %s', nzo)
logging.debug('DirectUnpacker still alive for %s: %s', nzo.work_name, last_stats)
# Bump the file-lock in case it's stuck
with nzo.direct_unpacker.next_file_lock:
nzo.direct_unpacker.next_file_lock.notify()
time.sleep(2)
# Did something change? Might be stuck
if last_stats == nzo.direct_unpacker.get_formatted_stats():
wait_count += 1
if wait_count > 60:
# We abort after 2 minutes of no changes
nzo.direct_unpacker.abort()
last_stats = nzo.direct_unpacker.get_formatted_stats()
# Did we already direct-unpack it? Not when recursive-unpacking
if nzo.direct_unpacker and rar_set in nzo.direct_unpacker.success_sets:
logging.info("Set %s completed by DirectUnpack", rar_set)
fail = False
success = True
rars = nzo.direct_unpacker.success_sets.pop(rar_set)
newfiles = globber(extraction_path)
rars, newfiles = nzo.direct_unpacker.success_sets.pop(rar_set)
else:
logging.info("Extracting rarfile %s (belonging to %s) to %s",
rarpath, rar_set, extraction_path)
@@ -541,9 +564,8 @@ def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
# Delete the old files if we have to
if success and delete and newfiles:
for rar in rars:
logging.info("Deleting %s", rar)
try:
os.remove(rar)
remove_file(rar)
except OSError:
if os.path.exists(rar):
logging.warning(T('Deleting %s failed!'), rar)
@@ -553,7 +575,7 @@ def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
if os.path.exists(brokenrar):
logging.info("Deleting %s", brokenrar)
try:
os.remove(brokenrar)
remove_file(brokenrar)
except OSError:
if os.path.exists(brokenrar):
logging.warning(T('Deleting %s failed!'), brokenrar)
@@ -613,18 +635,10 @@ def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction
rename = '-or' # Auto renaming
if sabnzbd.WIN32:
# Use all flags
if not has_win_device(rarfile_path):
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, '-ai', password_command,
'%s' % clip_path(rarfile_path), clip_path(extraction_path)]
else:
# Need long-path notation in case of forbidden-names
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, '-ai', password_command,
'%s' % clip_path(rarfile_path), '%s\\' % extraction_path]
# The subprocess_fix requires time to clear the buffers to work,
# otherwise the inputs get send incorrectly and unrar breaks
time.sleep(0.5)
# For Unrar to support long-path, we need to cricumvent Python's list2cmdline
# See: https://github.com/sabnzbd/sabnzbd/issues/1043
command = ['%s' % RAR_COMMAND, action, '-idp', overwrite, rename, '-ai', password_command,
'%s' % clip_path(rarfile_path), '%s\\' % long_path(extraction_path)]
elif RAR_PROBLEM:
# Use only oldest options (specifically no "-or")
@@ -638,7 +652,7 @@ def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction
if cfg.ignore_unrar_dates():
command.insert(3, '-tsm-')
stup, need_shell, command, creationflags = build_command(command)
stup, need_shell, command, creationflags = build_command(command, flatten_command=True)
# Get list of all the volumes part of this set
logging.debug("Analyzing rar file ... %s found", rarfile.is_rarfile(rarfile_path))
@@ -791,9 +805,13 @@ def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction
fail = 3
else:
m = re.search(r'^(Extracting|Creating|...)\s+(.*?)\s+OK\s*$', line)
m = re.search(EXTRACTED_RE, line)
if m:
extracted.append(real_path(extraction_path, TRANS(m.group(2))))
# In case of flat-unpack, UnRar still prints the whole path (?!)
unpacked_file = TRANS(m.group(2))
if cfg.flat_unpack():
unpacked_file = os.path.basename(unpacked_file)
extracted.append(real_path(extraction_path, unpacked_file))
if fail:
if proc:
@@ -853,9 +871,8 @@ def unzip(nzo, workdir, workdir_complete, delete, one_folder, zips):
i = 0
for _zip in zips:
logging.info("Deleting %s", _zip)
try:
os.remove(_zip)
remove_file(_zip)
i += 1
except OSError:
logging.warning(T('Deleting %s failed!'), _zip)
@@ -863,9 +880,8 @@ def unzip(nzo, workdir, workdir_complete, delete, one_folder, zips):
brokenzip = '%s.1' % _zip
if os.path.exists(brokenzip):
logging.info("Deleting %s", brokenzip)
try:
os.remove(brokenzip)
remove_file(brokenzip)
i += 1
except OSError:
logging.warning(T('Deleting %s failed!'), brokenzip)
@@ -1000,7 +1016,7 @@ def seven_extract_core(sevenset, extensions, extraction_path, one_folder, delete
parm = '-tsplit'
else:
name = sevenset
parm = '-t7z'
parm = '-tzip' if sevenset.lower().endswith('.zip') else '-t7z'
if not os.path.exists(name):
return 1, T('7ZIP set "%s" is incomplete, cannot unpack') % unicoder(sevenset)
@@ -1024,12 +1040,12 @@ def seven_extract_core(sevenset, extensions, extraction_path, one_folder, delete
for ext in extensions:
path = '%s.%s' % (sevenset, ext)
try:
os.remove(path)
remove_file(path)
except:
logging.warning(T('Deleting %s failed!'), path)
else:
try:
os.remove(sevenset)
remove_file(sevenset)
except:
logging.warning(T('Deleting %s failed!'), sevenset)
@@ -1077,9 +1093,8 @@ def par2_repair(parfile_nzf, nzo, workdir, setname, single):
# Download all par2 files that haven't been downloaded yet
readd = False
for extrapar in nzo.extrapars[setname][:]:
if extrapar not in nzo.finished_files and extrapar not in nzo.files:
nzo.add_parfile(extrapar)
readd = True
nzo.add_parfile(extrapar)
readd = True
if readd:
return readd, result
@@ -1146,9 +1161,8 @@ def par2_repair(parfile_nzf, nzo, workdir, setname, single):
if filepath in joinables:
joinables.remove(filepath)
if os.path.exists(filepath):
logging.info("Deleting %s", filepath)
try:
os.remove(filepath)
remove_file(filepath)
except OSError:
logging.warning(T('Deleting %s failed!'), filepath)
except:
@@ -1296,8 +1310,10 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False):
verifynum = 0
elif line.startswith('Main packet not found') or 'The recovery file does not exist' in line:
# Initialparfile probably didn't decode properly,
logging.info(T('Main packet not found...'))
# Initialparfile probably didn't decode properly or bad user parameters
# We will try to get another par2 file, but 99% of time it's user parameters
msg = T('Invalid par2 files or invalid PAR2 parameters, cannot verify or repair')
logging.info(msg)
logging.info("Extra pars = %s", nzo.extrapars[setname])
# Look for the smallest par2file
@@ -1315,7 +1331,6 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False):
nzo.add_parfile(nzf)
readd = True
else:
msg = T('Invalid par2 files or invalid PAR2 parameters, cannot verify or repair')
nzo.fail_msg = msg
msg = u'[%s] %s' % (unicoder(setname), msg)
nzo.set_unpack_info('Repair', msg)
@@ -1331,7 +1346,6 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False):
if added_blocks:
msg = T('Fetching %s blocks...') % str(added_blocks)
nzo.set_action_line(T('Fetching'), msg)
nzo.status = Status.FETCHING
readd = True
else:
# Failed
@@ -1440,6 +1454,15 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False):
nzo.set_unpack_info('Repair', msg)
nzo.status = Status.FAILED
elif line.startswith('Repair Failed.'):
# Unknown repair problem
msg = T('Repairing failed, %s') % line
nzo.fail_msg = msg
msg = u'[%s] %s' % (unicoder(setname), msg)
nzo.set_unpack_info('Repair', msg)
nzo.status = Status.FAILED
finished = 0
elif not verified:
if line.startswith('Verifying source files'):
nzo.set_action_line(T('Verifying'), '01/%02d' % verifytotal)
@@ -1474,6 +1497,10 @@ def PAR_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False):
except WindowsError, err:
raise WindowsError(err)
# Also log what is shown to user in history
if nzo.fail_msg:
logging.info(nzo.fail_msg)
logging.debug('PAR2 output was\n%s', '\n'.join(lines))
# If successful, add renamed files to the collection
@@ -1503,9 +1530,16 @@ def MultiPar_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False)
# But not really required due to prospective-par2
command = [str(MULTIPAR_COMMAND), 'r', '-vs2', '-vd%s' % parfolder, parfile]
# Check if there are maybe par2cmdline/par2tbb commands supplied
if '-t' in cfg.par_option() or '-p' in cfg.par_option():
logging.info('Removing old par2cmdline/par2tbb options for MultiPar')
cfg.par_option.set('')
# Only add user-options if supplied
options = cfg.par_option().strip()
if options:
# We wrongly instructed users to use /x parameter style instead of -x
options = options.replace('/', '-', 1)
command.insert(2, options)
# Append the wildcard for this set
@@ -1589,8 +1623,10 @@ def MultiPar_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False)
logging.error(msg)
elif line.startswith('valid file is not found'):
# Initialparfile probably didn't decode properly,
logging.info(T('Main packet not found...'))
# Initialparfile probably didn't decode properly, or bad user parameters
# We will try to get another par2 file, but 99% of time it's user parameters
msg = T('Invalid par2 files or invalid PAR2 parameters, cannot verify or repair')
logging.info(msg)
logging.info("Extra pars = %s", nzo.extrapars[setname])
# Look for the smallest par2file
@@ -1608,7 +1644,6 @@ def MultiPar_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False)
nzo.add_parfile(nzf)
readd = True
else:
msg = T('Invalid par2 files or invalid PAR2 parameters, cannot verify or repair')
nzo.fail_msg = msg
msg = u'[%s] %s' % (unicoder(setname), msg)
nzo.set_unpack_info('Repair', msg)
@@ -1753,7 +1788,6 @@ def MultiPar_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False)
if added_blocks:
msg = T('Fetching %s blocks...') % str(added_blocks)
nzo.set_action_line(T('Fetching'), msg)
nzo.status = Status.FETCHING
readd = True
else:
# Failed
@@ -1763,6 +1797,10 @@ def MultiPar_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False)
nzo.set_unpack_info('Repair', msg)
nzo.status = Status.FAILED
# MultiPar can say 'PAR File(s) Incomplete' also when it needs more blocks
# But the Need-more-blocks message is always last, so force failure
finished = 0
# Result of verification
elif line.startswith('All Files Complete') or line.endswith('PAR File(s) Incomplete'):
# Completed without damage!
@@ -1818,9 +1856,21 @@ def MultiPar_Verify(parfile, parfile_nzf, nzo, setname, joinables, single=False)
verifynum += 1
nzo.set_action_line(T('Verifying repair'), '%02d/%02d' % (verifynum, verifytotal))
elif line.startswith('Failed to repair'):
# Unknown repair problem
msg = T('Repairing failed, %s') % line
nzo.fail_msg = msg
msg = u'[%s] %s' % (unicoder(setname), msg)
nzo.set_unpack_info('Repair', msg)
nzo.status = Status.FAILED
finished = 0
p.wait()
# Also log what is shown to user in history
if nzo.fail_msg:
logging.info(nzo.fail_msg)
logging.debug('MultiPar output was\n%s', '\n'.join(lines))
# Add renamed files to the collection
@@ -1850,6 +1900,7 @@ def create_env(nzo=None, extra_env_fields=None):
# Are we adding things?
if nzo:
# Add basic info
for field in ENV_NZO_FIELDS:
try:
field_value = getattr(nzo, field)
@@ -1859,14 +1910,18 @@ def create_env(nzo=None, extra_env_fields=None):
elif isinstance(field_value, bool):
env['SAB_' + field.upper()] = str(field_value*1)
else:
env['SAB_' + field.upper()] = str(deunicode(field_value))
env['SAB_' + field.upper()] = str(field_value)
except:
# Catch key/unicode errors
pass
# Add extra fields
for field in extra_env_fields:
try:
env['SAB_' + field.upper()] = str(deunicode(extra_env_fields[field]))
if extra_env_fields[field] is not None:
env['SAB_' + field.upper()] = str(extra_env_fields[field])
else:
env['SAB_' + field.upper()] = ''
except:
# Catch key/unicode errors
pass
@@ -1879,6 +1934,9 @@ def create_env(nzo=None, extra_env_fields=None):
elif not nzo:
# No modification
return None
# Have to make sure no Unicode slipped in somehow
env = { deunicode(k): deunicode(v) for k, v in env.iteritems() }
return env
@@ -1896,8 +1954,10 @@ def userxbit(filename):
return xbitset
def build_command(command):
""" Prepare list from running an external program """
def build_command(command, flatten_command=False):
""" Prepare list from running an external program
On Windows we need to run our own list2cmdline for Unrar
"""
if not sabnzbd.WIN32:
if command[0].endswith('.py'):
with open(command[0], 'r') as script_file:
@@ -1941,7 +2001,7 @@ def build_command(command):
if need_shell and ' ' in command[0]:
command[0] = win32api.GetShortPathName(command[0])
if need_shell:
if need_shell or flatten_command:
command = list2cmdline(command)
return stup, need_shell, command, creationflags
@@ -1952,16 +2012,20 @@ def rar_volumelist(rarfile_path, password, known_volumes):
and merge them with existing list, removing duplicates
"""
# UnRar is required to read some RAR files
rarfile.UNRAR_TOOL = RAR_COMMAND
zf = rarfile.RarFile(rarfile_path)
# RarFile can fail in special cases
try:
rarfile.UNRAR_TOOL = RAR_COMMAND
zf = rarfile.RarFile(rarfile_path)
# setpassword can fail due to bugs in RarFile
if password:
try:
zf.setpassword(password)
except:
pass
zf_volumes = zf.volumelist()
# setpassword can fail due to bugs in RarFile
if password:
try:
zf.setpassword(password)
except:
pass
zf_volumes = zf.volumelist()
except:
zf_volumes = []
# Remove duplicates
known_volumes_base = [os.path.basename(vol) for vol in known_volumes]
@@ -2228,7 +2292,7 @@ def pre_queue(name, pp, cat, script, priority, size, groups):
values = [1, name, pp, cat, script, priority, None]
script_path = make_script_path(cfg.pre_script())
if script_path:
command = [script_path, name, fix(pp), fix(cat), fix(script), fix(priority), str(size), ' '.join(groups)]
command = [script_path, name, pp, fix(cat), fix(script), priority, str(size), ' '.join(groups)]
command.extend(analyse_show(name))
try:
@@ -2249,7 +2313,7 @@ def pre_queue(name, pp, cat, script, priority, size, groups):
n = 0
for line in output.split('\n'):
line = line.strip('\r\n \'"')
if n < len(values) and line:
if n < len(values):
values[n] = TRANS(line)
n += 1
accept = int_conv(values[0])
@@ -2269,24 +2333,11 @@ def list2cmdline(lst):
for arg in lst:
if not arg:
nlst.append('""')
elif (' ' in arg) or ('\t' in arg) or ('&' in arg) or ('|' in arg) or (';' in arg) or (',' in arg):
nlst.append('"%s"' % arg)
else:
nlst.append(arg)
nlst.append('"%s"' % arg)
return ' '.join(nlst)
def get_from_url(url):
""" Retrieve URL and return content
`timeout` sets non-standard timeout
"""
import urllib2
try:
return urllib2.urlopen(url).read()
except:
return None
def is_sevenfile(path):
""" Return True if path has proper extension and 7Zip is installed """
return SEVEN_COMMAND and os.path.splitext(path)[1].lower() == '.7z'

View File

@@ -27,7 +27,6 @@ import socket
import urllib2
import httplib
import urllib
import time
import subprocess
import json
from threading import Thread
@@ -134,13 +133,17 @@ def get_prio(gtype, section):
return -1000
def check_cat(section, job_cat):
""" Check if `job_cat` is enabled in `section`. * = All """
def check_cat(section, job_cat, keyword=None):
""" Check if `job_cat` is enabled in `section`.
* = All, if no other categories selected.
"""
if not job_cat:
return True
try:
section_cats = sabnzbd.config.get_config(section, '%s_cats' % section)()
return ('*' in section_cats or job_cat in section_cats)
if not keyword:
keyword = section
section_cats = sabnzbd.config.get_config(section, '%s_cats' % keyword)()
return (['*'] == section_cats or job_cat in section_cats)
except TypeError:
logging.debug('Incorrect Notify option %s:%s_cats', section, section)
return True
@@ -164,31 +167,26 @@ def send_notification(title, msg, gtype, job_cat=None):
return send_local_growl(title, msg, gtype)
else:
Thread(target=send_growl, args=(title, msg, gtype)).start()
time.sleep(0.5)
# Prowl
if sabnzbd.cfg.prowl_enable() and check_cat('prowl', job_cat):
if sabnzbd.cfg.prowl_apikey():
Thread(target=send_prowl, args=(title, msg, gtype)).start()
time.sleep(0.5)
# Pushover
if sabnzbd.cfg.pushover_enable() and check_cat('pushover', job_cat):
if sabnzbd.cfg.pushover_token():
Thread(target=send_pushover, args=(title, msg, gtype)).start()
time.sleep(0.5)
# Pushbullet
if sabnzbd.cfg.pushbullet_enable() and check_cat('pushbullet', job_cat):
if sabnzbd.cfg.pushbullet_apikey() and check_classes(gtype, 'pushbullet'):
Thread(target=send_pushbullet, args=(title, msg, gtype)).start()
time.sleep(0.5)
# Notification script.
if sabnzbd.cfg.nscript_enable() and check_cat('nscript', job_cat):
if sabnzbd.cfg.nscript_script():
Thread(target=send_nscript, args=(title, msg, gtype)).start()
time.sleep(0.5)
# NTFOSD
if have_ntfosd() and sabnzbd.cfg.ntfosd_enable():
@@ -443,6 +441,8 @@ def send_pushover(title, msg, gtype, force=False, test=None):
apikey = sabnzbd.cfg.pushover_token()
userkey = sabnzbd.cfg.pushover_userkey()
device = sabnzbd.cfg.pushover_device()
emergency_retry = sabnzbd.cfg.pushover_emergency_retry()
emergency_expire = sabnzbd.cfg.pushover_emergency_expire()
if not apikey or not userkey:
return T('Cannot send, missing required data')
@@ -452,27 +452,42 @@ def send_pushover(title, msg, gtype, force=False, test=None):
if force:
prio = 1
if prio > -3:
try:
conn = httplib.HTTPSConnection("api.pushover.net:443")
conn.request("POST", "/1/messages.json", urllib.urlencode({
"token": apikey,
"user": userkey,
"device": device,
"title": title,
"message": msg,
"priority": prio
}), {"Content-type": "application/x-www-form-urlencoded"})
res = conn.getresponse()
if res.status != 200:
logging.error(T('Bad response from Pushover (%s): %s'), res.status, res.read())
if prio == 2:
body = { "token": apikey,
"user": userkey,
"device": device,
"title": title,
"message": msg,
"priority": prio,
"retry": emergency_retry,
"expire": emergency_expire
}
return do_send_pushover(body)
if prio > -3 and prio < 2:
body = { "token": apikey,
"user": userkey,
"device": device,
"title": title,
"message": msg,
"priority": prio,
}
return do_send_pushover(body)
except:
logging.warning(T('Failed to send pushover message'))
logging.info("Traceback: ", exc_info=True)
def do_send_pushover(body):
try:
conn = httplib.HTTPSConnection("api.pushover.net:443")
conn.request("POST", "/1/messages.json", urllib.urlencode(body),
{"Content-type": "application/x-www-form-urlencoded"})
res = conn.getresponse()
if res.status != 200:
logging.error(T('Bad response from Pushover (%s): %s'), res.status, res.read())
return T('Failed to send pushover message')
return ''
else:
return ''
except:
logging.warning(T('Failed to send pushover message'))
logging.info("Traceback: ", exc_info=True)
return T('Failed to send pushover message')
def send_pushbullet(title, msg, gtype, force=False, test=None):
""" Send message to Pushbullet """

View File

@@ -26,11 +26,11 @@ import datetime
import sabnzbd
from sabnzbd.nzbstuff import NzbObject
from sabnzbd.misc import exit_sab, cat_to_opts, \
get_admin_path, remove_all, globber_full
from sabnzbd.misc import exit_sab, cat_to_opts, remove_file, \
get_admin_path, remove_all, globber_full, int_conv, caller_name
from sabnzbd.panic import panic_queue
import sabnzbd.database as database
from sabnzbd.decorators import notify_downloader
from sabnzbd.decorators import NzbQueueLocker
from sabnzbd.constants import QUEUE_FILE_NAME, QUEUE_VERSION, FUTURE_Q_FOLDER, \
JOB_ADMIN, LOW_PRIORITY, NORMAL_PRIORITY, HIGH_PRIORITY, TOP_PRIORITY, \
REPAIR_PRIORITY, STOP_PRIORITY, VERIFIED_FILE, \
@@ -43,6 +43,7 @@ from sabnzbd.assembler import Assembler, file_has_articles
import sabnzbd.notifier as notifier
from sabnzbd.encoding import platform_encode
from sabnzbd.bpsmeter import BPSMeter
from sabnzbd.dirscanner import ProcessSingleFile
class NzbQueue(object):
@@ -99,7 +100,7 @@ class NzbQueue(object):
self.add(nzo, save=True)
else:
try:
os.remove(item)
remove_file(item)
except:
pass
@@ -139,7 +140,7 @@ class NzbQueue(object):
# Remove any future-jobs, we can't save those
for item in globber_full(os.path.join(cfg.admin_dir.get_path(), FUTURE_Q_FOLDER)):
os.remove(item)
remove_file(item)
# Done converting
cfg.converted_nzo_pickles.set(True)
@@ -147,6 +148,7 @@ class NzbQueue(object):
nzo_ids = []
return nzo_ids
@NzbQueueLocker
def scan_jobs(self, all=False, action=True):
""" Scan "incomplete" for missing folders,
'all' is True: Include active folders
@@ -230,7 +232,6 @@ class NzbQueue(object):
return nzo_id
@notify_downloader
def send_back(self, nzo):
""" Send back job to queue after successful pre-check """
try:
@@ -238,13 +239,14 @@ class NzbQueue(object):
except:
logging.debug('Failed to find NZB file after pre-check (%s)', nzo.nzo_id)
return
from sabnzbd.dirscanner import ProcessSingleFile
res, nzo_ids = ProcessSingleFile(nzo.work_name + '.nzb', nzb_path, keep=True, reuse=True)
if res == 0 and nzo_ids:
nzo = self.replace_in_q(nzo, nzo_ids[0])
# Reset reuse flag to make pause/abort on encryption possible
nzo.reuse = False
@NzbQueueLocker
def replace_in_q(self, nzo, nzo_id):
""" Replace nzo by new in at the same spot in the queue, destroy nzo """
# Must be a separate function from "send_back()", due to the required queue-lock
@@ -269,6 +271,7 @@ class NzbQueue(object):
logging.info("Traceback: ", exc_info=True)
return nzo
@NzbQueueLocker
def save(self, save_nzo=None):
""" Save queue, all nzo's or just the specified one """
logging.info("Saving queue")
@@ -339,7 +342,8 @@ class NzbQueue(object):
nzo.set_final_name_pw(name, password)
else:
# Reset url fetch wait time
nzo.wait = None
nzo.url_wait = None
nzo.url_tries = 0
return True
else:
return False
@@ -350,7 +354,7 @@ class NzbQueue(object):
else:
return None
@notify_downloader
@NzbQueueLocker
def add(self, nzo, save=True, quiet=False):
if not nzo.nzo_id:
nzo.nzo_id = sabnzbd.get_new_id('nzo', nzo.workpath, self.__nzo_table)
@@ -406,6 +410,7 @@ class NzbQueue(object):
self.sort_by_avg_age()
return nzo.nzo_id
@NzbQueueLocker
def remove(self, nzo_id, add_to_history=True, save=True, cleanup=True, keep_basic=False, del_files=False):
if nzo_id in self.__nzo_table:
nzo = self.__nzo_table.pop(nzo_id)
@@ -427,7 +432,7 @@ class NzbQueue(object):
self.cleanup_nzo(nzo, keep_basic, del_files)
sabnzbd.remove_data(nzo_id, nzo.workpath)
logging.info('Removed job %s', nzo.final_name)
logging.info('[%s] Removed job %s', caller_name(), nzo.final_name)
if save:
self.save(nzo)
else:
@@ -449,6 +454,7 @@ class NzbQueue(object):
return removed
@NzbQueueLocker
def remove_all(self, search=None):
if search:
search = search.lower()
@@ -511,7 +517,7 @@ class NzbQueue(object):
handled.append(nzo_id)
return handled
@notify_downloader
@NzbQueueLocker
def resume_nzo(self, nzo_id):
handled = []
if nzo_id in self.__nzo_table:
@@ -522,6 +528,7 @@ class NzbQueue(object):
handled.append(nzo_id)
return handled
@NzbQueueLocker
def switch(self, item_id_1, item_id_2):
try:
# Allow an index as second parameter, easier for some skins
@@ -570,32 +577,39 @@ class NzbQueue(object):
# If moving failed/no movement took place
return (-1, nzo1.priority)
@NzbQueueLocker
def move_up_bulk(self, nzo_id, nzf_ids, size):
if nzo_id in self.__nzo_table:
for unused in range(size):
self.__nzo_table[nzo_id].move_up_bulk(nzf_ids)
@NzbQueueLocker
def move_top_bulk(self, nzo_id, nzf_ids):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].move_top_bulk(nzf_ids)
@NzbQueueLocker
def move_down_bulk(self, nzo_id, nzf_ids, size):
if nzo_id in self.__nzo_table:
for unused in range(size):
self.__nzo_table[nzo_id].move_down_bulk(nzf_ids)
@NzbQueueLocker
def move_bottom_bulk(self, nzo_id, nzf_ids):
if nzo_id in self.__nzo_table:
self.__nzo_table[nzo_id].move_bottom_bulk(nzf_ids)
@NzbQueueLocker
def sort_by_avg_age(self, reverse=False):
logging.info("Sorting by average date... (reversed:%s)", reverse)
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_date_cmp, reverse)
@NzbQueueLocker
def sort_by_name(self, reverse=False):
logging.info("Sorting by name... (reversed:%s)", reverse)
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_name_cmp, reverse)
@NzbQueueLocker
def sort_by_size(self, reverse=False):
logging.info("Sorting by size... (reversed:%s)", reverse)
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_size_cmp, reverse)
@@ -617,10 +631,11 @@ class NzbQueue(object):
else:
logging.debug("Sort: %s not recognized", field)
@NzbQueueLocker
def __set_priority(self, nzo_id, priority):
""" Sets the priority on the nzo and places it in the queue at the appropriate position """
try:
priority = int(priority)
priority = int_conv(priority)
nzo = self.__nzo_table[nzo_id]
nzo_id_pos1 = -1
pos = -1
@@ -640,7 +655,7 @@ class NzbQueue(object):
if priority == self.__nzo_list[nzo_id_pos1].priority:
return nzo_id_pos1
nzo.priority = priority
nzo.set_priority(priority)
if sabnzbd.scheduler.analyse(False, priority) and \
nzo.status in (Status.CHECKING, Status.DOWNLOADING, Status.QUEUED):
nzo.status = Status.PAUSED
@@ -689,7 +704,7 @@ class NzbQueue(object):
except:
return -1
@notify_downloader
@NzbQueueLocker
def set_priority(self, nzo_ids, priority):
try:
n = -1
@@ -699,11 +714,13 @@ class NzbQueue(object):
except:
return -1
def reset_try_lists(self, nzf=None, nzo=None):
if nzf:
nzf.reset_try_list()
if nzo:
nzo.reset_try_list()
def reset_try_lists(self, article, article_reset=True):
""" Let article get new fetcher and reset trylists """
article.fetcher = None
if article_reset:
article.reset_try_list()
article.nzf.reset_try_list()
article.nzf.nzo.reset_try_list()
def reset_all_try_lists(self):
for nzo in self.__nzo_list:
@@ -719,6 +736,9 @@ class NzbQueue(object):
return False
def get_article(self, server, servers):
""" Get next article for jobs in the queue
Not locked for performance, since it only reads the queue
"""
for nzo in self.__nzo_list:
# Not when queue paused and not a forced item
if nzo.status not in (Status.PAUSED, Status.GRABBING) or nzo.priority == TOP_PRIORITY:
@@ -733,6 +753,9 @@ class NzbQueue(object):
return
def register_article(self, article, found=True):
""" Register the articles we tried
Not locked for performance, since it only modifies individual NZOs
"""
nzf = article.nzf
nzo = nzf.nzo
@@ -773,7 +796,7 @@ class NzbQueue(object):
def end_job(self, nzo):
""" Send NZO to the post-processing queue """
logging.info('Ending job %s', nzo.final_name)
logging.info('[%s] Ending job %s', caller_name(), nzo.final_name)
# Notify assembler to call postprocessor
if not nzo.deleted:
@@ -793,7 +816,9 @@ class NzbQueue(object):
Assembler.do.process((nzo, None))
def actives(self, grabs=True):
""" Return amount of non-paused jobs, optionally with 'grabbing' items """
""" Return amount of non-paused jobs, optionally with 'grabbing' items
Not locked for performance, only reads the queue
"""
n = 0
for nzo in self.__nzo_list:
# Ignore any items that are paused
@@ -806,6 +831,7 @@ class NzbQueue(object):
def queue_info(self, search=None, start=0, limit=0):
""" Return list of queued jobs,
optionally filtered by 'search' and limited by start and limit.
Not locked for performance, only reads the queue
"""
if search:
search = search.lower()
@@ -836,7 +862,9 @@ class NzbQueue(object):
return QNFO(bytes_total, bytes_left, bytes_left_previous_page, pnfo_list, q_size, n)
def remaining(self):
""" Return bytes left in the queue by non-paused items """
""" Return bytes left in the queue by non-paused items
Not locked for performance, only reads the queue
"""
bytes_left = 0
for nzo in self.__nzo_list:
if nzo.status != 'Paused':
@@ -862,6 +890,7 @@ class NzbQueue(object):
empty = []
for nzo in self.__nzo_list:
if not nzo.futuretype and not nzo.files and nzo.status not in (Status.PAUSED, Status.GRABBING):
logging.info('Found idle job %s', nzo.final_name)
empty.append(nzo)
# Stall prevention by checking if all servers are in the trylist
@@ -871,8 +900,11 @@ class NzbQueue(object):
for nzf in nzo.files:
if len(nzf.try_list) == sabnzbd.downloader.Downloader.do.server_nr:
# We do not want to reset all article trylists, they are good
logging.info('Resetting bad trylist for file %s in job %s', nzf.filename, nzo.final_name)
nzf.reset_try_list()
# Reset main trylist, minimal performance impact
logging.info('Resetting bad trylist for job %s', nzo.final_name)
nzo.reset_try_list()
for nzo in empty:
@@ -883,7 +915,7 @@ class NzbQueue(object):
if nzo.priority == priority:
nzo.pause()
@notify_downloader
@NzbQueueLocker
def resume_on_prio(self, priority):
for nzo in self.__nzo_list:
if nzo.priority == priority:
@@ -895,7 +927,7 @@ class NzbQueue(object):
if nzo.cat == cat:
nzo.pause()
@notify_downloader
@NzbQueueLocker
def resume_on_cat(self, cat):
for nzo in self.__nzo_list:
if nzo.cat == cat:

View File

@@ -40,14 +40,14 @@ except ImportError:
# SABnzbd modules
import sabnzbd
from sabnzbd.constants import GIGI, ATTRIB_FILE, JOB_ADMIN, \
DEFAULT_PRIORITY, LOW_PRIORITY, NORMAL_PRIORITY, \
PAUSED_PRIORITY, TOP_PRIORITY, DUP_PRIORITY, REPAIR_PRIORITY, \
REPAIR_PRIORITY, TOP_PRIORITY, HIGH_PRIORITY, NORMAL_PRIORITY, \
LOW_PRIORITY, DEFAULT_PRIORITY, PAUSED_PRIORITY, DUP_PRIORITY, STOP_PRIORITY, \
RENAMES_FILE, MAX_BAD_ARTICLES, Status, PNFO
from sabnzbd.misc import to_units, cat_to_opts, cat_convert, sanitize_foldername, \
get_unique_path, get_admin_path, remove_all, sanitize_filename, globber_full, \
int_conv, set_permissions, format_time_string, long_path, trim_win_path, \
fix_unix_encoding, calc_age, is_obfuscated_filename, get_ext, get_filename, \
get_unique_filename, renamer
get_unique_filename, renamer, remove_file, remove_dir
from sabnzbd.decorators import synchronized
import sabnzbd.config as config
import sabnzbd.cfg as cfg
@@ -112,7 +112,7 @@ class TryList(object):
# Article
##############################################################################
ArticleSaver = (
'article', 'art_id', 'bytes', 'partnum', 'nzf'
'article', 'art_id', 'bytes', 'partnum', 'lowest_partnum', 'nzf'
)
@@ -128,6 +128,7 @@ class Article(TryList):
self.art_id = None
self.bytes = bytes
self.partnum = partnum
self.lowest_partnum = False
self.tries = 0 # Try count
self.nzf = nzf
@@ -269,7 +270,23 @@ class NzbFile(TryList):
self.valid = bool(article_db)
if self.valid and self.nzf_id:
sabnzbd.save_data(article_db, self.nzf_id, nzo.workpath)
# Save first article seperate, but not for all but first par2 file
# Non-par2 files and the first par2 will have no volume and block number
# When DirectUnpack is disabled, do not do any of this to also preserve disk IO
setname, vol, block = sabnzbd.par2file.analyse_par2(self.filename)
if cfg.direct_unpack() and not vol and not block:
first_num = min(article_db.keys())
first_article = self.add_article(article_db.pop(first_num), first_num)
first_article.lowest_partnum = True
self.nzo.first_articles.append(first_article)
# Any articles left?
if article_db:
# Save the rest
sabnzbd.save_data(article_db, self.nzf_id, nzo.workpath)
else:
# All imported
self.import_finished = True
def finish_import(self):
""" Load the article objects from disk """
@@ -277,22 +294,28 @@ class NzbFile(TryList):
article_db = sabnzbd.load_data(self.nzf_id, self.nzo.workpath, remove=False)
if article_db:
for partnum in article_db:
art_id = article_db[partnum][0]
bytes = article_db[partnum][1]
self.add_article(article_db[partnum], partnum)
article = Article(art_id, bytes, partnum, self)
self.articles.append(article)
self.decodetable[partnum] = article
# Make sure we have labeled the lowest part number
# Also when DirectUnpack is disabled we need to know
self.decodetable[min(self.decodetable)].lowest_partnum = True
# Mark safe to continue
self.import_finished = True
elif not self.nzo.is_gone():
# TEMPORARY ERRORS
if not os.path.exists(os.path.join(self.nzf_id, self.nzo.workpath)):
logging.warning('Article DB file not found %s', self)
logging.warning('Article DB file not found %s: %s', self.nzf_id, self)
else:
# It was there, but empty
logging.warning('Article DB empty %s', self)
logging.warning('Article DB empty %s: %s', self.nzf_id, self)
def add_article(self, article_info, partnum):
""" Add article to object database and return article object """
article = Article(article_info[0], article_info[1], partnum, self)
self.articles.append(article)
self.decodetable[partnum] = article
return article
def remove_article(self, article, found):
""" Handle completed article, possibly end of file """
@@ -329,15 +352,11 @@ class NzbFile(TryList):
""" Is this file completed? """
return self.import_finished and not bool(self.articles)
@property
def lowest_partnum(self):
""" Get lowest article number of this file """
return min(self.decodetable)
def remove_admin(self):
""" Remove article database from disk (sabnzbd_nzf_<id>)"""
try:
os.remove(os.path.join(self.nzo.workpath, self.nzf_id))
logging.debug('Removing article database for %s', self.nzf_id)
remove_file(os.path.join(self.nzo.workpath, self.nzf_id))
except:
pass
@@ -511,7 +530,7 @@ class NzbParser(xml.sax.handler.ContentHandler):
self.nzf_list.remove(nzo_matches[0])
if nzf.valid and nzf.nzf_id:
logging.info('File %s added to queue', self.filename)
logging.info('File %s - %s added to queue', nzf.filename, nzf.nzf_id)
self.nzo.files.append(nzf)
self.nzo.files_table[nzf.nzf_id] = nzf
self.nzo.bytes += nzf.bytes
@@ -561,7 +580,7 @@ NzbObjectSaver = (
'status', 'avg_bps_freq', 'avg_bps_total', 'priority', 'saved_articles', 'nzo_id',
'futuretype', 'deleted', 'parsed', 'action_line', 'unpack_info', 'fail_msg', 'nzo_info',
'custom_name', 'password', 'next_save', 'save_timeout', 'encrypted', 'bad_articles',
'duplicate', 'oversized', 'precheck', 'incomplete', 'reuse', 'meta',
'duplicate', 'oversized', 'precheck', 'incomplete', 'reuse', 'meta', 'first_articles',
'md5sum', 'servercount', 'unwanted_ext', 'renames', 'rating_filtered'
)
@@ -571,7 +590,6 @@ NZO_LOCK = threading.RLock()
class NzbObject(TryList):
@synchronized(NZO_LOCK)
def __init__(self, filename, pp, script, nzb=None,
futuretype=False, cat=None, url=None,
priority=NORMAL_PRIORITY, nzbname=None, status="Queued", nzo_info=None,
@@ -606,8 +624,9 @@ class NzbObject(TryList):
# In case only /password was entered for nzbname
work_name = filename
self.work_name = work_name
self.final_name = work_name
# Remove trailing .nzb and .par(2)
self.work_name = create_work_name(work_name)
self.final_name = create_work_name(work_name)
self.meta = {}
self.servercount = {} # Dict to keep bytes per server
@@ -618,6 +637,7 @@ class NzbObject(TryList):
self.bytes_tried = 0 # Which bytes did we try
self.bytes_missing = 0 # Bytes missing
self.bad_articles = 0 # How many bad (non-recoverable) articles
self.set_priority(priority) # Parse priority of input
self.repair = r # True if we want to repair this set
self.unpack = u # True if we want to unpack this set
self.delete = d # True if we want to delete this set
@@ -647,12 +667,8 @@ class NzbObject(TryList):
self.status = status
self.avg_bps_freq = 0
self.avg_bps_total = 0
try:
priority = int(priority)
except:
priority = DEFAULT_PRIORITY
self.priority = priority
self.first_articles = []
self.saved_articles = []
self.nzo_id = None
@@ -692,13 +708,11 @@ class NzbObject(TryList):
self.next_save = None
self.save_timeout = None
self.encrypted = 0
self.wait = None
self.url_wait = None
self.url_tries = 0
self.pp_active = False # Signals active post-processing (not saved)
self.md5sum = None
# Remove trailing .nzb and .par(2)
self.work_name = create_work_name(self.work_name)
if nzb is None:
# This is a slot for a future NZB, ready now
return
@@ -806,35 +820,46 @@ class NzbObject(TryList):
self.password = unicoder(password, True)
# Determine category and find pp/script values
self.cat, pp_tmp, self.script, self.priority = cat_to_opts(cat, pp, script, priority)
self.cat, pp_tmp, self.script, priority = cat_to_opts(cat, pp, script, priority)
self.set_priority(priority)
self.repair, self.unpack, self.delete = sabnzbd.pp_to_opts(pp_tmp)
# Run user pre-queue script if needed
if not reuse:
accept, name, pp, cat, script, priority, group = \
if not reuse and cfg.pre_script():
accept, name, pp, cat_pp, script_pp, priority, group = \
sabnzbd.newsunpack.pre_queue(self.final_name_pw_clean, pp, cat, script,
priority, self.bytes, self.groups)
# Accept or reject
accept = int_conv(accept)
if accept < 1:
self.purge_data()
raise TypeError
if accept == 2:
self.fail_msg = T('Pre-queue script marked job as failed')
# Process all options, only over-write if set by script
# Beware that cannot do "if priority/pp", because those can
# also have a valid value of 0, which shouldn't be ignored
if name:
self.set_final_name_pw(name)
try:
pp = int(pp)
except:
pp = None
if cat_pp:
cat = cat_pp
try:
priority = int(priority)
except:
priority = None
if accept < 1:
self.purge_data()
raise TypeError
if name:
self.set_final_name_pw(name)
priority = DEFAULT_PRIORITY
if script_pp:
script = script_pp
if group:
self.groups = [str(group)]
if accept == 2:
self.fail_msg = T('Pre-queue script marked job as failed')
# Re-evaluate results from pre-queue script
self.cat, pp, self.script, self.priority = cat_to_opts(cat, pp, script, priority)
self.cat, pp, self.script, priority = cat_to_opts(cat, pp, script, priority)
self.set_priority(priority)
self.repair, self.unpack, self.delete = sabnzbd.pp_to_opts(pp)
else:
accept = 1
@@ -881,37 +906,8 @@ class NzbObject(TryList):
if reuse:
self.check_existing_files(wdir)
if cfg.auto_sort():
self.files.sort(cmp=nzf_cmp_date)
else:
self.files.sort(cmp=nzf_cmp_name)
# In the hunt for Unwanted Extensions:
# The file with the unwanted extension often is in the first or the last rar file
# So put the last rar immediately after the first rar file so that it gets detected early
if cfg.unwanted_extensions() and not cfg.auto_sort():
# ... only useful if there are unwanted extensions defined and there is no sorting on date
logging.debug('Unwanted Extension: putting last rar after first rar')
nzfposcounter = firstrarpos = lastrarpos = 0
for nzf in self.files:
nzfposcounter += 1
if '.rar' in str(nzf):
# a NZF found with '.rar' in the name
if firstrarpos == 0:
# this is the first .rar found, so remember this position
firstrarpos = nzfposcounter
lastrarpos = nzfposcounter
lastrarnzf = nzf # The NZF itself
if firstrarpos != lastrarpos:
# at least two different .rar's found
logging.debug('Unwanted Extension: First rar at %s, Last rar at %s', firstrarpos, lastrarpos)
logging.debug('Unwanted Extension: Last rar is %s', str(lastrarnzf))
try:
self.files.remove(lastrarnzf) # first remove. NB: remove() does searches for lastrarnzf
self.files.insert(firstrarpos, lastrarnzf) # ... and only then add after position firstrarpos
except:
logging.debug('The lastrar swap did not go well')
# Perform sorting
self.sort_nzfs()
# Copy meta fields to nzo_info, if not already set
for kw in self.meta:
@@ -955,6 +951,42 @@ class NzbObject(TryList):
nzf.deleted = True
return not bool(self.files)
def sort_nzfs(self):
""" Sort the files in the NZO, respecting
date sorting and unwanted extensions
"""
if cfg.auto_sort():
self.files.sort(cmp=nzf_cmp_date)
else:
self.files.sort(cmp=nzf_cmp_name)
# In the hunt for Unwanted Extensions:
# The file with the unwanted extension often is in the first or the last rar file
# So put the last rar immediately after the first rar file so that it gets detected early
if cfg.unwanted_extensions() and not cfg.auto_sort():
# ... only useful if there are unwanted extensions defined and there is no sorting on date
logging.debug('Unwanted Extension: putting last rar after first rar')
nzfposcounter = firstrarpos = lastrarpos = 0
for nzf in self.files:
nzfposcounter += 1
if '.rar' in str(nzf):
# a NZF found with '.rar' in the name
if firstrarpos == 0:
# this is the first .rar found, so remember this position
firstrarpos = nzfposcounter
lastrarpos = nzfposcounter
lastrarnzf = nzf # The NZF itself
if firstrarpos != lastrarpos:
# at least two different .rar's found
logging.debug('Unwanted Extension: First rar at %s, Last rar at %s', firstrarpos, lastrarpos)
logging.debug('Unwanted Extension: Last rar is %s', str(lastrarnzf))
try:
self.files.remove(lastrarnzf) # first remove. NB: remove() does searches for lastrarnzf
self.files.insert(firstrarpos, lastrarnzf) # ... and only then add after position firstrarpos
except:
logging.debug('The lastrar swap did not go well')
def reset_all_try_lists(self):
for nzf in self.files:
nzf.reset_all_try_lists()
@@ -991,6 +1023,9 @@ class NzbObject(TryList):
for setname in self.extrapars:
self.extrapars[parset].sort(key=lambda x: x.blocks)
# Also re-parse all filenames in case par2 came after first articles
self.verify_all_filenames_and_resort()
@synchronized(NZO_LOCK)
def handle_par2(self, nzf, filepath):
""" Check if file is a par2 and build up par2 collection """
@@ -1020,6 +1055,10 @@ class NzbObject(TryList):
# Change the properties
nzf.set_par2(setname, vol, block)
logging.debug('Got additional md5pack for set %s', nzf.setname)
# Make sure it exists, could be removed by newsunpack
if setname not in self.extrapars:
self.extrapars[setname] = []
self.extrapars[setname].append(nzf)
elif self.repair:
@@ -1099,8 +1138,23 @@ class NzbObject(TryList):
@synchronized(NZO_LOCK)
def remove_article(self, article, found):
nzf = article.nzf
# First or regular article?
if article.lowest_partnum and self.first_articles and article in self.first_articles:
self.first_articles.remove(article)
# All first articles done?
if not self.first_articles and self.md5of16k:
self.verify_all_filenames_and_resort()
# Remove from file-tracking
file_done = nzf.remove_article(article, found)
# Only on fully loaded files we can say if it's really done
if not nzf.import_finished:
file_done = False
# File completed, remove and do checks
if file_done:
self.remove_nzf(nzf)
if not self.reuse and cfg.fail_hopeless_jobs() and not self.check_quality(99)[0]:
@@ -1227,7 +1281,23 @@ class NzbObject(TryList):
# Abort unpacking if not desired anymore
if not self.unpack:
self.abort_direct_unpacker()
self.save_to_disk()
def set_priority(self, value):
""" Check if this is a valid priority """
# When unknown (0 is a known one), set to DEFAULT
if value == '' or value is None:
self.priority = DEFAULT_PRIORITY
return
# Convert input
value = int_conv(value)
if value in (REPAIR_PRIORITY, TOP_PRIORITY, HIGH_PRIORITY, NORMAL_PRIORITY, \
LOW_PRIORITY, DEFAULT_PRIORITY, PAUSED_PRIORITY, DUP_PRIORITY, STOP_PRIORITY):
self.priority = value
return
# Invalid value, set to normal priority
self.priority = NORMAL_PRIORITY
@property
def final_name_labeled(self):
@@ -1244,8 +1314,8 @@ class NzbObject(TryList):
prefix += T('UNWANTED') + ' / ' # : Queue indicator for unwanted extensions
if self.rating_filtered and self.status == 'Paused':
prefix += T('FILTERED') + ' / ' # : Queue indicator for filtered
if isinstance(self.wait, float):
dif = int(self.wait - time.time() + 0.5)
if isinstance(self.url_wait, float):
dif = int(self.url_wait - time.time() + 0.5)
if dif > 0:
prefix += T('WAIT %s sec') % dif + ' / ' # : Queue indicator for waiting URL fetch
if (self.avg_stamp + float(cfg.propagation_delay() * 60)) > time.time() and self.priority != TOP_PRIORITY:
@@ -1402,7 +1472,7 @@ class NzbObject(TryList):
# format the total time the download took, in days, hours, and minutes, or seconds.
complete_time = format_time_string(seconds, timecompleted.days)
msg1 = T('Downloaded in %s at an average of %sB/s') % (complete_time, to_units(avg_bps * 1024, dec_limit=1))
msg1 = T('Downloaded in %s at an average of %sB/s') % (complete_time, to_units(avg_bps * 1024))
msg1 += u'<br/>' + T('Age') + ': ' + calc_age(self.avg_date, True)
bad = self.nzo_info.get('bad_articles', 0)
@@ -1442,34 +1512,44 @@ class NzbObject(TryList):
article = None
nzf_remove_list = []
for nzf in self.files:
if nzf.deleted:
logging.debug('Skipping existing file %s', nzf.filename or nzf.subject)
else:
# Don't try to get an article if server is in try_list of nzf
if not nzf.server_in_try_list(server):
if not nzf.import_finished:
# Only load NZF when it's a primary server
# or when it's a backup server without active primaries
if sabnzbd.highest_server(server):
nzf.finish_import()
# Still not finished? Something went wrong...
if not nzf.import_finished and not self.is_gone():
logging.error(T('Error importing %s'), nzf)
nzf_remove_list.append(nzf)
continue
else:
continue
# Did we go through all first-articles?
if self.first_articles:
for article_test in self.first_articles:
article = article_test.get_article(server, servers)
if article:
break
article = nzf.get_article(server, servers)
if article:
break
# Move on to next ones
if not article:
for nzf in self.files:
if nzf.deleted:
logging.debug('Skipping existing file %s', nzf.filename or nzf.subject)
else:
# Don't try to get an article if server is in try_list of nzf
if not nzf.server_in_try_list(server):
if not nzf.import_finished:
# Only load NZF when it's a primary server
# or when it's a backup server without active primaries
if sabnzbd.highest_server(server):
nzf.finish_import()
# Still not finished? Something went wrong...
if not nzf.import_finished and not self.is_gone():
logging.error(T('Error importing %s'), nzf)
nzf_remove_list.append(nzf)
nzf.nzo.status = Status.PAUSED
continue
else:
continue
article = nzf.get_article(server, servers)
if article:
break
# Remove all files for which admin could not be read
for nzf in nzf_remove_list:
nzf.deleted = True
nzf.completed = True
self.files.remove(nzf)
# If cleanup emptied the active files list, end this job
if nzf_remove_list and not self.files:
sabnzbd.NzbQueue.do.end_job(self)
@@ -1574,6 +1654,14 @@ class NzbObject(TryList):
self.renamed_file(yenc_filename, nzf.filename)
nzf.filename = yenc_filename
def verify_all_filenames_and_resort(self):
""" Verify all filenames based on par2 info and then re-sort files """
logging.info('Checking all filenames for %s', self.final_name)
for nzf_verify in self.files:
self.verify_nzf_filename(nzf_verify)
logging.info('Re-sorting %s after getting filename information', self.final_name)
self.sort_nzfs()
@synchronized(NZO_LOCK)
def renamed_file(self, name_set, old_name=None):
""" Save renames at various stages (Download/PP)
@@ -1650,25 +1738,27 @@ class NzbObject(TryList):
remove_all(wpath, 'SABnzbd_nz?_*', keep_folder=True)
remove_all(wpath, 'SABnzbd_article_*', keep_folder=True)
# We save the renames file
sabnzbd.save_data(self.renames, RENAMES_FILE, self.workpath)
sabnzbd.save_data(self.renames, RENAMES_FILE, self.workpath, silent=True)
else:
remove_all(wpath, recursive=True)
if del_files:
remove_all(self.downpath, recursive=True)
else:
try:
os.rmdir(self.downpath)
remove_dir(self.downpath)
except:
pass
def gather_info(self, full=False):
queued_files = []
if full:
for _set in self.extrapars:
for nzf in self.extrapars[_set]:
# Don't show files twice
if not nzf.completed and nzf not in self.files:
queued_files.append(nzf)
# extrapars can change during iteration
with NZO_LOCK:
for _set in self.extrapars:
for nzf in self.extrapars[_set]:
# Don't show files twice
if not nzf.completed and nzf not in self.files:
queued_files.append(nzf)
return PNFO(self.repair, self.unpack, self.delete, self.script, self.nzo_id,
self.final_name_labeled, self.password, {}, '', self.cat, self.url, self.remaining,
@@ -1797,7 +1887,8 @@ class NzbObject(TryList):
# Set non-transferable values
self.pp_active = False
self.avg_stamp = time.mktime(self.avg_date.timetuple())
self.wait = None
self.url_wait = None
self.url_tries = 0
self.to_be_removed = False
self.direct_unpacker = None
if self.meta is None:

View File

@@ -461,7 +461,7 @@ class SABnzbdDelegate(NSObject):
self.setMenuTitle_("")
elif bytes_left > 0:
self.state = ""
speed = to_units(bpsnow, dec_limit=1)
speed = to_units(bpsnow)
# "10.1 MB/s" doesn't fit, remove space char
if 'M' in speed and len(speed) > 5:
speed = speed.replace(' ', '')

View File

@@ -22,6 +22,7 @@ sabnzbd.panic - Send panic message to the browser
import os
import logging
import tempfile
import ctypes
try:
import webbrowser
except ImportError:
@@ -29,6 +30,7 @@ except ImportError:
import sabnzbd
import sabnzbd.cfg as cfg
from sabnzbd.encoding import unicoder
PANIC_PORT = 1
PANIC_TEMPL = 2
@@ -164,7 +166,7 @@ def panic_message(panic, a=None, b=None):
def panic_port(host, port):
print "\n%s:\n %s" % (T('Fatal error'), T('Unable to bind to port %s on %s. Some other software uses the port or SABnzbd is already running.') % (port, host))
show_error_dialog("\n%s:\n %s" % (T('Fatal error'), T('Unable to bind to port %s on %s. Some other software uses the port or SABnzbd is already running.') % (port, host)))
launch_a_browser(panic_message(PANIC_PORT, host, port))
@@ -185,7 +187,7 @@ def panic_sqlite(name):
def panic(reason, remedy=""):
print "\n%s:\n %s\n%s" % (T('Fatal error'), reason, remedy)
show_error_dialog("\n%s:\n %s\n%s" % (T('Fatal error'), reason, remedy))
launch_a_browser(panic_message(PANIC_OTHER, reason, remedy))
@@ -217,6 +219,15 @@ def launch_a_browser(url, force=False):
logging.info("Traceback: ", exc_info=True)
def show_error_dialog(msg):
""" Show a pop-up when program cannot start
Windows-only, otherwise only print to console
"""
if sabnzbd.WIN32:
ctypes.windll.user32.MessageBoxW(0, unicoder(msg), T('Fatal error'), 0)
print msg
def error_page_401(status, message, traceback, version):
""" Custom handler for 401 error """
title = T('Access denied')

View File

@@ -24,7 +24,6 @@ import Queue
import logging
import sabnzbd
import xml.sax.saxutils
import xml.etree.ElementTree
import time
import re
@@ -35,7 +34,7 @@ from sabnzbd.misc import real_path, get_unique_path, create_dirs, move_to_path,
make_script_path, long_path, clip_path, \
on_cleanup_list, renamer, remove_dir, remove_all, globber, globber_full, \
set_permissions, cleanup_empty_directories, fix_unix_encoding, \
sanitize_and_trim_path, sanitize_files_in_folder
sanitize_and_trim_path, sanitize_files_in_folder, remove_file
from sabnzbd.tvsort import Sorter
from sabnzbd.constants import REPAIR_PRIORITY, TOP_PRIORITY, POSTPROC_QUEUE_FILE_NAME, \
POSTPROC_QUEUE_VERSION, sample_match, JOB_ADMIN, Status, VERIFIED_FILE
@@ -52,6 +51,8 @@ import sabnzbd.notifier as notifier
import sabnzbd.utils.rarfile as rarfile
import sabnzbd.utils.checkdir
MAX_FAST_JOB_COUNT = 3
# Match samples
RE_SAMPLE = re.compile(sample_match, re.I)
@@ -68,15 +69,26 @@ class PostProcessor(Thread):
if self.history_queue is None:
self.history_queue = []
self.queue = Queue.Queue()
# Fast-queue for jobs already finished by DirectUnpack
self.fast_queue = Queue.Queue()
# Regular queue for jobs that might need more attention
self.slow_queue = Queue.Queue()
# Load all old jobs
for nzo in self.history_queue:
self.process(nzo)
# Counter to not only process fast-jobs
self.__fast_job_count = 0
# State variables
self.__stop = False
self.__busy = False
self.paused = False
PostProcessor.do = self
self.__busy = False # True while a job is being processed
def save(self):
""" Save postproc queue """
logging.info("Saving postproc queue")
@@ -116,7 +128,12 @@ class PostProcessor(Thread):
""" Push on finished job in the queue """
if nzo not in self.history_queue:
self.history_queue.append(nzo)
self.queue.put(nzo)
# Fast-track if it has DirectUnpacked jobs or if it's still going
if nzo.direct_unpacker and (nzo.direct_unpacker.success_sets or not nzo.direct_unpacker.killed):
self.fast_queue.put(nzo)
else:
self.slow_queue.put(nzo)
self.save()
sabnzbd.history_updated()
@@ -132,7 +149,8 @@ class PostProcessor(Thread):
def stop(self):
""" Stop thread after finishing running job """
self.__stop = True
self.queue.put(None)
self.slow_queue.put(None)
self.fast_queue.put(None)
def cancel_pp(self, nzo_id):
""" Change the status, so that the PP is canceled """
@@ -146,7 +164,7 @@ class PostProcessor(Thread):
def empty(self):
""" Return True if pp queue is empty """
return self.queue.empty() and not self.__busy
return self.slow_queue.empty() and self.fast_queue.empty() and not self.__busy
def get_queue(self):
""" Return list of NZOs that still need to be processed """
@@ -168,6 +186,18 @@ class PostProcessor(Thread):
else:
logging.info("Completed Download Folder %s is not on FAT", complete_dir)
# Check on Windows if we have unicode-subprocess
if sabnzbd.WIN32:
try:
import subprocessww
except ImportError:
logging.warning(T('Module subprocessww missing. Expect problems with Unicoded file and directory names in downloads.'))
# Do a pruge of the history-items if it was set, just to be sure
history_db = database.HistoryDB()
history_db.auto_history_purge()
history_db.close()
# Start looping
check_eoq = False
while not self.__stop:
@@ -177,15 +207,28 @@ class PostProcessor(Thread):
time.sleep(5)
continue
# Something in the fast queue?
try:
nzo = self.queue.get(timeout=1)
# Every few fast-jobs we should check allow a
# slow job so that they don't wait forever
if self.__fast_job_count >= MAX_FAST_JOB_COUNT and self.slow_queue.qsize():
raise Queue.Empty
nzo = self.fast_queue.get(timeout=2)
self.__fast_job_count += 1
except Queue.Empty:
if check_eoq:
check_eoq = False
handle_empty_queue()
# Try the slow queue
try:
nzo = self.slow_queue.get(timeout=2)
# Reset fast-counter
self.__fast_job_count = 0
except Queue.Empty:
# Check for empty queue
if check_eoq:
check_eoq = False
handle_empty_queue()
# No fast or slow jobs, better luck next loop!
continue
else:
nzo = self.queue.get()
# Stop job
if not nzo:
@@ -213,6 +256,9 @@ class PostProcessor(Thread):
history_db.close()
nzo.purge_data(keep_basic=False, del_files=True)
# Processing done
nzo.pp_active = False
self.remove(nzo)
check_eoq = True
@@ -238,7 +284,6 @@ def process_job(nzo):
postproc_time = 0
script_log = ''
script_line = ''
crash_msg = ''
# Get the job flags
nzo.save_attribs()
@@ -495,15 +540,15 @@ def process_job(nzo):
Rating.do.update_auto_flag(nzo.nzo_id, Rating.FLAG_EXPIRED, host)
except:
logging.error(T('Post Processing Failed for %s (%s)'), filename, crash_msg)
if not crash_msg:
logging.info("Traceback: ", exc_info=True)
crash_msg = T('see logfile')
nzo.fail_msg = T('PostProcessing was aborted (%s)') % unicoder(crash_msg)
logging.error(T('Post Processing Failed for %s (%s)'), filename, T('see logfile'))
logging.info("Traceback: ", exc_info=True)
nzo.fail_msg = T('PostProcessing was aborted (%s)') % T('see logfile')
notifier.send_notification(T('Download Failed'), filename, 'failed', nzo.cat)
nzo.status = Status.FAILED
par_error = True
all_ok = False
if cfg.email_endjob():
emailer.endjob(nzo.final_name, nzo.cat, all_ok, clip_path(workdir_complete), nzo.bytes_downloaded,
nzo.fail_msg, nzo.unpack_info, '', '', 0)
@@ -563,7 +608,7 @@ def process_job(nzo):
def prepare_extraction_path(nzo):
""" Based on the information that we have, generate
the extraction path and create the directory.
Seperated so it can be called from DirectUnpacker
Separated so it can be called from DirectUnpacker
"""
one_folder = False
marker_file = None
@@ -668,6 +713,7 @@ def parring(nzo, workdir):
logging.info('Re-added %s to queue', filename)
if nzo.priority != TOP_PRIORITY:
nzo.priority = REPAIR_PRIORITY
nzo.status = Status.FETCHING
sabnzbd.nzbqueue.NzbQueue.do.add(nzo)
sabnzbd.downloader.Downloader.do.resume_from_postproc()
@@ -796,7 +842,7 @@ def cleanup_list(wdir, skip_nzb):
if on_cleanup_list(filename, skip_nzb):
try:
logging.info("Removing unwanted file %s", path)
os.remove(path)
remove_file(path)
except:
logging.error(T('Removing %s failed'), clip_path(path))
logging.info("Traceback: ", exc_info=True)
@@ -843,10 +889,14 @@ def nzb_redirect(wdir, nzbname, pp, script, cat, priority):
def one_file_or_folder(folder):
""" If the dir only contains one file or folder, join that file/folder onto the path """
if os.path.exists(folder) and os.path.isdir(folder):
cont = os.listdir(folder)
if len(cont) == 1:
folder = os.path.join(folder, cont[0])
folder = one_file_or_folder(folder)
try:
cont = os.listdir(folder)
if len(cont) == 1:
folder = os.path.join(folder, cont[0])
folder = one_file_or_folder(folder)
except WindowsError:
# Can occur on paths it doesn't like, for example "C:"
pass
return folder
@@ -876,7 +926,7 @@ def remove_samples(path):
path = os.path.join(root, file_)
try:
logging.info("Removing unwanted sample file %s", path)
os.remove(path)
remove_file(path)
except:
logging.error(T('Removing %s failed'), clip_path(path))
logging.info("Traceback: ", exc_info=True)
@@ -929,7 +979,7 @@ def del_marker(path):
if path and os.path.exists(path):
logging.debug('Removing marker file %s', path)
try:
os.remove(path)
remove_file(path)
except:
logging.info('Cannot remove marker file %s', path)
logging.info("Traceback: ", exc_info=True)

View File

@@ -180,6 +180,10 @@ class RSSQueue(object):
logging.warning(T('Cannot read %s'), RSS_FILE_NAME)
logging.info("Traceback: ", exc_info=True)
# Storage needs to be dict
if not self.jobs:
self.jobs = {}
# jobs is a NAME-indexed dictionary
# Each element is link-indexed dictionary
# Each element is another dictionary:
@@ -380,8 +384,6 @@ class RSSQueue(object):
n = 0
if ('F' in reTypes or 'S' in reTypes) and (not season or not episode):
season, episode = sabnzbd.newsunpack.analyse_show(title)[1:3]
season = int_conv(season)
episode = int_conv(episode)
# Match against all filters until an positive or negative match
logging.debug('Size %s', size)
@@ -618,7 +620,7 @@ def _HandleLink(jobs, feed, link, title, size, age, season, episode, flag, orgca
jobs[link]['status'] = 'D'
jobs[link]['time_downloaded'] = time.localtime()
logging.info("Adding %s (%s) to queue", link, title)
sabnzbd.add_url(link, pp=pp, script=script, cat=cat, priority=priority, nzbname=nzbname, feed_name=feed)
sabnzbd.add_url(link, pp=pp, script=script, cat=cat, priority=priority, nzbname=nzbname)
else:
if star:
jobs[link]['status'] = flag + '*'
@@ -713,8 +715,11 @@ def ep_match(season, episode, expr, title=None):
"""
m = _RE_SP.search(expr)
if m:
# Make sure they are all integers for comparison
req_season = int(m.group(1))
req_episode = int(m.group(2))
season = int_conv(season)
episode = int_conv(episode)
if season > req_season or (season == req_season and episode >= req_episode):
if title:
show = expr[:m.start()].replace('.', ' ').replace('_', ' ').strip()

View File

@@ -94,8 +94,8 @@ class SABTrayThread(SysTrayIconThread):
self.counter += 1
if self.counter > 10:
self.sabpaused, bytes_left, bpsnow, time_left = api.fast_queue()
mb_left = to_units(bytes_left, dec_limit=1)
speed = to_units(bpsnow, dec_limit=1)
mb_left = to_units(bytes_left)
speed = to_units(bpsnow)
if self.sabpaused:
self.hover_text = self.txt_paused
@@ -110,6 +110,14 @@ class SABTrayThread(SysTrayIconThread):
self.refresh_icon()
self.counter = 0
# left-click handler
def click(self, *args):
# Make sure to stop the timer
self.stop_click_timer()
# Pause/resume and force update of icon/text
self.pauseresume(None)
self.counter = 11
# menu handler
def opencomplete(self, icon):
try:

View File

@@ -78,8 +78,8 @@ class StatusIcon(Thread):
# run this every updatefreq ms
def run(self):
self.sabpaused, bytes_left, bpsnow, time_left = api.fast_queue()
mb_left = to_units(bytes_left, dec_limit=1)
speed = to_units(bpsnow, dec_limit=1)
mb_left = to_units(bytes_left)
speed = to_units(bpsnow)
if self.sabpaused:
self.tooltip = T('Paused')

View File

@@ -189,7 +189,6 @@ SKIN_TEXT = {
'ft-newRelease@1' : TT('New release %s available at'), # Used in Footer
# Main page
'useGlitter': TT('Try our new skin Glitter! Fresh new design that is optimized for desktop and mobile devices. Go to Config -> General to change your skin.'),
'shutdownOK?' : TT('Are you sure you want to shutdown SABnzbd?'),
'link-shutdown' : TT('Shutdown'), #: Shutdown SABnzbd
'link-pause' : TT('Pause'), #: Pause downloading
@@ -343,6 +342,7 @@ SKIN_TEXT = {
'explain-web_username' : TT('Optional authentication username.'),
'opt-web_password' : TT('SABnzbd Password'),
'explain-web_password' : TT('Optional authentication password.'),
'checkSafety' : TT('If the SABnzbd Host or Port is exposed to the internet, your current settings allow full external access to the SABnzbd interface.'),
'security' : TT('Security'),
'opt-enable_https' : TT('Enable HTTPS'),
'opt-notInstalled' : TT('not installed'),
@@ -666,6 +666,10 @@ SKIN_TEXT = {
'explain-pushover_userkey' : TT('User Key (required)'), #: Pushover settings
'opt-pushover_device' : TT('Device(s)'), #: Pushover settings
'explain-pushover_device' : TT('Device(s) to which message should be sent'), #: Pushover settings
'opt-pushover_emergency_retry' : TT('Emergency retry'), #: Pushover settings
'explain-pushover_emergency_retry' : TT('How often (in seconds) the same notification will be sent'), #: Pushover settings
'opt-pushover_emergency_expire' : TT('Emergency expire'), #: Pushover settings
'explain-pushover_emergency_expire' : TT('How many seconds your notification will continue to be retried'), #: Pushover settings
'section-Pushbullet' : TT('Pushbullet'), #: Header for Pushbullet notification section
'opt-pushbullet_enable' : TT('Enable Pushbullet notifications'), #: Pushbullet settings
'explain-pushbullet_enable' : TT('Requires a Pushbullet account'), #: Pushbulletsettings
@@ -804,6 +808,7 @@ SKIN_TEXT = {
'Glitter-filtered' : TT('FILTERED'),
'Glitter-waitSec' : TT('WAIT %s sec'),
'Glitter-error' : TT('ERROR:'),
'Glitter-fetch' : TT('Fetch'),
'Glitter-interfaceOptions' : TT('Web Interface'),
'Glitter-interfaceRefresh' : TT('Refresh rate'),
'Glitter-useGlobalOptions' : TT('Use global interface settings'),
@@ -857,6 +862,7 @@ SKIN_TEXT = {
'Glitter-pausePromptFail': TT('Sorry, we could not interpret that. Try again.'),
'Glitter-pauseFor' : TT('Pause for...'),
'Glitter-refresh' : TT('Refresh'),
'Glitter-logText' : TT('All usernames, passwords and API-keys are automatically removed from the log and the included copy of your settings.'),
'Glitter-sortAgeAsc' : TT('Sort by Age <small>Oldest&rarr;Newest</small>'),
'Glitter-sortAgeDesc' : TT('Sort by Age <small>Newest&rarr;Oldest</small>'),
'Glitter-sortNameAsc' : TT('Sort by Name <small>A&rarr;Z</small>'),

View File

@@ -38,7 +38,7 @@ RE_SAMPLE = re.compile(sample_match, re.I)
EXCLUDED_FILE_EXTS = ('.vob', '.bin')
LOWERCASE = ('the', 'of', 'and', 'at', 'vs', 'a', 'an', 'but', 'nor', 'for', 'on',
'so', 'yet')
'so', 'yet', 'with')
UPPERCASE = ('III', 'II', 'IV')
REPLACE_AFTER = {

View File

@@ -30,7 +30,7 @@ from httplib import IncompleteRead
from threading import Thread
import sabnzbd
from sabnzbd.constants import FUTURE_Q_FOLDER, Status
from sabnzbd.constants import DEF_TIMEOUT, MAX_URL_RETRIES, FUTURE_Q_FOLDER, Status
from sabnzbd.encoding import unicoder
import sabnzbd.misc as misc
import sabnzbd.dirscanner as dirscanner
@@ -59,8 +59,17 @@ class URLGrabber(Thread):
def add(self, url, future_nzo, when=None):
""" Add an URL to the URLGrabber queue, 'when' is seconds from now """
if when and future_nzo:
future_nzo.wait = time.time() + when
if future_nzo and when:
# Always increase counter
future_nzo.url_tries += 1
# Too many tries? Cancel
if future_nzo.url_tries > MAX_URL_RETRIES:
bad_fetch(future_nzo, url, T('Maximum retries'))
return
future_nzo.url_wait = time.time() + when
self.queue.put((url, future_nzo))
def stop(self):
@@ -81,8 +90,9 @@ class URLGrabber(Thread):
if future_nzo:
# Re-queue when too early and still active
if future_nzo.wait and future_nzo.wait > time.time():
if future_nzo.url_wait and future_nzo.url_wait > time.time():
self.add(url, future_nzo)
time.sleep(1.0)
continue
# Paused
if future_nzo.status == Status.PAUSED:
@@ -171,7 +181,6 @@ class URLGrabber(Thread):
elif item == 'x-dnzb-password':
nzo_info['password'] = value
elif item == 'retry-after':
# For NZBFinder
wait = misc.int_conv(value)
# Rating fields
@@ -187,7 +196,7 @@ class URLGrabber(Thread):
retry = True
fn = None
elif retry:
fn, msg, retry, wait, data = _analyse(fn, url)
fn, msg, retry, wait, data = _analyse(fn, url, future_nzo)
if not fn:
if retry:
@@ -300,23 +309,28 @@ def _build_request(url):
return urllib2.urlopen(req)
def _analyse(fn, url):
def _analyse(fn, url, future_nzo):
""" Analyze response of indexer
returns fn|None, error-message|None, retry, wait-seconds, data
"""
data = None
if not fn or fn.code != 200:
logging.debug('No usable response from indexer, retry after 60 sec')
if fn:
msg = fn.msg
else:
msg = ''
return None, msg, True, 60, data
# Increasing wait-time in steps for standard errors
when = DEF_TIMEOUT * (future_nzo.url_tries + 1)
logging.debug('No usable response from indexer, retry after %s sec', when)
return None, msg, True, when, data
# Check for an error response
if not fn or fn.msg != 'OK':
logging.debug('Received nothing from indexer, retry after 60 sec')
return None, fn.msg, True, 60, data
# Increasing wait-time in steps for standard errors
when = DEF_TIMEOUT * (future_nzo.url_tries + 1)
logging.debug('Received nothing from indexer, retry after %s sec', when)
return None, fn.msg, True, when, data
return fn, fn.msg, False, 0, data

View File

@@ -1,162 +0,0 @@
## Fixing python 2.7 windows unicode issue with ``subprocess.Popen``.
## Copied from
## http://vaab.blog.kal.fr/2017/03/16/fixing-windows-python-2-7-unicode-issue-with-subprocesss-popen/
## https://gist.github.com/vaab/2ad7051fc193167f15f85ef573e54eb9
## issue: https://bugs.python.org/issue19264
import os
import ctypes
import subprocess
import _subprocess
from ctypes import byref, windll, c_char_p, c_wchar_p, c_void_p, \
Structure, sizeof, c_wchar, WinError
from ctypes.wintypes import BYTE, WORD, LPWSTR, BOOL, DWORD, LPVOID, \
HANDLE
##
## Types
##
CREATE_UNICODE_ENVIRONMENT = 0x00000400
LPCTSTR = c_char_p
LPTSTR = c_wchar_p
LPSECURITY_ATTRIBUTES = c_void_p
LPBYTE = ctypes.POINTER(BYTE)
class STARTUPINFOW(Structure):
_fields_ = [
("cb", DWORD), ("lpReserved", LPWSTR),
("lpDesktop", LPWSTR), ("lpTitle", LPWSTR),
("dwX", DWORD), ("dwY", DWORD),
("dwXSize", DWORD), ("dwYSize", DWORD),
("dwXCountChars", DWORD), ("dwYCountChars", DWORD),
("dwFillAtrribute", DWORD), ("dwFlags", DWORD),
("wShowWindow", WORD), ("cbReserved2", WORD),
("lpReserved2", LPBYTE), ("hStdInput", HANDLE),
("hStdOutput", HANDLE), ("hStdError", HANDLE),
]
LPSTARTUPINFOW = ctypes.POINTER(STARTUPINFOW)
class PROCESS_INFORMATION(Structure):
_fields_ = [
("hProcess", HANDLE), ("hThread", HANDLE),
("dwProcessId", DWORD), ("dwThreadId", DWORD),
]
LPPROCESS_INFORMATION = ctypes.POINTER(PROCESS_INFORMATION)
class DUMMY_HANDLE(ctypes.c_void_p):
def __init__(self, *a, **kw):
super(DUMMY_HANDLE, self).__init__(*a, **kw)
self.closed = False
def Close(self):
if not self.closed:
windll.kernel32.CloseHandle(self)
self.closed = True
def __int__(self):
return self.value
CreateProcessW = windll.kernel32.CreateProcessW
CreateProcessW.argtypes = [
LPCTSTR, LPTSTR, LPSECURITY_ATTRIBUTES,
LPSECURITY_ATTRIBUTES, BOOL, DWORD, LPVOID, LPCTSTR,
LPSTARTUPINFOW, LPPROCESS_INFORMATION,
]
CreateProcessW.restype = BOOL
##
## Patched functions/classes
##
def CreateProcess(executable, args, _p_attr, _t_attr,
inherit_handles, creation_flags, env, cwd,
startup_info):
"""Create a process supporting unicode executable and args for win32
Python implementation of CreateProcess using CreateProcessW for Win32
"""
si = STARTUPINFOW(
dwFlags=startup_info.dwFlags,
wShowWindow=startup_info.wShowWindow,
cb=sizeof(STARTUPINFOW),
)
# Only cast to ints when it's given
if startup_info.hStdInput:
si.hStdInput = int(startup_info.hStdInput)
if startup_info.hStdOutput:
si.hStdOutput = int(startup_info.hStdOutput)
if startup_info.hStdError:
si.hStdError = int(startup_info.hStdError)
wenv = None
if env is not None:
## LPCWSTR seems to be c_wchar_p, so let's say CWSTR is c_wchar
env = (unicode("").join([
unicode("%s=%s\0") % (k, v)
for k, v in env.items()])) + unicode("\0")
wenv = (c_wchar * len(env))()
wenv.value = env
pi = PROCESS_INFORMATION()
creation_flags |= CREATE_UNICODE_ENVIRONMENT
if CreateProcessW(executable, args, None, None,
inherit_handles, creation_flags,
wenv, cwd, byref(si), byref(pi)):
return (DUMMY_HANDLE(pi.hProcess), DUMMY_HANDLE(pi.hThread),
pi.dwProcessId, pi.dwThreadId)
raise WinError()
class Popen(subprocess.Popen):
"""This superseeds Popen and corrects a bug in cPython 2.7 implem"""
def _execute_child(self, args, executable, preexec_fn, close_fds,
cwd, env, universal_newlines,
startupinfo, creationflags, shell, to_close,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite):
"""Code from part of _execute_child from Python 2.7 (9fbb65e)
There are only 2 little changes concerning the construction of
the the final string in shell mode: we preempt the creation of
the command string when shell is True, because original function
will try to encode unicode args which we want to avoid to be able to
sending it as-is to ``CreateProcess``.
"""
if not isinstance(args, subprocess.types.StringTypes):
args = subprocess.list2cmdline(args)
if startupinfo is None:
startupinfo = subprocess.STARTUPINFO()
if shell:
startupinfo.dwFlags |= _subprocess.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = _subprocess.SW_HIDE
comspec = os.environ.get("COMSPEC", unicode("cmd.exe"))
args = unicode('{} /c "{}"').format(comspec, args)
if (_subprocess.GetVersion() >= 0x80000000 or
os.path.basename(comspec).lower() == "command.com"):
w9xpopen = self._find_w9xpopen()
args = unicode('"%s" %s') % (w9xpopen, args)
creationflags |= _subprocess.CREATE_NEW_CONSOLE
super(Popen, self)._execute_child(args, executable,
preexec_fn, close_fds, cwd, env, universal_newlines,
startupinfo, creationflags, False, to_close, p2cread,
p2cwrite, c2pread, c2pwrite, errread, errwrite)
_subprocess.CreateProcess = CreateProcess

View File

@@ -4,12 +4,14 @@
# http://www.brunningonline.net/simon/blog/archives/SysTrayIcon.py.html
# modified on 2011-10-04 by Jan Schejbal to support threading and preload icons
# override doUpdates to perform actions inside the icon thread
# override click to perform actions when left-clicking the icon
import os
import pywintypes
import win32api
import win32con
import win32gui_struct
import timer
try:
import winxpgui as win32gui
except ImportError:
@@ -45,6 +47,7 @@ class SysTrayIconThread(Thread):
self.menu_actions_by_id = dict(self.menu_actions_by_id)
del self._next_action_id
self.click_timer = None
self.default_menu_index = (default_menu_index or 0)
self.window_class_name = window_class_name or "SysTrayIconPy"
@@ -89,7 +92,7 @@ class SysTrayIconThread(Thread):
sleep(0.100)
win32gui.Shell_NotifyIcon(win32gui.NIM_DELETE, (self.hwnd, 0))
# override this
# Override this
def doUpdates(self):
pass
@@ -175,12 +178,19 @@ class SysTrayIconThread(Thread):
win32gui.PostQuitMessage(0) # Terminate the app.
def notify(self, hwnd, msg, wparam, lparam):
# Double click is actually 1 single click followed
# by a double-click event, no way to differentiate
# So we need a timed callback to cancel
if lparam == win32con.WM_LBUTTONDBLCLK:
self.execute_menu_option(self.default_menu_index + self.FIRST_ID)
self.stop_click_timer()
elif lparam == win32con.WM_RBUTTONUP:
self.show_menu()
elif lparam == win32con.WM_LBUTTONUP:
pass
elif lparam == win32con.WM_LBUTTONDOWN:
# Wrapper of win32api, timeout is in ms
# We need to wait at least untill what user has defined as double click
self.stop_click_timer()
self.click_timer = timer.set_timer(win32gui.GetDoubleClickTime(), self.click)
return True
def show_menu(self):
@@ -204,6 +214,17 @@ class SysTrayIconThread(Thread):
# Weird PyWin/win32gui bug, just ignore it for now
pass
# Override this for left-click action
# Need to call the stop-timer in that function!
def click(self, *args):
pass
def stop_click_timer(self):
# Stop the timer
if self.click_timer:
timer.kill_timer(self.click_timer)
self.click_timer = None
def create_menu(self, menu, menu_options):
for option_text, option_icon, option_action, option_id in menu_options[::-1]:
if option_icon:

View File

@@ -24,7 +24,7 @@ import logging
import os
from sabnzbd.encoding import unicoder
import sabnzbd.cfg as cfg
from sabnzbd.misc import get_ext, get_filename
from sabnzbd.misc import get_ext, get_filename, get_from_url
import sabnzbd.newsunpack
from sabnzbd.constants import VALID_ARCHIVES
@@ -47,7 +47,7 @@ def upload_file(url, fp):
password = cfg.password()
if username and password:
url = '%s&ma_username=%s&ma_password=%s' % (url, username, password)
sabnzbd.newsunpack.get_from_url(url)
get_from_url(url)
except:
logging.error("Failed to upload file: %s", fp)
logging.info("Traceback: ", exc_info=True)

View File

@@ -4,5 +4,5 @@
# You MUST use double quotes (so " and not ')
__version__ = "2.3.0-develop"
__version__ = "2.4.0-develop"
__baseline__ = "unknown"

160
scripts/Deobfuscate.py Normal file
View File

@@ -0,0 +1,160 @@
#!/usr/bin/python -OO
# Copyright 2008-2017 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
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""
Deobfuscation post-processing script:
Will check in the completed job folder if maybe there are par2 files,
for example "rename.par2", and use those to rename the files.
If there is no "rename.par2" available, it will rename the largest
file to the job-name in the queue.
NOTES:
1) To use this script you need Python installed on your system and
select "Add to path" during its installation. Select this folder in
Config > Folders > Scripts Folder and select this script for each job
you want it sued for, or link it to a category in Config > Categories.
2) Beware that files on the 'Cleanup List' are removed before
scripts are called and if any of them happen to be required by
the found par2 file, it will fail.
3) If there are multiple larger (>40MB) files, then the script will not
rename anything, since it could be a multi-pack.
4) If you want to modify this script, make sure to copy it out
of this directory, or it will be overwritten when SABnzbd is updated.
5) Feedback or bugs in this script can be reported in on our forum:
https://forums.sabnzbd.org/viewforum.php?f=9
"""
import os
import sys
import time
import fnmatch
import subprocess
# Files to exclude and minimal file size for renaming
EXCLUDED_FILE_EXTS = ('.vob', '.bin')
MIN_FILE_SIZE = 40*1024*1024
# Are we being called from SABnzbd?
if not os.environ.get('SAB_VERSION'):
print "This script needs to be called from SABnzbd as post-processing script."
sys.exit(1)
def print_splitter():
""" Simple helper function """
print '\n------------------------\n'
# Windows or others?
par2_command = os.environ['SAB_PAR2_COMMAND']
if os.environ['SAB_MULTIPAR_COMMAND']:
par2_command = os.environ['SAB_MULTIPAR_COMMAND']
# Diagnostic info
print_splitter()
print 'SABnzbd version: ', os.environ['SAB_VERSION']
print 'Job location: ', os.environ['SAB_COMPLETE_DIR']
print 'Par2-command: ', par2_command
print_splitter()
# Search for par2 files
matches = []
for root, dirnames, filenames in os.walk(os.environ['SAB_COMPLETE_DIR']):
for filename in fnmatch.filter(filenames, '*.par2'):
matches.append(os.path.join(root, filename))
print 'Found file:', os.path.join(root, filename)
# Found any par2 files we can use?
run_renamer = True
if not matches:
print "No par2 files found to process."
# Run par2 from SABnzbd on them
for par2_file in matches:
# Build command, make it check the whole directory
wildcard = os.path.join(os.environ['SAB_COMPLETE_DIR'], '*')
command = [str(par2_command), 'r', par2_file, wildcard]
# Start command
print_splitter()
print 'Starting command: ', repr(command)
try:
result = subprocess.check_output(command)
except subprocess.CalledProcessError as e:
# Multipar also gives non-zero in case of succes
result = e.output
# Show output
print_splitter()
print result
print_splitter()
# Last status-line for the History
# Check if the magic words are there
if 'Repaired successfully' in result or 'All files are correct' in result or \
'Repair complete' in result or 'All Files Complete' in result or 'PAR File(s) Incomplete' in result:
print 'Recursive repair/verify finished.'
run_renamer = False
else:
print 'Recursive repair/verify did not complete!'
# No matches? Then we try to rename the largest file to the job-name
if run_renamer:
print_splitter()
print 'Trying to see if there are large files to rename'
print_splitter()
# If there are more larger files, we don't rename
largest_file = None
for root, dirnames, filenames in os.walk(os.environ['SAB_COMPLETE_DIR']):
for filename in filenames:
full_path = os.path.join(root, filename)
file_size = os.path.getsize(full_path)
# Do we count this file?
if file_size > MIN_FILE_SIZE and os.path.splitext(filename)[1].lower() not in EXCLUDED_FILE_EXTS:
# Did we already found one?
if largest_file:
print 'Found:', largest_file
print 'Found:', full_path
print_splitter()
print 'Found multiple larger files, aborting.'
largest_file = None
break
largest_file = full_path
# Found something large enough?
if largest_file:
# We don't need to do any cleaning of dir-names
# since SABnzbd already did that!
new_name = '%s%s' % (os.path.join(os.environ['SAB_COMPLETE_DIR'], os.environ['SAB_FINAL_NAME']), os.path.splitext(largest_file)[1].lower())
print 'Renaming %s to %s' % (largest_file, new_name)
# With retries for Windows
for r in range(3):
try:
os.rename(largest_file, new_name)
print 'Renaming done!'
break
except:
time.sleep(1)
else:
print 'No par2 files or large files found'
# Always exit with succes-code
sys.exit(0)

44
scripts/Sample-PostProc.py Executable file
View File

@@ -0,0 +1,44 @@
#!/usr/bin/env python
# Example Post-Processing Script for SABnzbd (2.3.1 and higher), written in Python.
# For Linux, MacOS, Windows and any other platform with Python
# See https://sabnzbd.org/wiki/scripts/post-processing-scripts for details
#
# Example test run on Linux:
# env SAB_VERSION=X.Y SAB_AVG_BPS=666 python ./Sample-PostProc.py somedir222 nzbname CleanJobName123 Index12 Cat88 MyGroup PP0 https://example.com/
import sys, os
# Raw parsing of input parameters en SABnzbd environment variables
counter = 0
print "\nINPUT from argv:\n"
for item in sys.argv:
print "Argument", counter, ":", item
counter += 1
print "\nINPUT from environment variables (only SAB specifics):\n"
for item in os.environ:
if item.find("SAB_") == 0:
print item, os.environ[item]
# More intelligent parsing:
try:
(scriptname,directory,orgnzbname,jobname,reportnumber,category,group,postprocstatus,url) = sys.argv
except:
print "No SAB compliant number of commandline parameters found (should be 8):", len(sys.argv)-1
sys.exit(1) # non-zero return code
# Some examples:
print "\nExamples of some specific values:\n"
print "jobname is", jobname
try:
sabversion = os.environ['SAB_VERSION']
print "sabversion is", sabversion
except:
pass
''' your code here '''
# We're done:
print "\nScript done. All OK." # the last line will appear in the SABnzb History GUI
sys.exit(0) # The result code towards SABnzbd

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