Compare commits

..

52 Commits

Author SHA1 Message Date
Safihre
971e4fc909 Merge branch '3.0.x' 2020-08-30 20:58:31 +02:00
Safihre
51cc765949 Update text files for 3.0.2 2020-08-30 20:50:45 +02:00
Safihre
19c6a4fffa Propagation delay label was shown even if no delay was activated 2020-08-29 16:46:16 +02:00
Safihre
105ac32d2f Reading RSS feed with no categories set could result in crash
Closes #1589
2020-08-28 10:16:49 +02:00
Safihre
57550675d2 Removed logging in macOS sabApp that resulted in double logging 2020-08-28 10:16:41 +02:00
Safihre
e674abc5c0 Update text files for 3.0.2RC2 2020-08-26 08:56:29 +02:00
Safihre
f965c96f51 Change the macOS power assertion to NoIdleSleep 2020-08-26 08:50:54 +02:00
Safihre
c76b8ed9e0 End-of-queue-script did not run on Windows due to long-path
https://forums.sabnzbd.org/viewtopic.php?f=3&t=24918

Will refactor this so they all call 1 function.
2020-08-24 11:28:14 +02:00
Safihre
4fbd0d8a7b Check if name is a string before switching to nzbfile in addfile
Closes #1584
2020-08-24 09:05:25 +02:00
Safihre
2186c0fff6 Update text files for 3.0.2 RC 1 2020-08-21 15:42:35 +02:00
Safihre
1adca9a9c1 Do not crash if certifi certificates are not available
This could happen on Windows, due to overactive virus scanners
2020-08-21 15:26:06 +02:00
Safihre
9408353f2b Priority was not parsed correctly if supplied as string 2020-08-21 15:12:09 +02:00
Safihre
84f4d453d2 Permissions would be set even if user didn't set any
Windows developers like me shouldn't do permissions stuff..
2020-08-21 15:12:01 +02:00
Safihre
d10209f2a1 Extend tests of create_all_dirs to cover apply_umask=False 2020-08-21 15:11:53 +02:00
Safihre
3ae149c72f Split the make_mo.py command for NSIS 2020-08-19 22:21:02 +02:00
Safihre
47385acc3b Make sure we force the final_name to string on legacy get_attrib_file 2020-08-19 16:21:13 +02:00
Safihre
814eeaa900 Redesigned the saving of attributes
Now uses pickle, so that the type of the property is preserved.
Made flexible, so that more properties can be easily added later.
Closes #1575
2020-08-19 16:21:07 +02:00
Safihre
5f2ea13aad NzbFile comparison could crash when comparing finished_files
https://forums.sabnzbd.org/viewtopic.php?f=3&t=24902&p=121748
2020-08-19 08:50:06 +02:00
Safihre
41ca217931 Merge branch '3.0.x' 2020-08-18 11:05:50 +02:00
Safihre
b57d36e8dd Set version information to 3.0.1 2020-08-18 11:05:36 +02:00
Safihre
9a4be70734 List Cheetah minimal version in requirements.txt 2020-08-18 08:21:20 +02:00
Safihre
a8443595a6 Generalize use of certifi module 2020-08-18 08:20:47 +02:00
Safihre
fd0a70ac58 Update text files for 3.0.1 2020-08-17 16:52:23 +02:00
Safihre
8a8685c968 Permissions should only be applied if requested
Corrects 050b925f7b
2020-08-16 18:28:39 +02:00
Safihre
9e6cb8da8e Temporarily set cheroot version due to it breaking our tests
cherrypy/cheroot/issues/312
2020-08-16 18:28:13 +02:00
Safihre
054ec54d51 Basic authentication option was broken
Closes #1571
2020-08-10 15:34:01 +02:00
Safihre
272ce773cb Update text files for 3.0.1RC1 2020-08-07 15:28:11 +02:00
Safihre
050b925f7b Permissions were not set correctly when creating directories (#1568)
Restores changes made in d2e0ebe
2020-08-07 15:22:53 +02:00
Safihre
0087940898 Merge branch '3.0.x' into master 2020-08-02 09:46:41 +02:00
Safihre
e323c014f9 Set version information to 3.0.0 2020-08-01 16:17:08 +02:00
Safihre
cc465c7554 Update text files for 3.0.0
🎉🎉
2020-08-01 15:59:30 +02:00
Safihre
14cb37564f Update translate-link in SABnzbd 2020-07-19 13:01:39 +02:00
Safihre
094db56c3b Default-text for Automatically sort queue 2020-07-16 22:29:02 +02:00
Safihre
aabb709b8b Update text files for 3.0.0 RC 2 2020-07-15 14:10:35 +02:00
Safihre
0833dd2db9 Update translatable texts in 3.0.x branch 2020-07-15 14:07:21 +02:00
Safihre
cd3f912be4 RAR-renamer should be run on badly named RAR-files
https://forums.sabnzbd.org/viewtopic.php?f=2&t=24514&p=121433
2020-07-15 14:01:48 +02:00
Safihre
665c516db6 Only really run pre-script when it is set 2020-07-12 14:20:18 +02:00
Safihre
b670da9fa0 Always use Default-priority when creating NZB-objects
Closes #1552
2020-07-12 14:03:07 +02:00
Safihre
80bee9bffe Search-icon would be shown on top of drop-downs
Closes #1545
2020-06-30 12:57:28 +02:00
Safihre
d85a70e8ad Always report API paused status as a boolean
Closes #1542
2020-06-30 10:26:34 +02:00
Safihre
8f21533e76 Set version to 2.3.9 2019-05-24 11:39:14 +02:00
Safihre
89996482a1 Merge branch '2.3.x' 2019-05-24 09:33:12 +02:00
Safihre
03c10dce91 Update text files for 2.3.9 2019-05-24 09:32:34 +02:00
Safihre
bd5331be05 Merge branch 'develop' into 2.3.x 2019-05-24 09:12:02 +02:00
Safihre
46e1645289 Correct typo in release notes 2019-05-18 10:56:39 +02:00
Safihre
4ce3965747 Update text files for 2.3.9RC2 2019-05-18 09:56:05 +02:00
Safihre
9d4af19db3 Merge branch 'develop' into 2.3.x 2019-05-18 09:45:20 +02:00
Safihre
48e034f4be Update text files for 2.3.9RC1 2019-05-07 13:50:20 +02:00
Safihre
f8959baa2f Revert "Notify develop-users that we will switch to Python 3"
This reverts commit fb238af7de.
2019-05-07 13:35:13 +02:00
Safihre
8ed5997eae Merge branch 'develop' into 2.3.x 2019-05-07 13:10:10 +02:00
Safihre
daf9f50ac8 Set version to 2.3.8 2019-03-18 11:10:56 +01:00
Safihre
6b11013c1a Merge branch '2.3.x' 2019-03-18 11:09:35 +01:00
128 changed files with 2110 additions and 8488 deletions

View File

@@ -1,33 +0,0 @@
name: Update translatable texts
on:
push:
branches:
- develop
jobs:
translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Generate translatable texts
run: |
python3 tools/extract_pot.py
- name: Install Transifex client
# Sudo is needed to link the "tx"-command
run: |
sudo -H python3 -m pip install setuptools wheel
sudo -H python3 -m pip install transifex-client
- name: Push/pull Transifex translations
run: |
tx push --source --parallel
tx pull --all --force --parallel
env:
TX_TOKEN: ${{ secrets.TX_TOKEN }}
- name: Push translatable and translated texts back to repo
uses: stefanzweifel/git-auto-commit-action@master
with:
commit_message: Update translatable texts
commit_user_name: SABnzbd Automation
commit_user_email: bugs@sabnzbd.org
commit_author: SABnzbd Automation <bugs@sabnzbd.org>

View File

@@ -32,7 +32,8 @@ install:
ln -s /usr/lib/chromium-browser/chromedriver ~/bin/chromedriver;
fi;
- python3 --version
- python3 -m pip install --upgrade pip wheel
- python3 -m pip install --upgrade pip
- python3 -m pip install --upgrade wheel
- python3 -m pip install --upgrade -r requirements.txt
- python3 -m pip install --upgrade -r tests/requirements.txt

View File

@@ -1,24 +0,0 @@
[main]
host = https://www.transifex.com
[sabnzbd-translations.po-main-sabnzbd-pot--develop]
file_filter = po/main/<lang>.po
minimum_perc = 0
source_file = po/main/SABnzbd.pot
source_lang = en
type = PO
[sabnzbd-translations.po-email-sabemail-pot--develop]
file_filter = po/email/<lang>.po
minimum_perc = 0
source_file = po/email/SABemail.pot
source_lang = en
type = PO
[sabnzbd-translations.po-nsis-sabnsis-pot--develop]
file_filter = po/nsis/<lang>.po
minimum_perc = 0
source_file = po/nsis/SABnsis.pot
source_lang = en
type = PO

16
ABOUT.txt Normal file
View File

@@ -0,0 +1,16 @@
*******************************************
*** This is SABnzbd ***
*******************************************
SABnzbd is an open-source cross-platform binary newsreader.
It simplifies the process of downloading from Usenet dramatically,
thanks to its friendly web-based user interface and advanced
built-in post-processing options that automatically verify, repair,
extract and clean up posts downloaded from Usenet.
SABnzbd also has a fully customizable user interface,
and offers a complete API for third-party applications to hook into.
There is an extensive Wiki on the use of SABnzbd.
https://sabnzbd.org/wiki/
Please also read the file "ISSUES.txt"

View File

@@ -1,4 +1,4 @@
SABnzbd 3.1.0
SABnzbd 3.0.0
-------------------------------------------------------------------------------
0) LICENSE

View File

@@ -14,13 +14,13 @@
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/3.1/special
See: https://sabnzbd.org/wiki/configuration/3.0/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/3.1/special
See: https://sabnzbd.org/wiki/configuration/3.0/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.

View File

@@ -1,7 +1,7 @@
Metadata-Version: 1.0
Name: SABnzbd
Version: 3.1.0Beta2
Summary: SABnzbd-3.1.0Beta2
Version: 3.0.2
Summary: SABnzbd-3.0.2
Home-page: https://sabnzbd.org
Author: The SABnzbd Team
Author-email: team@sabnzbd.org

View File

@@ -1,46 +1,72 @@
Release Notes - SABnzbd 3.1.0 Beta 2
Release Notes - SABnzbd 3.0.2
=========================================================
## Changes and bugfixes since 3.1.0 Beta 1
- Post-processing could lock the application.
- Improved detection for Deobfuscate final filenames.
- Paused priority of pre-queue script was ignored.
- Multi-edit layout was displayed wrongly.
- Jobs with only par2-files would result in a crash.
- Downloaded bytes could show as exceeding the total bytes of a job.
- Restore limit on length of foldernames (`max_foldername_length`).
- Duplicate Detection did not check filenames in History.
- Show warning that Pyton 3.5 support will be dropped after 3.1.0.
- Linux: false-positive warning about UnRar version was shown.
- Windows: could fail to create folders on some network shares.
- Windows: external processes would show in popup window.
- Windows: show version in tray icon tooltip.
## Bugfixes since 3.0.1
- Priority was not parsed correctly if supplied as through the API.
- API-call `addfile` could fail if `name` and `nzbfile` were used.
- Permissions were still not set correctly when creating directories.
- Propagation delay label was shown even if no delay was activated.
- Reading RSS feed with no categories set could result in crash.
- Jobs with numeric names could crash post-processing.
- Jobs with missing articles could result in crash.
- macOS: changed the power assertion to `NoIdleSleep`.
- Windows: end-of-queue-script did not run on Windows.
- Windows: crash if the virus scanner removed the certificate bundle.
## Changes since 3.0.2
- Added option to automatically deobfuscate final filenames: after unpacking,
detect and rename obfuscated or meaningless filenames to the job name,
similar to the Deobfuscate.py post-processing script.
- Switched to Transifex as our translations platform:
Help us translate SABnzbd in your language! Add untranslated texts or
improved existing translations here: https://sabnzbd.org/wiki/translate
- Redesigned job availability-check to be more efficient and reliable.
- Skip repair on Retry if all sets were previously successfully verified.
- Passwords included in the filename no longer have to be at the end.
- Added password input box on the Add NZB screen.
- Windows/macOS: update UnRar to 5.91 and MultiPar to 1.3.1.0.
- Windows: retry `Access Denied` when renaming files on Windows.
## Bugfixes since 3.0.0
- Basic Authentication resulted in crash.
- Permissions were not set correctly when creating directories.
- Windows: base SSL certificate bundle was not included.
## Bugfixes since 3.0.2
- Assembler crashes could occur due to race condition in `ArticleCache`.
- On HTTP-redirects the scheme/hostname/port were ignored when behind a proxy.
- Strip slash of the end of `url_base` as it could break other code.
- Unpacking with a relative folder set for a category could fail.
- Windows: non-Latin languages were displayed incorrectly in the installer.
## About the new major version
We have been working for months to upgrade the SABnzbd code from Python 2 to Python 3.
Although it might not sound like a big change, we had to rewrite almost every part of
the code. We also included a number of new features, listed below.
## Big changes in 3.0.0
- Python 3.5 and above are the only supported versions of Python.
- Cache handling is greatly improved, resulting in more stable speeds on some systems.
- Articles failing with CRC errors are now retried on other servers.
- SFV files, even obfuscated, will be used for renaming when there are no par2 files.
- Fully obfuscated RAR-sets with no verification files are detected and extracted.
- Built-in internet bandwidth test.
- Windows Service support was changed. The service will need to be reinstalled!
Documentation: https://sabnzbd.org/wiki/advanced/sabnzbd-as-a-windows-service
- The Windows installer is 64-bit only, for 32-bit please use the standalone package.
## Other changes since 2.3.9
- Files inside an NZB that are fully identical are now skipped automatically.
- Folders of jobs that failed post-processing are renamed to `_FAILED_`.
- Blocking of unwanted extensions that are directly inside an NZB.
- In Python 3 OpenSSL 1.1.1 is used for Windows and macOS, as a result
newsservers manually set to `RC4-MD5` cipher can no longer connect.
Documentation: https://sabnzbd.org/wiki/advanced/ssl-ciphers
- TLS1.3 support for newsserver connections.
- SABYenc, par2 and unrar are now required to start downloading.
- Growl-support was removed.
- The `smpl` skin was removed.
- Using the API with `output=text` to add NZB's will report the `nzo_ids` instead of `ok`.
- Queue-item labels are no longer part of the name but separated in API-property `labels`.
- API-calls `tapi` and `qstatus` were removed.
- On Windows only Multipar is available for repair.
- Linux tray icon support was improved.
- On Linux special permission bits are removed from files after download.
- macOS features such as the menu and notifications now use native code.
## Bugfixes since 2.3.9
- Resolved potential security issue in FAT-filesystem check and Nice and IONice Parameters.
More information: https://github.com/sabnzbd/sabnzbd/security/advisories/GHSA-9x87-96gg-33w2
- Sample removal did not work if only 1 sample file was present.
- Crash on badly formatted RSS-feeds or readout during editing.
- Only really run pre-queue-script when it is set.
- Always report API `paused` status as a boolean.
- Automatic aborting of jobs that can't be completed would sometimes not trigger.
- Windows systems could enter standby state during downloading.
- Some errors thrown by unrar were not caught.
- Files and sockets were not always closed correctly.
- Unwanted extension check was overly aggressively deleting folders
## Upgrade notices
- Jobs that failed on versions before 3.1.x, will throw an error about the
attribute file failing to load when they are retried on 3.1.0+. This error
can be ignored.
- When upgrading from 2.x.x or older the queue will be converted. Job order,
settings and data will be preserved, but if you decide to go back to 2.x.x
your queue cannot be downgraded again. But you can restore the jobs by going

View File

@@ -102,19 +102,9 @@ def guard_loglevel():
LOG_FLAG = True
def warning_helpful(*args, **kwargs):
""" Wrapper to ignore helpfull warnings if desired """
if sabnzbd.cfg.helpfull_warnings():
return logging.warning(*args, **kwargs)
return logging.info(*args, **kwargs)
logging.warning_helpful = warning_helpful
class GUIHandler(logging.Handler):
"""Logging handler collects the last warnings/errors/exceptions
to be displayed in the web-gui
""" Logging handler collects the last warnings/errors/exceptions
to be displayed in the web-gui
"""
def __init__(self, size):
@@ -286,7 +276,7 @@ def identify_web_template(key, defweb, wdir):
full_main = real_path(full_dir, DEF_MAIN_TMPL)
if not os.path.exists(full_main):
logging.warning_helpful(T("Cannot find web template: %s, trying standard template"), full_main)
logging.warning(T("Cannot find web template: %s, trying standard template"), full_main)
full_dir = real_path(sabnzbd.DIR_INTERFACES, DEF_STDINTF)
full_main = real_path(full_dir, DEF_MAIN_TMPL)
if not os.path.exists(full_main):
@@ -429,12 +419,10 @@ def print_modules():
logging.info("UNRAR binary... found (%s)", sabnzbd.newsunpack.RAR_COMMAND)
# Report problematic unrar
if sabnzbd.newsunpack.RAR_PROBLEM:
if sabnzbd.newsunpack.RAR_PROBLEM and not sabnzbd.cfg.ignore_wrong_unrar():
have_str = "%.2f" % (float(sabnzbd.newsunpack.RAR_VERSION) / 100)
want_str = "%.2f" % (float(sabnzbd.constants.REC_RAR_VERSION) / 100)
logging.warning_helpful(
T("Your UNRAR version is %s, we recommend version %s or higher.<br />"), have_str, want_str
)
logging.warning(T("Your UNRAR version is %s, we recommend version %s or higher.<br />"), have_str, want_str)
elif not (sabnzbd.WIN32 or sabnzbd.DARWIN):
logging.info("UNRAR binary version %.2f", (float(sabnzbd.newsunpack.RAR_VERSION) / 100))
else:
@@ -507,8 +495,8 @@ def check_resolve(host):
def get_webhost(cherryhost, cherryport, https_port):
"""Determine the webhost address and port,
return (host, port, browserhost)
""" Determine the webhost address and port,
return (host, port, browserhost)
"""
if cherryhost == "0.0.0.0" and not check_resolve("127.0.0.1"):
cherryhost = ""
@@ -604,7 +592,7 @@ def get_webhost(cherryhost, cherryport, https_port):
logging.info("IPV6 has priority on this system, potential Firefox issue")
if ipv6 and ipv4 and cherryhost == "" and sabnzbd.WIN32:
logging.warning_helpful(T("Please be aware the 0.0.0.0 hostname will need an IPv6 address for external access"))
logging.warning(T("Please be aware the 0.0.0.0 hostname will need an IPv6 address for external access"))
if cherryhost == "localhost" and not sabnzbd.WIN32 and not sabnzbd.DARWIN:
# On the Ubuntu family, localhost leads to problems for CherryPy
@@ -679,8 +667,8 @@ def find_free_port(host, currentport):
def check_for_sabnzbd(url, upload_nzbs, allow_browser=True):
"""Check for a running instance of sabnzbd on this port
allow_browser==True|None will launch the browser, False will not.
""" Check for a running instance of sabnzbd on this port
allow_browser==True|None will launch the browser, False will not.
"""
if allow_browser is None:
allow_browser = True
@@ -702,10 +690,10 @@ def check_for_sabnzbd(url, upload_nzbs, allow_browser=True):
def evaluate_inipath(path):
"""Derive INI file path from a partial path.
Full file path: if file does not exist the name must contain a dot
but not a leading dot.
foldername is enough, the standard name will be appended.
""" Derive INI file path from a partial path.
Full file path: if file does not exist the name must contain a dot
but not a leading dot.
foldername is enough, the standard name will be appended.
"""
path = os.path.normpath(os.path.abspath(path))
inipath = os.path.join(path, DEF_INI_FILE)
@@ -722,9 +710,9 @@ def evaluate_inipath(path):
def commandline_handler():
"""Split win32-service commands are true parameters
Returns:
service, sab_opts, serv_opts, upload_nzbs
""" Split win32-service commands are true parameters
Returns:
service, sab_opts, serv_opts, upload_nzbs
"""
service = ""
sab_opts = []
@@ -855,6 +843,7 @@ def main():
pid_path = None
pid_file = None
new_instance = False
osx_console = False
ipv6_hosting = None
_service, sab_opts, _serv_opts, upload_nzbs = commandline_handler()
@@ -1164,17 +1153,13 @@ def main():
# On Linux/FreeBSD/Unix "UTF-8" is strongly, strongly adviced:
if not sabnzbd.WIN32 and not sabnzbd.DARWIN and not ("utf-8" in sabnzbd.encoding.CODEPAGE.lower()):
logging.warning_helpful(
logging.warning(
T(
"SABnzbd was started with encoding %s, this should be UTF-8. Expect problems with Unicoded file and directory names in downloads."
),
sabnzbd.encoding.CODEPAGE,
)
# TODO: Remove after 3.1.0
if sys.hexversion < 0x03060000:
logging.warning_helpful("Python 3.5 is end-of-life. SABnzbd 3.2.0 will only run on Python 3.6 and above.")
# SSL Information
logging.info("SSL version = %s", ssl.OPENSSL_VERSION)
@@ -1412,7 +1397,6 @@ def main():
# Make available from both URLs
main_page = sabnzbd.interface.MainPage()
cherrypy.Application.relative_urls = "server"
cherrypy.tree.mount(main_page, "/", config=appconfig)
cherrypy.tree.mount(main_page, sabnzbd.cfg.url_base(), config=appconfig)
@@ -1653,9 +1637,9 @@ https://sabnzbd.org/wiki/advanced/sabnzbd-as-a-windows-service
def handle_windows_service():
"""Handle everything for Windows Service
Returns True when any service commands were detected or
when we have started as a service.
""" Handle everything for Windows Service
Returns True when any service commands were detected or
when we have started as a service.
"""
# Detect if running as Windows Service (only Vista and above!)
# Adapted from https://stackoverflow.com/a/55248281/5235502

View File

@@ -6,7 +6,8 @@ environment:
install:
- "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%"
- python --version
- python -m pip install --upgrade pip wheel
- python -m pip install --upgrade pip
- python -m pip install --upgrade wheel
- python -m pip install --upgrade -r requirements.txt
- python -m pip install --upgrade -r tests/requirements.txt

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Config"#-->
<!--#set global $help_uri="configuration/3.1/configure"#-->
<!--#set global $help_uri="configuration/3.0/configure"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#from sabnzbd.encoding import CODEPAGE#-->

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Categories"#-->
<!--#set global $help_uri="configuration/3.1/categories"#-->
<!--#set global $help_uri="configuration/3.0/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/3.1/folders"#-->
<!--#set global $help_uri="configuration/3.0/folders"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="General"#-->
<!--#set global $help_uri="configuration/3.1/general"#-->
<!--#set global $help_uri="configuration/3.0/general"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">

View File

@@ -1,12 +1,12 @@
<!--#set global $pane="Email"#-->
<!--#set global $help_uri="configuration/3.1/notifications"#-->
<!--#set global $help_uri="configuration/3.0/notifications"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#def show_notify_checkboxes($section_label)#-->
<!--#for $type in $notify_types#-->
<!--#for $type in $notify_keys#-->
<div class="field-pair">
<label class="config wide" for="${section_label}_prio_$type">
$T($notify_types[$type]).replace('/', ' / ')
$T($notify_texts[$type]).replace('/', ' / ') <!--#if $type == 'download'#--> / $T('link-pause') / $T('link-resume')<!--#end if#-->
</label>
<input type="checkbox" name="${section_label}_prio_$type" id="${section_label}_prio_$type" value="1" <!--#if int($getVar($section_label + '_prio_' + $type)) > 0 then 'checked="checked"' else ""#--> />
</div>
@@ -232,10 +232,10 @@
<span class="desc">$T('explain-prowl_apikey')</span>
</div>
<!--#set $section_label = 'prowl'#-->
<!--#for $type in $notify_types#-->
<!--#for $type in $notify_keys#-->
<div class="field-pair">
<label class="config" for="${section_label}_prio_$type">
$T($notify_types[$type]).replace('/', ' / ')
$T($notify_texts[$type]).replace('/', ' / ') <!--#if $type == 'download'#--> / $T('link-pause') / $T('link-resume')<!--#end if#-->
</label>
<select name="${section_label}_prio_$type" id="${section_label}_prio_$type">
<option value="-3" <!--#if $getVar($section_label + '_prio_' + $type) == -3 then 'selected="selected"' else ""#--> >$T('prowl-off')</option>
@@ -298,10 +298,10 @@
<span class="desc">$T('explain-pushover_emergency_expire')</span>
</div>
<!--#set $section_label = 'pushover'#-->
<!--#for $type in $notify_types#-->
<!--#for $type in $notify_keys#-->
<div class="field-pair">
<label class="config" for="${section_label}_prio_$type">
$T($notify_types[$type]).replace('/', ' / ')
$T($notify_texts[$type]).replace('/', ' / ') <!--#if $type == 'download'#--> / $T('link-pause') / $T('link-resume')<!--#end if#-->
</label>
<select name="${section_label}_prio_$type" id="${section_label}_prio_$type">
<option value="-3" <!--#if $getVar($section_label + '_prio_' + $type) == -3 then 'selected="selected"' else ""#--> >$T('pushover-off')</option>

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="RSS"#-->
<!--#set global $help_uri="configuration/3.1/rss"#-->
<!--#set global $help_uri="configuration/3.0/rss"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
<!--#if not $active_feed#-->

View File

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

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Servers"#-->
<!--#set global $help_uri="configuration/3.1/servers"#-->
<!--#set global $help_uri="configuration/3.0/servers"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Sorting"#-->
<!--#set global $help_uri="configuration/3.1/sorting"#-->
<!--#set global $help_uri="configuration/3.0/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/3.1/special"#-->
<!--#set global $help_uri="configuration/3.0/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/3.1/switches"#-->
<!--#set global $help_uri="configuration/3.0/switches"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
@@ -237,11 +237,6 @@
<input type="checkbox" name="ignore_samples" id="ignore_samples" value="1" <!--#if int($ignore_samples) > 0 then 'checked="checked"' else ""#--> />
<span class="desc">$T('explain-ignore_samples') $T('igsam-del').</span>
</div>
<div class="field-pair">
<label class="config" for="deobfuscate_final_filenames">$T('opt-deobfuscate_final_filenames')</label>
<input type="checkbox" name="deobfuscate_final_filenames" id="deobfuscate_final_filenames" value="1" <!--#if int($deobfuscate_final_filenames) > 0 then 'checked="checked"' else ""#--> />
<span class="desc">$T('explain-deobfuscate_final_filenames')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="enable_meta">$T('opt-enable_meta')</label>
<input type="checkbox" name="enable_meta" id="enable_meta" value="1" <!--#if int($enable_meta) > 0 then 'checked="checked"' else ""#--> />

View File

@@ -439,7 +439,7 @@
<button type="button" class="close" data-dismiss="modal">&times;</button>
<h4 class="modal-title">$T('Glitter-addNZB')</h4>
</div>
<div class="modal-body form-horizontal">
<div class="modal-body">
<div class="row">
<form data-bind="submit: addNZBFromURL" class="col-sm-6">
<fieldset>
@@ -470,45 +470,29 @@
</div>
<div class="clearfix"></div>
<hr />
<div class="form-group">
<label class="col-sm-4 control-label">$T('name')</label>
<div class="row form-horizontal">
<label class="col-sm-6 control-label">$T('Glitter-addnzbFilename')</label>
<div class="col-sm-6">
<input type="text" name="nzbname" id="nzbname" placeholder="$T('Glitter-addnzbFilename')" class="form-control" />
<input type="text" name="nzbname" id="nzbname" placeholder="$T('name')" class="form-control" />
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">$T('srv-password')</label>
<div class="col-sm-6">
<input type="text" name="password" id="password" placeholder="$T('srv-optional')" class="form-control" />
</div>
<hr />
<div class="clearfix"></div>
<div class="add-nzb-inputbox" title="$T('category')" data-tooltip="true" data-placement="left">
<span class="glyphicon glyphicon-tag"></span>
<select name="Category" class="form-control" data-bind="options: queue.categoriesList, optionsValue: 'catValue', optionsText: 'catText',"></select>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">$T('category')</label>
<div class="col-sm-6">
<select name="Category" class="form-control" data-bind="options: queue.categoriesList, optionsValue: 'catValue', optionsText: 'catText',"></select>
<span class="glyphicon glyphicon-tag"></span>
</div>
<div class="add-nzb-inputbox" 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: queue.priorityOptions, optionsValue: 'value', optionsText: 'name', optionsCaption: '$T('default')'"></select>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">$T('priority')</label>
<div class="col-sm-6">
<select name="Priority" class="form-control" data-bind="options: queue.priorityOptions, optionsValue: 'value', optionsText: 'name', optionsCaption: '$T('default')'"></select>
<span class="glyphicon glyphicon-sort-by-attributes-alt"></span>
</div>
<div class="add-nzb-inputbox" title="$T('swtag-pp')" data-tooltip="true" data-placement="left">
<span class="glyphicon glyphicon-check"></span>
<select name="Processing" class="form-control" data-bind="options: queue.processingOptions, optionsValue: 'value', optionsText: 'name', optionsCaption: '$T('default')'"></select>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">$T('swtag-pp')</label>
<div class="col-sm-6">
<select name="Processing" class="form-control" data-bind="options: queue.processingOptions, optionsValue: 'value', optionsText: 'name', optionsCaption: '$T('default')'"></select>
<span class="glyphicon glyphicon-check"></span>
</div>
</div>
<div class="form-group">
<label class="col-sm-4 control-label">$T('eoq-scripts')</label>
<div class="col-sm-6">
<select name="Post-processing" class="form-control" data-bind="options: queue.scriptsList, optionsCaption: '$T('default')', enable: (queue.scriptsList().length > 1)"></select>
<span class="glyphicon glyphicon-flash"></span>
</div>
<div class="add-nzb-inputbox" title="$T('eoq-scripts')" data-tooltip="true" data-placement="left">
<span class="glyphicon glyphicon-flash"></span>
<select name="Post-processing" class="form-control" data-bind="options: queue.scriptsList, optionsCaption: '$T('default')'"></select>
</div>
<div class="clearfix"></div>
</div>

View File

@@ -668,7 +668,6 @@ function ViewModel() {
mode: "addurl",
name: $(form.nzbURL).val(),
nzbname: $('#nzbname').val(),
password: $('#password').val(),
script: $('#modal-add-nzb select[name="Post-processing"]').val(),
priority: $('#modal-add-nzb select[name="Priority"]').val(),
pp: $('#modal-add-nzb select[name="Processing"]').val()
@@ -708,7 +707,6 @@ function ViewModel() {
data.append("name", file);
data.append("mode", "addfile");
data.append("nzbname", $('#nzbname').val());
data.append("password", $('#password').val());
data.append("script", $('#modal-add-nzb select[name="Post-processing"]').val())
data.append("priority", $('#modal-add-nzb select[name="Priority"]').val())
data.append("apikey", apiKey);

View File

@@ -852,24 +852,18 @@ tr.queue-item>td:first-child>a {
.multioperations-selector .add-nzb-inputbox {
width: 20%;
float: left;
}
.multioperations-selector .add-nzb-inputbox select {
display: inline-block;
width: calc(100% - 30px);
margin: 5px 0px 5px 2px;
}
.multioperations-selector .add-nzb-inputbox-small {
width: 80px;
float: right;
padding-left: 0;
padding-top: 12px;
padding-top: 2px;
}
.multioperations-selector .add-nzb-inputbox-small .label {
margin-left: 5px;
vertical-align: text-bottom;
margin-left: 2px;
}
.multioperations-selector .add-nzb-inputbox-small span {
@@ -890,7 +884,7 @@ tr.queue-item>td:first-child>a {
.multioperations-selector .add-nzb-inputbox-options {
width: auto;
padding-right: 7px;
padding-right: 6px;
}
.multioperations-selector .add-nzb-inputbox-small label[for="multiedit-pause"],
@@ -1282,8 +1276,7 @@ tr.queue-item>td:first-child>a {
min-height: 270px;
}
#modal-options .form-group,
#modal-add-nzb .form-group {
#modal-options .form-group {
margin-bottom: 5px;
}
@@ -1395,8 +1388,7 @@ tr.queue-item>td:first-child>a {
padding-bottom: 0;
}
#modal-options .col-sm-6,
#modal-add-nzb .col-sm-6 {
#modal-options .col-sm-6 {
padding-bottom: 3px;
}
@@ -1528,14 +1520,25 @@ tr.queue-item>td:first-child>a {
margin-bottom: 5px;
}
#modal-add-nzb .col-sm-6:first-of-type label {
text-align: right;
#modal-add-nzb .add-nzb-inputbox:nth-child(even) select {
width: 100%;
}
#modal-add-nzb select {
width: calc(100% - 35px);
.add-nzb-inputbox {
float: left;
width: 50%;
margin: 5px 0px;
padding-left: 20px;
}
.add-nzb-inputbox select {
display: inline-block;
margin-right: 5px;
width: calc(100% - 10px);
}
.add-nzb-inputbox span {
display: inline-block;
margin: 8px 2px 0px -20px;
}
.btn-file {

View File

Binary file not shown.

View File

@@ -5,7 +5,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: team@sabnzbd.org\n"
"Language-Team: SABnzbd <team@sabnzbd.org>\n"

View File

@@ -1,114 +0,0 @@
# SABnzbd Translation Template file EMAIL
# Copyright 2011-2020 The SABnzbd-Team
# team@sabnzbd.org
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Language-Team: Czech (https://www.transifex.com/sabnzbd/teams/111101/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: cs\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
#: email/email.tmpl:1
msgid ""
"##\n"
"## Default Email template for SABnzbd\n"
"## This a Cheetah template\n"
"## Documentation: http://sabnzbd.wikidot.com/email-templates\n"
"##\n"
"## Newlines and whitespace are significant!\n"
"##\n"
"## These are the email headers\n"
"To: $to\n"
"From: $from\n"
"Date: $date\n"
"Subject: SABnzbd has <!--#if $status then \"completed\" else \"failed\" #--> job $name\n"
"X-priority: 5\n"
"X-MS-priority: 5\n"
"## After this comes the body, the empty line is required!\n"
"\n"
"Hi,\n"
"<!--#if $status #-->\n"
"SABnzbd has downloaded \"$name\" <!--#if $msgid==\"\" then \"\" else \"(newzbin #\" + $msgid + \")\"#-->\n"
"<!--#else#-->\n"
"SABnzbd has failed to download \"$name\" <!--#if $msgid==\"\" then \"\" else \"(newzbin #\" + $msgid + \")\"#-->\n"
"<!--#end if#-->\n"
"Finished at $end_time\n"
"Downloaded $size\n"
"\n"
"Results of the job:\n"
"<!--#for $stage in $stages #-->\n"
"Stage $stage <!--#slurp#-->\n"
"<!--#for $result in $stages[$stage]#-->\n"
" $result <!--#slurp#-->\n"
"<!--#end for#-->\n"
"<!--#end for#-->\n"
"<!--#if $script!=\"\" #-->\n"
"Output from user script \"$script\" (Exit code = $script_ret):\n"
"$script_output\n"
"<!--#end if#-->\n"
"<!--#if $status #-->\n"
"Enjoy!\n"
"<!--#else#-->\n"
"Sorry!\n"
"<!--#end if#-->\n"
msgstr ""
#: email/rss.tmpl:1
msgid ""
"##\n"
"## RSS Email template for SABnzbd\n"
"## This a Cheetah template\n"
"## Documentation: http://sabnzbd.wikidot.com/email-templates\n"
"##\n"
"## Newlines and whitespace are significant!\n"
"##\n"
"## These are the email headers\n"
"To: $to\n"
"From: $from\n"
"Date: $date\n"
"Subject: SABnzbd has added $amount jobs to the queue\n"
"X-priority: 5\n"
"X-MS-priority: 5\n"
"## After this comes the body, the empty line is required!\n"
"\n"
"Hi,\n"
"\n"
"SABnzbd has added $amount job(s) to the queue.\n"
"They are from RSS feed \"$feed\".\n"
"<!--#for $job in $jobs#-->\n"
" $job <!--#slurp#-->\n"
"<!--#end for#-->\n"
"\n"
"Bye\n"
msgstr ""
#: email/badfetch.tmpl:1
msgid ""
"##\n"
"## Bad URL Fetch Email template for SABnzbd\n"
"## This a Cheetah template\n"
"## Documentation: http://sabnzbd.wikidot.com/email-templates\n"
"##\n"
"## Newlines and whitespace are significant!\n"
"##\n"
"## These are the email headers\n"
"To: $to\n"
"From: $from\n"
"Date: $date\n"
"Subject: SABnzbd failed to fetch an NZB\n"
"X-priority: 5\n"
"X-MS-priority: 5\n"
"## After this comes the body, the empty line is required!\n"
"\n"
"Hi,\n"
"\n"
"SABnzbd has failed to retrieve the NZB from $url.\n"
"The error message was: $msg\n"
"\n"
"Bye\n"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Danish (https://www.transifex.com/sabnzbd/teams/111101/da/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Spanish (https://www.transifex.com/sabnzbd/teams/111101/es/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Finnish (https://www.transifex.com/sabnzbd/teams/111101/fi/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: French (https://www.transifex.com/sabnzbd/teams/111101/fr/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: ION, 2020\n"
"Language-Team: Hebrew (https://www.transifex.com/sabnzbd/teams/111101/he/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Norwegian Bokmål (https://www.transifex.com/sabnzbd/teams/111101/nb/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Dutch (https://www.transifex.com/sabnzbd/teams/111101/nl/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Polish (https://www.transifex.com/sabnzbd/teams/111101/pl/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/sabnzbd/teams/111101/pt_BR/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Romanian (https://www.transifex.com/sabnzbd/teams/111101/ro/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Russian (https://www.transifex.com/sabnzbd/teams/111101/ru/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Serbian (https://www.transifex.com/sabnzbd/teams/111101/sr/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Swedish (https://www.transifex.com/sabnzbd/teams/111101/sv/)\n"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Chinese (China) (https://www.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"

View File

@@ -5,7 +5,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: team@sabnzbd.org\n"
"Language-Team: SABnzbd <team@sabnzbd.org>\n"
@@ -76,11 +76,6 @@ msgstr ""
msgid "SABnzbd was started with encoding %s, this should be UTF-8. Expect problems with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -153,11 +148,6 @@ msgstr ""
msgid "Loading %s failed"
msgstr ""
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr ""
@@ -211,12 +201,12 @@ msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords were tried)"
msgid "WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords were tried)"
msgid "WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -225,7 +215,7 @@ msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
#: sabnzbd/assembler.py
@@ -238,12 +228,12 @@ msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr ""
#: sabnzbd/assembler.py
@@ -680,11 +670,6 @@ msgstr ""
msgid "m"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -695,21 +680,6 @@ msgstr ""
msgid "Your password file contains more than 30 passwords, testing all these passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr ""
@@ -961,6 +931,16 @@ msgstr ""
msgid "Checking"
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr ""
@@ -991,16 +971,6 @@ msgstr ""
msgid "Startup/Shutdown"
msgstr ""
#. Notification - Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr ""
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr ""
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1119,7 +1089,6 @@ msgstr ""
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr ""
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr ""
@@ -1252,10 +1221,20 @@ msgstr ""
msgid "Limit Speed"
msgstr ""
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr ""
#: sabnzbd/osxmenu.py
msgid "min."
msgstr ""
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr ""
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1425,10 +1404,6 @@ msgstr ""
msgid "Download failed - Not on your server(s)"
msgstr ""
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr ""
#: sabnzbd/postproc.py
msgid "Moving"
msgstr ""
@@ -1490,6 +1465,10 @@ msgstr ""
msgid "Cannot create final folder %s"
msgstr ""
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr ""
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr ""
@@ -1522,11 +1501,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1547,11 +1521,6 @@ msgstr ""
msgid "Error while shutting down system"
msgstr ""
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3378,14 +3347,6 @@ msgstr ""
msgid "Delete after download"
msgstr ""
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid "If filenames of (large) files in the final folder look obfuscated or meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Danish (https://www.transifex.com/sabnzbd/teams/111101/da/)\n"
@@ -92,11 +92,6 @@ msgstr ""
"SABnzbd blev startet med kodning %s, dette bør være UTF-8. Forvent problemer"
" med Unicoded fil- og mappenavne i downloads."
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -169,11 +164,6 @@ msgstr "Fejl i tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Downloadning af %s mislykkedes"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "E-mail afsendelse mislykkedes"
@@ -228,20 +218,20 @@ msgstr "Fatal fejl i Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"Pauset job \"%s\" på grund af krypterede RAR fil (hvis oplyst, alle "
"adgangskoder blev forsøgt)"
"Advarsel: Pauset job \"%s\" på grund af krypterede RAR fil (hvis oplyst, "
"alle adgangskoder blev forsøgt)"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"Afbrudt job \"%s\" på grund af krypterede RAR fil (hvis oplyst, alle "
"adgangskoder blev forsøgt)"
"Advarsel: Afbrudt job \"%s\" på grund af krypterede RAR fil (hvis oplyst, "
"alle adgangskoder blev forsøgt)"
#: sabnzbd/assembler.py
msgid "Aborted, encryption detected"
@@ -249,8 +239,8 @@ msgstr "Afbrudt, kryptering registreret"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "I \"%s\" uønsket extension i RAR fil. Uønsket fil er \"%s\" "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "Advarsel: I \"%s\" uønsket extension i RAR fil. Uønsket fil er \"%s\" "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -262,13 +252,13 @@ msgstr "Afbrudt, uønsket extension fundet"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr "Pause job \"%s\" på grund af rating (%s)"
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "ADVARSEL: Pause job \"%s\" på grund af rating (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr "Afbrudt job \"%s\" på grund af rating (%s)"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "ADVARSEL: Afbrudt job \"%s\" på grund af rating (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -739,11 +729,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -756,21 +741,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Python script \"%s\" har ikke udfør (+x) tilladelsessæt"
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Køre script"
@@ -1027,6 +997,16 @@ msgstr "Tjekker ekstra filer"
msgid "Checking"
msgstr "Kontrollerer"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Python script \"%s\" har ikke udfør (+x) tilladelsessæt"
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Forsøger SFV verifikation"
@@ -1059,19 +1039,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Start/lukning"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Pause"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Genoptag"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1190,7 +1157,6 @@ msgstr "%s => mangler fra alle servere, afviser"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Ødelagt NZB fil %s, springer over (årsag=%s, linje=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Tom NZB fil %s"
@@ -1324,10 +1290,22 @@ msgstr "Tøm historik"
msgid "Limit Speed"
msgstr "Hastighedsbegrænsning"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Pause"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Genoptag"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1531,10 +1509,6 @@ msgstr "Overførslen kan mislykkes, kun %s af det krævede %s tilgængelig"
msgid "Download failed - Not on your server(s)"
msgstr "Download mislykkedes - ikke på din server (e)"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Efterbehandling"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Flytter"
@@ -1596,6 +1570,10 @@ msgstr "Overførsel fuldført"
msgid "Cannot create final folder %s"
msgstr "Kan ikke oprette endelig mappe %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Efterbehandling"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Ingen par2 sæt"
@@ -1628,11 +1606,6 @@ msgstr "RAR filer kontrolleres med succes"
msgid "RAR files failed to verify"
msgstr "RAR filer kunne ikke bekræfte"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1653,11 +1626,6 @@ msgstr "Det lykkedes ikke systemet at gå i standby"
msgid "Error while shutting down system"
msgstr "Fejl ved lukning af system"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3621,16 +3589,6 @@ msgstr "Filtrerer prøve filer (f.eks. video eksempler)."
msgid "Delete after download"
msgstr "Fjern efter download"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "verifikation HTTPS certifikat"

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"
@@ -97,11 +97,6 @@ msgstr ""
"sein. Es werden Probleme mit Unicode codierten Dateien und "
"Ordnerbezeichnungen in Downloads erwartet."
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -175,11 +170,6 @@ msgstr "Fehler in tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Fehler beim Laden von %s"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "E-Mail erfolgreich versendet"
@@ -235,20 +225,20 @@ msgstr "Schwerer Fehler im Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"\"%s\" wurde angehalten, da es ein verschlüsseltes RAR Archiv enthält (falls"
" unterstützt, wurden alle Passwörter ausprobiert)"
"ACHTUNG: \"%s\" wurde angehalten, da es ein verschlüsseltes RAR Archiv "
"enthält (falls unterstützt, wurden alle Passwörter ausprobiert)"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
" \"%s\" wurde abgebrochen, da es ein verschlüsseltes RAR Archiv enthält "
"(falls unterstützt, wurden alle Passwörter ausprobiert)"
"ACHTUNG: \"%s\" wurde abgebrochen, da es ein verschlüsseltes RAR Archiv "
"enthält (falls unterstützt, wurden alle Passwörter ausprobiert)"
#: sabnzbd/assembler.py
msgid "Aborted, encryption detected"
@@ -256,8 +246,9 @@ msgstr "Abgebrochen, Verschlüsselung vorhanden"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "Unerwünschter Typ \"%s\" in RAR Datei. Unerwünschte Datei ist %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"WARNUNG: Unerwünschter Typ \"%s\" in RAR Datei. Unerwünschte Datei ist %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -269,13 +260,13 @@ msgstr "Abgebrochen, unerwünschte Dateieindung gefunden"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr "Aufgabe \"%s\" aufgrund der Bewertung (%s) pausiert."
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "WARNUNG: Aufgabe \"%s\" aufgrund der Bewertung (%s) pausiert."
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr "Aufgabe \"%s\" aufgrund der Bewertung (%s) abgebrochen"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "Warnung: Aufgabe \"%s\" aufgrund der Bewertung (%s) abgebrochen"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -762,11 +753,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -782,21 +768,6 @@ msgstr ""
"Passwörter dauert sehr lange. Versuchen Sie, nur nützliche Passwörter "
"aufzulisten."
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr "[%s] Der Befehl in build_command ist nicht definiert."
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Dem Pythonskript \"%s\" fehlen die Ausführungsrechte (+x)"
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Ausführen des Skripts"
@@ -1057,6 +1028,16 @@ msgstr "Überprüfe zusätzliche Dateien"
msgid "Checking"
msgstr "Wird überprüft"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr "[%s] Der Befehl in build_command ist nicht definiert."
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Dem Pythonskript \"%s\" fehlen die Ausführungsrechte (+x)"
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Versuche SFV-Überprüfung"
@@ -1092,19 +1073,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Starten/Beenden"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Anhalten"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Fortsetzen"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1223,7 +1191,6 @@ msgstr "%s wurde auf keinem Server gefunden und daher übersprungen"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Ungültige NZB-Datei %s wird übersprungen: %s auf Zeile %s"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Leere NZB-Datei %s"
@@ -1360,10 +1327,22 @@ msgstr "Verlauf leeren"
msgid "Limit Speed"
msgstr "Geschwindigkeit begrenzen"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Anhalten"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "Min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Fortsetzen"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1579,10 +1558,6 @@ msgstr ""
msgid "Download failed - Not on your server(s)"
msgstr "Download fehlgeschlagen - Nicht auf deinem/n Server/n vorhanden"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Nachbearbeitung"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Verschiebevorgang"
@@ -1644,6 +1619,10 @@ msgstr "Download fertig"
msgid "Cannot create final folder %s"
msgstr "Konnte Download-Ordner %s nicht anlegen"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Nachbearbeitung"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Keine PAR2-Sätze"
@@ -1676,11 +1655,6 @@ msgstr "RAR-Datei erfolgreich überprüft"
msgid "RAR files failed to verify"
msgstr "RAR-Datei konnten nicht überprüft werden"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1701,11 +1675,6 @@ msgstr "Fehler beim Wechsel in den Bereitschaftsmodus"
msgid "Error while shutting down system"
msgstr "Fehler beim Herunterfahren des Systems"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3716,16 +3685,6 @@ msgstr "Beispieldateien herausfiltern (z.B. Videoausschnitte)"
msgid "Delete after download"
msgstr "Nach dem Download löschen"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "HTTPS Zertifikat Überprüfung"

View File

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Finnish (https://www.transifex.com/sabnzbd/teams/111101/fi/)\n"
@@ -92,11 +92,6 @@ msgstr ""
"Unicode-merkkejä tiedosto- ja kansionimissä sisältävät lataukset voivat "
"aiheuttaa ongelmia."
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -170,11 +165,6 @@ msgstr "Virhe tiedostossa tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Kohteen %s lataaminen epäonnistui"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "Sähköpostitus onnistui"
@@ -229,15 +219,15 @@ msgstr "Vakava virhe kohteessa Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -246,8 +236,10 @@ msgstr "Peruutettu, salattu arkisto tunnistettu"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"Varoitus: Latauksessa \"%s\" ei toivottu tiedostopääte RAR arkistossa. Ei "
"toivottu tiedosto on %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -259,13 +251,13 @@ msgstr "Peruutettu, ei toivottu tiedostopääte havaittu"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "VAROITUS : Keskeytetty lataus \"%s\", koska luokituksena (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "VAROITUS : Peruutettiin lataus \"%s\", koska luokituksena on (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -735,11 +727,6 @@ msgstr "t"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -752,21 +739,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Ajetaan skripti"
@@ -1020,6 +992,16 @@ msgstr ""
msgid "Checking"
msgstr "Tarkistetaan"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Yritetään SFV varmennusta"
@@ -1052,19 +1034,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Käynnistys/Sammutus"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Keskeytä"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Jatka"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1183,7 +1152,6 @@ msgstr "%s => puuttuu kaikilta palvelimilta, hylätään"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Virheellinen NZB tiedosto %s, ohitetaan (syy=%s, rivi=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Tyhjä NZB tiedosto %s"
@@ -1317,10 +1285,22 @@ msgstr "Tyhjennä historia"
msgid "Limit Speed"
msgstr "Nopeusrajoitus"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Keskeytä"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Jatka"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1524,10 +1504,6 @@ msgstr "Lataaminen saattaa epäonnistua, vain %s osaa %s osasta saatavilla"
msgid "Download failed - Not on your server(s)"
msgstr "Lataus epäonnistui - Ei ole palvelimilla"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Jälkikäsittely"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Siirretään"
@@ -1589,6 +1565,10 @@ msgstr "Lataus valmistui"
msgid "Cannot create final folder %s"
msgstr "Ei voitu luoda lopullista kansiota %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Jälkikäsittely"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Ei par2 arkistoja"
@@ -1621,11 +1601,6 @@ msgstr "RAR arkistot varmennettiin onnistuneesti"
msgid "RAR files failed to verify"
msgstr "RAR arkistoja ei voitu varmentaa"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1646,11 +1621,6 @@ msgstr "Järjestelmän valmiustilaan laittaminen epäonnistui"
msgid "Error while shutting down system"
msgstr "Virhe sammutettaessa järjestelmää"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3624,16 +3594,6 @@ msgstr "Ohittaa näytetiedostot (esim. videonäytteet)."
msgid "Delete after download"
msgstr "Poista lataamisen jälkeen"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "HTTPS sertfikaatin varmennus"

View File

@@ -3,14 +3,14 @@
# team@sabnzbd.org
#
# Translators:
# Fred L <88com88@gmail.com>, 2020
# Safihre <safihre@sabnzbd.org>, 2020
# Fred L <88com88@gmail.com>, 2020
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Last-Translator: Fred L <88com88@gmail.com>, 2020\n"
"Language-Team: French (https://www.transifex.com/sabnzbd/teams/111101/fr/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -99,13 +99,6 @@ msgstr ""
"Attendez-vous à des problèmes avec les noms de fichiers et de répertoires "
"Unicode dans les téléchargements."
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
"Impossible de charger les certificats supplémentaires à partir du package "
"certifi"
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -178,11 +171,6 @@ msgstr "Échec dans tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Echec du chargement de %s"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr "Impossible d'accéder au fichier PID %s"
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "L'envoi de l'e-mail a réussi"
@@ -237,20 +225,20 @@ msgstr "Erreur fatale dans l'assembleur"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"La tâche \"%s\" a été mise en pause à cause d'un fichier RAR chiffré (tous "
"les mots de passe fournis ont été essayés)"
"ATTENTION : la tâche \"%s\" a été mise en pause à cause d'un fichier RAR "
"chiffré (tous les mots de passe fournis ont été essayés)"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"La tâche \"%s\" a été abandonnée à cause d'un fichier RAR chiffré (tous les "
"mots de passe fournis ont été essayés)"
"ATTENTION : la tâche \"%s\" a été abandonnée à cause d'un fichier RAR "
"chiffré (tous les mots de passe fournis ont été essayés)"
#: sabnzbd/assembler.py
msgid "Aborted, encryption detected"
@@ -258,10 +246,10 @@ msgstr "Interrompu, cryptage détecté"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"Le fichier RAR \"%s\" contient une extension indésirable. Le fichier "
"indésirable est %s "
"AVERTISSEMENT : Le fichier RAR\"%s\" contient une extension indésirable. Le "
"fichier indésirable est %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -273,13 +261,13 @@ msgstr "Interrompu, extension indésirable détectée"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr "Tâche \"%s\" mise en pause à cause du classement (%s)"
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "AVERTISSEMENT : Tâche \"%s\" mise en pause à cause du classement (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr "Tâche \"%s\" annulée à cause du classement (%s)"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "AVERTISSEMENT : tâche \"%s\" annulée à cause du classement (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -765,11 +753,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr "Échec de l'upload du fichier : %s"
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -785,23 +768,6 @@ msgstr ""
" ces mots de passe prend beaucoup de temps. Essayez de n'y lister que les "
"mots de passe utiles."
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr "Échec de lecture du fichier de mot de passe %s"
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr "[%s] La commande dans build_command n'est pas définie."
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
"Le script Python \"%s\" n'est pas configuré avec les permissions dexécution"
" (+x)"
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Exécution du script"
@@ -1062,6 +1028,18 @@ msgstr "Vérification des fichiers supplémentaires"
msgid "Checking"
msgstr "Vérification"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr "[%s] La commande dans build_command n'est pas définie."
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
"Le script Python \"%s\" n'est pas configuré avec les permissions dexécution"
" (+x)"
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Essai vérification SFV"
@@ -1097,19 +1075,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Démarrage/Arrêt"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Mettre en pause"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Reprendre"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1228,7 +1193,6 @@ msgstr "%s => absent de tous les serveurs, rejeté"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Fichier NZB invalide %s, ignoré (raison=%s, ligne=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Fichier NZB %s vide"
@@ -1362,10 +1326,22 @@ msgstr "Vider l'historique"
msgid "Limit Speed"
msgstr "Limiter la vitesse"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Mettre en pause"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Reprendre"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1581,10 +1557,6 @@ msgstr ""
msgid "Download failed - Not on your server(s)"
msgstr "Le téléchargement a échoué - absent de vos serveur(s)"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Post-traitement"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Déplacement"
@@ -1646,6 +1618,10 @@ msgstr "Téléchargement terminé"
msgid "Cannot create final folder %s"
msgstr "Impossible de créer le dossier final %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Post-traitement"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Pas de fichiers par2"
@@ -1678,11 +1654,6 @@ msgstr "Fichiers RAR vérifiés avec succès"
msgid "RAR files failed to verify"
msgstr "Echec lors de la vérification des fichiers RAR"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr "Aucun fichier rar antérieur correspondant pour %s"
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1703,11 +1674,6 @@ msgstr "Échec de la mise en veille"
msgid "Error while shutting down system"
msgstr "Erreur lors de l'arrêt du système"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr "Exception DBus reçue %s"
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3723,18 +3689,6 @@ msgstr "Exclure les fichiers échantillons (par ex. les samples vidéo)."
msgid "Delete after download"
msgstr "Supprimer après téléchargement"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr "Désobfusquer les noms de fichiers finaux"
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
"Si les noms de fichiers (volumineux) dans le dossier final semblent obscurs "
"ou dénués de sens, ils seront renommés avec le nom de la tâche."
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "Vérification du certificat HTTPS"

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: ION, 2020\n"
"Language-Team: Hebrew (https://www.transifex.com/sabnzbd/teams/111101/he/)\n"
@@ -88,11 +88,6 @@ msgstr ""
".של קבצים וסיפריות בהורדות Unicode צפה לבעיות עם שמות .UTF-8 היא אמורה להיות"
" ,%s הותחל עם קידוד SABnzbd"
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -165,11 +160,6 @@ msgstr "tempfile.mkstemp-כישלון ב"
msgid "Loading %s failed"
msgstr "נכשלה %s טעינת"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr "לא ניתן להשיג גישה אל קובץ PID בשם %s"
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "דוא״ל הצליח"
@@ -224,16 +214,20 @@ msgstr "Assembler-שגיאה חמורה ב"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"(מוצפן (במקרה שסופקה, כל הסיסמאות נוסו RAR בגלל קובץ \"%s\" אזהרה: השהה את "
"העבודה"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"(מוצפן (במקרה שסופקה, כל הסיסמאות נוסו RAR בגלל קובץ \"%s\" אזהרה: ביטל את "
"העבודה"
#: sabnzbd/assembler.py
msgid "Aborted, encryption detected"
@@ -241,8 +235,8 @@ msgstr "בוטל, הצפנה התגלתה"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "%s קובץ בלתי רצוי הוא .RAR סיומת בלתי רצויה בקובץ \"%s\"-אזהרה: ב "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -254,13 +248,13 @@ msgstr "בוטל, סיומת בלתי רצויה התגלתה"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "(%s) בגלל דירוג \"%s\" אזהרה: עבודה מושהת"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "(%s) בגלל דירוג \"%s\" אזהרה: עבודה בוטלה"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -729,11 +723,6 @@ msgstr "ש"
msgid "m"
msgstr "ד"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr "נכשל בהעלאת קובץ: %s"
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -748,21 +737,6 @@ msgstr ""
".קובץ הסיסמאות שלך מכיל יותר מ־30 סיסמאות, בחינת כל הסיסמאות האלו תיקח זמן "
"רב. נסה לכתוב ברשימה רק סיסמאות שימושיות"
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr "נכשל בקריאת קובץ הסיסמה %s"
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr "אינה מוגדרת build_command הפקודה ב [%s]"
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "(+x) אין ערכת הרשאות ביצוע \"%s\" לתסריט פייתון"
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "מריץ תסריט"
@@ -1015,6 +989,16 @@ msgstr "בודק קבצי תוספת"
msgid "Checking"
msgstr "בודק"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr "אינה מוגדרת build_command הפקודה ב [%s]"
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "(+x) אין ערכת הרשאות ביצוע \"%s\" לתסריט פייתון"
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "SFV מנסה וידוא"
@@ -1049,19 +1033,6 @@ msgstr "וויקי"
msgid "Startup/Shutdown"
msgstr "הזנק/כיבוי"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "השהה"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "המשך"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1180,7 +1151,6 @@ msgstr "חסר מכל השרתים, משליך <= %s"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "מדלג ,%s בלתי תקף NZB קובץ (סיבה=%s שורה=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "%s ריק NZB קובץ"
@@ -1314,10 +1284,22 @@ msgstr "טהר היסטוריה"
msgid "Limit Speed"
msgstr "הגבל מהירות"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "השהה"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "דקות"
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "המשך"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1525,10 +1507,6 @@ msgstr "הורדה עשויה להיכשל, רק %s מתוך %s דרושים ז
msgid "Download failed - Not on your server(s)"
msgstr "הורדה נכשלה - לא בשרת(ים) שלך"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "בתר־עיבוד"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "מעביר"
@@ -1590,6 +1568,10 @@ msgstr "הורדה הושלמה"
msgid "Cannot create final folder %s"
msgstr "%s לא יכול ליצור תיקייה סופית"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "בתר־עיבוד"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "par2 [%s] אין ערכות"
@@ -1622,11 +1604,6 @@ msgstr "קבצי RAR וודאו בהצלחה"
msgid "RAR files failed to verify"
msgstr "נכשלו בוידוא RAR קבצי"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr "אין קובץ rar קודם תואם עבור %s"
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1647,11 +1624,6 @@ msgstr "נכשל בהיכוננות מערכת"
msgid "Error while shutting down system"
msgstr "שגיאה בזמן כיבוי מערכת"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr "חריגת DBus התקבלה %s"
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3603,16 +3575,6 @@ msgstr "(סנן החוצה קבצי דוגמית (לדוגמה, דוגמיות
msgid "Delete after download"
msgstr "מחק לאחר הורדה"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "HTTPS וידוא אישור"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Norwegian Bokmål (https://www.transifex.com/sabnzbd/teams/111101/nb/)\n"
@@ -90,11 +90,6 @@ msgstr ""
"SABnzbd ble startet med koding %s, dette burde være UTF-8. Forvent problemer"
" med Unicode filer- og katalognavn i nedlastinger."
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -167,11 +162,6 @@ msgstr "Feil i tempfil.mkstemp"
msgid "Loading %s failed"
msgstr "Lasting av %s mislyktes"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "E-post sendning lykkes"
@@ -226,15 +216,15 @@ msgstr "Kritisk feil i Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -243,8 +233,8 @@ msgstr "Avbrutt, kryptering funnet"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "ADVARSEL: I \"%s\" uønsket filtype i RAR fil. Uønsket fil er %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -256,13 +246,13 @@ msgstr "Avbryt, uønsket forlenging oppdaget"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "ADVARSEL: Pauset jobb \"%s\" grunnet rangeringen (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "ADVARSEL: Avbrøt jobb \"%s\" grunnet rangering (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -731,11 +721,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -748,21 +733,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Kjører skript"
@@ -1017,6 +987,16 @@ msgstr ""
msgid "Checking"
msgstr "Undersøker"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Prøver SFV-verifisering"
@@ -1049,19 +1029,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Oppstart/avsluttning"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Stans midlertidig"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Gjenoppta"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1180,7 +1147,6 @@ msgstr "%s => mangler på alle servere, fjerner"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Feilaktig NZB fil %s, hopper over (årsak=%s, linje=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Tom NZB-fil %s"
@@ -1314,10 +1280,22 @@ msgstr "Slett historikk"
msgid "Limit Speed"
msgstr "Hastighetsbegrensning"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Stans midlertidig"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Gjenoppta"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1521,10 +1499,6 @@ msgstr "Nedlasting kan feile, kun %s av kravet på %s tilgjengelig"
msgid "Download failed - Not on your server(s)"
msgstr "Nedlastning feilet - Finnes ikke på din(e) server(e)"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Etterbehandling"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Flytter"
@@ -1586,6 +1560,10 @@ msgstr "Nedlasting ferdig"
msgid "Cannot create final folder %s"
msgstr "Kan ikke opprette mappe %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Etterbehandling"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Ingen par2 deler"
@@ -1618,11 +1596,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1643,11 +1616,6 @@ msgstr "Kunne ikke sette systemet i ventemodus"
msgid "Error while shutting down system"
msgstr "Feil under avslutting av systemet"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3599,16 +3567,6 @@ msgstr "Filtrere ut sample-filer (ex. video samplinger)."
msgid "Delete after download"
msgstr "Fjern etter nedlasting"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Dutch (https://www.transifex.com/sabnzbd/teams/111101/nl/)\n"
@@ -94,11 +94,6 @@ msgstr ""
"bij het downloaden, problemen krijgen met Unicode namen van bestanden en "
"mappen."
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr "Extra certificaten uit het certifi pakket konden niet geladen worden"
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -171,11 +166,6 @@ msgstr "Probleem met tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Inlezen van %s mislukt"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr "Kan het PID bestand %s niet benaderen"
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "E-mail verzonden"
@@ -230,20 +220,20 @@ msgstr "Onherstelbare fout in de Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"Download \"%s\" is gepauzeerd vanwege een versleuteld RAR bestand (indien "
"aanwezig, zijn alle wachtwoorden geprobeerd)"
"WAARSCHUWING: Download \"%s\" is gepauzeerd vanwege een versleuteld RAR "
"bestand (indien aanwezig, zijn alle wachtwoorden geprobeerd)"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
"Download \"%s\" is afgebroken vanwege een versleuteld RAR bestand (indien "
"aanwezig, zijn alle wachtwoorden geprobeerd)."
"WAARSCHUWING: Download \"%s\" is afgebroken vanwege een versleuteld RAR "
"bestand (indien aanwezig, zijn alle wachtwoorden"
#: sabnzbd/assembler.py
msgid "Aborted, encryption detected"
@@ -251,8 +241,10 @@ msgstr "Afgebroken, versleuteling ontdekt"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "Ongewenste extensie ontdekt in \"%s\". Het ongewenste bestand is \"%s\" "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"WAARSCHUWING: Ongewenste extensie ontdekt in \"%s\". Het ongewenste bestand "
"is \"%s\" "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -264,13 +256,13 @@ msgstr "Afgebroken, ongewenste extensie ontdekt"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr "Download '%s' gepauzeerd vanwege rating (%s)"
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "WAARSCHUWING: Download '%s' gepauzeerd vanwege rating (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr "Download '%s' afgebroken vanwege rating (%s)"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "WAARSCHUWING: Download '%s' afgebroken vanwege rating (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -753,11 +745,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr "Kon het volgende bestand niet uploaden: %s"
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -773,21 +760,6 @@ msgstr ""
"deze wachtwoorden kost heel veel tijd. Zorg ervoor dat je alleen maar "
"nuttige wachtwoorden in dit bestand zet."
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr "Kan het wachtwoord bestand niet uitlezen %s"
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr "[%s] Het commando in build_command is ongedefinieerd"
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Python-script '%s' heeft geen uitvoerpermissie (+x)"
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Script uitvoeren"
@@ -1044,6 +1016,16 @@ msgstr "Controleren van extra bestanden"
msgid "Checking"
msgstr "Controleren"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr "[%s] Het commando in build_command is ongedefinieerd"
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Python-script '%s' heeft geen uitvoerpermissie (+x)"
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Probeer SFV-verificatie"
@@ -1079,19 +1061,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Opstarten/Afsluiten"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Pauze"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Doorgaan"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1210,7 +1179,6 @@ msgstr "%s => ontbreekt op alle servers, overslaan"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Foutief NZB-bestand %s, overslaan (reden=%s, regel=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "NZB-bestand %s is leeg"
@@ -1344,10 +1312,22 @@ msgstr "Wis de volledige geschiedenis"
msgid "Limit Speed"
msgstr "Beperk snelheid"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Pauze"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Doorgaan"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1556,10 +1536,6 @@ msgstr ""
msgid "Download failed - Not on your server(s)"
msgstr "Download mislukt - Niet meer op je server(s)"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Nabewerking"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Verplaatsen"
@@ -1621,6 +1597,10 @@ msgstr "Download voltooid"
msgid "Cannot create final folder %s"
msgstr "Kan bestemmingsmap %s niet maken"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Nabewerking"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Geen par2 groepen"
@@ -1653,11 +1633,6 @@ msgstr "RAR bestanden zijn succesvol geverifieerd"
msgid "RAR files failed to verify"
msgstr "RAR bestanden zijn niet verifieerbaar"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr "Geen voorgaand rar-bestand gevonden bij %s"
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1678,11 +1653,6 @@ msgstr "Kan het systeem niet in standby krijgen"
msgid "Error while shutting down system"
msgstr "Fout bij het afsluiten van het systeem"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr "DBus foutmelding %s "
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3086,7 +3056,7 @@ msgstr ""
#: sabnzbd/skintext.py
msgid "History Retention"
msgstr "Geschiedenis bewaren"
msgstr "Geschiedenis Bewaren"
#: sabnzbd/skintext.py
msgid ""
@@ -3525,7 +3495,7 @@ msgstr ""
#: sabnzbd/skintext.py
msgid "On failure, try alternative NZB"
msgstr "Bij mislukte download: probeer alternatieve NZB"
msgstr "Bij mislukking: probeer alternatieve NZB"
#: sabnzbd/skintext.py
msgid "Some servers provide an alternative NZB when a download fails."
@@ -3675,19 +3645,6 @@ msgstr "Wat te doen met \"sample\"-bestanden?"
msgid "Delete after download"
msgstr "Verwijderen na download"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr "Verbeter bestandsnamen van voltooide downloads"
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
"Als bestandsnamen van (grote) bestanden na een voltooide download onlogisch "
"of verhaspelt lijken (obfuscated), worden ze vervangen door de naam van de "
"download."
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "HTTPS certificaatverificatie"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Polish (https://www.transifex.com/sabnzbd/teams/111101/pl/)\n"
@@ -85,11 +85,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -162,11 +157,6 @@ msgstr "Błąd w tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Nie udało się wczytać %s"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "Wiadomość wysłana"
@@ -221,15 +211,15 @@ msgstr "Błąd krytyczny w module składającym"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -238,8 +228,10 @@ msgstr "Przerwano, wykryto szyfrowanie"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"UWAGA: Plik z niepożądanym rozszerzeniem wewnątrz pliku RAR \"%s\". "
"Niepożądany plik to %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -251,13 +243,13 @@ msgstr "Przerwano, wykryto niepożądane rozszerzenie"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "UWAGA: Zadanie \"%s\" zostało wstrzymane z powodu oceny (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "UWAGA: Zadanie \"%s\" zostało przerwane z powodu oceny (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -730,11 +722,6 @@ msgstr "g"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -747,21 +734,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Uruchamianie skryptu"
@@ -1018,6 +990,16 @@ msgstr ""
msgid "Checking"
msgstr "Sprawdzanie"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Próba weryfikacji SFV"
@@ -1050,19 +1032,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Uruchomienie/Wyłączenie"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Wstrzymaj"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Wznów"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1181,7 +1150,6 @@ msgstr "%s => nie znaleziono na żadnym serwerze, porzucam"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Nieprawidłowy plik NZB %s, pomijam (powód=%s, linia=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Pusty plik NZB %s"
@@ -1315,10 +1283,22 @@ msgstr "Wyczyść historię"
msgid "Limit Speed"
msgstr "Ogranicz prędkość"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Wstrzymaj"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Wznów"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1526,10 +1506,6 @@ msgstr "Pobieranie może się nie udać, dostępne jedynie %s z wymaganych %s"
msgid "Download failed - Not on your server(s)"
msgstr "Pobieranie nieudane - Dane niedostępne na skonfigurowanych serwerach"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Przetwarzanie końcowe"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Przenoszenie"
@@ -1591,6 +1567,10 @@ msgstr "Zakończono pobieranie"
msgid "Cannot create final folder %s"
msgstr "Nie można utworzyć ostatecznego katalogu %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Przetwarzanie końcowe"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s} Brak zestawów par2"
@@ -1623,11 +1603,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1648,11 +1623,6 @@ msgstr "Wstrzymanie systemu nie powiodło się"
msgid "Error while shutting down system"
msgstr "Wyłączenie systemu nie powiodło się"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3610,16 +3580,6 @@ msgstr "Działania, które zostaną podjęte dla plików próbek (np. próbek wi
msgid "Delete after download"
msgstr "Usuń po pobraniu"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Portuguese (Brazil) (https://www.transifex.com/sabnzbd/teams/111101/pt_BR/)\n"
@@ -89,11 +89,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -166,11 +161,6 @@ msgstr "Falha em tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Falha ao carregar %s"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "E-mail enviado com sucesso"
@@ -225,15 +215,15 @@ msgstr "Erro fatal no Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -242,8 +232,10 @@ msgstr "Cancelado, criptografia detectada"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"ATENÇÃO: Extensão indesejada no arquivo RAR em \"%s\". O arquivo não "
"desejado é %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -255,13 +247,13 @@ msgstr "Cancelado, extensão indesejada detectada"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "ATENÇÃO: Tarefa \"%s\" em pausa em razão de pontuação (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "ATENÇÃO: Tarefa \"%s\" interrompida em razão de pontuação (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -734,11 +726,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -751,21 +738,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Executando script"
@@ -1019,6 +991,16 @@ msgstr ""
msgid "Checking"
msgstr "Verificando"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Tentando verificação SFV"
@@ -1051,19 +1033,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Inicialização/Encerramento"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Pausar"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Continuar"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1182,7 +1151,6 @@ msgstr "%s => faltando em todos os servidores. Descartando"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Arquivo NZB %s inválido. Pulando (razão=%s, linha=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Arquivo NZB %s vazio"
@@ -1316,10 +1284,22 @@ msgstr "Limpar Histórico"
msgid "Limit Speed"
msgstr "Limitar Velocidade"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Pausar"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Continuar"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1528,10 +1508,6 @@ msgstr ""
msgid "Download failed - Not on your server(s)"
msgstr "O download falhou - Não está em seu(s) servidor(s)"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Pós-processamento"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Movendo"
@@ -1593,6 +1569,10 @@ msgstr "Download concluído"
msgid "Cannot create final folder %s"
msgstr "Não é possível criar a pasta final %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Pós-processamento"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Nenhum conjunto par2"
@@ -1625,11 +1605,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1650,11 +1625,6 @@ msgstr "Falha ao colocar o sistema em espera"
msgid "Error while shutting down system"
msgstr "Erro ao desligar o sistema"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3614,16 +3584,6 @@ msgstr "Exclui arquivos de amostra. Exemplo: amostras de vídeo."
msgid "Delete after download"
msgstr "Excluir após download"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Romanian (https://www.transifex.com/sabnzbd/teams/111101/ro/)\n"
@@ -89,11 +89,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -166,11 +161,6 @@ msgstr "Eroare în tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Încărcarea %s nereuşită"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "Email reuşit"
@@ -225,15 +215,15 @@ msgstr "Eroare fatală în Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -242,8 +232,10 @@ msgstr "Terminat, encriptare detectată"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"ATENȚIE: În fișierul RAR \"%s\" sunt extensii nedorite. Fișierul nedorit "
"este %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -255,13 +247,13 @@ msgstr "Oprit, extensii nedorite detectate"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "ATENȚIE: Sarcina \"%s\" întrearuptă datorită ratingului (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "ATENȚIE: Sarcina \"%s\" anulată datorită ratingului (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -733,11 +725,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -750,21 +737,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Rulare script"
@@ -1019,6 +991,16 @@ msgstr ""
msgid "Checking"
msgstr "Se verifică"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Încerc verificare SFV"
@@ -1051,19 +1033,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Pornire/Închidere"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Pauză"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Reia"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1182,7 +1151,6 @@ msgstr "%s => lipsă de pe toate serverele, ignorare"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Fişier NZB invalid %s, ignorăm (motiv=%s, line=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Fişier NZB gol %s"
@@ -1316,10 +1284,22 @@ msgstr "Şterge Istoricul"
msgid "Limit Speed"
msgstr "Limitare de Viteză"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Pauză"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Reia"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1527,10 +1507,6 @@ msgstr "Descărcarea ar putea eşua, doar %s din %s disponibil"
msgid "Download failed - Not on your server(s)"
msgstr "Descărcare euată, - Nu este pe serverul(ele) dumneavoastră"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Post-procesare"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Mutare"
@@ -1592,6 +1568,10 @@ msgstr "Descărcare terminată"
msgid "Cannot create final folder %s"
msgstr "Nu pot crea dosar final %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Post-procesare"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Niciun set par2"
@@ -1624,11 +1604,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1649,11 +1624,6 @@ msgstr "Punere sistem în aşteptare nereuşită"
msgid "Error while shutting down system"
msgstr "Eroare la oprirea sistemului"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3607,16 +3577,6 @@ msgstr "Ignoră fişiere monstră (de ex. monstre video)"
msgid "Delete after download"
msgstr "Şterge după descărcare"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Russian (https://www.transifex.com/sabnzbd/teams/111101/ru/)\n"
@@ -89,11 +89,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -166,11 +161,6 @@ msgstr "Ошибка в tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Ошибка загрузки %s"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "Электронное письмо успешно отправлено"
@@ -225,15 +215,15 @@ msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -242,7 +232,7 @@ msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
#: sabnzbd/assembler.py
@@ -255,12 +245,12 @@ msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr ""
#: sabnzbd/assembler.py
@@ -732,11 +722,6 @@ msgstr "ч"
msgid "m"
msgstr "м"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -749,21 +734,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Запуск сценария"
@@ -1019,6 +989,16 @@ msgstr ""
msgid "Checking"
msgstr "Проверка"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Проверка SFV-суммы"
@@ -1051,19 +1031,6 @@ msgstr "Вики-сайт"
msgid "Startup/Shutdown"
msgstr "Запуск/остановка"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Приостановить"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Возобновить"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1182,7 +1149,6 @@ msgstr "%s => отсутствует на всех серверах, отбро
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Недопустимый NZB-файл %s: пропущен (причина — %s, строка — %s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Пустой NZB-файл %s"
@@ -1316,10 +1282,22 @@ msgstr "Очистить историю"
msgid "Limit Speed"
msgstr "Ограничение скорости"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Приостановить"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "мин."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Возобновить"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1525,10 +1503,6 @@ msgstr ""
msgid "Download failed - Not on your server(s)"
msgstr ""
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Пост-обработка"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Перемещение"
@@ -1590,6 +1564,10 @@ msgstr "Загрузка завершена"
msgid "Cannot create final folder %s"
msgstr "Не удаётся создать конечную папку %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Пост-обработка"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Нет PAR2-файлов"
@@ -1622,11 +1600,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1647,11 +1620,6 @@ msgstr "Не удалось перевести систему в состоян
msgid "Error while shutting down system"
msgstr "Не удалось завершить работу системы"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3598,16 +3566,6 @@ msgstr "Отфильтровывать файлы образцов (наприм
msgid "Delete after download"
msgstr "Удалить после загрузки"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Serbian (https://www.transifex.com/sabnzbd/teams/111101/sr/)\n"
@@ -87,11 +87,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -164,11 +159,6 @@ msgstr "Грешка у tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Učitavanje %s neuspešno"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "Упешно слање е-поште"
@@ -223,15 +213,15 @@ msgstr "Fatalna greška u Assembler-u"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -240,8 +230,10 @@ msgstr "Prekinuto, detektovana enkripcija"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"UPOZORENJE: U \"%s\" pronađena neželjena ekstenzija u RAR datoteci. "
"Neželjena datoteka je %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -253,13 +245,13 @@ msgstr "Prekinuto, detektovana neželjena ekstenzija"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "UPOZORENJE: Posao \"%s\" pauziran zbog ocene (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "UPOZORENJE: Posao \"%s\" prekinut zbog ocene (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -727,11 +719,6 @@ msgstr "с"
msgid "m"
msgstr "м"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -744,21 +731,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Покретање скрипта"
@@ -1013,6 +985,16 @@ msgstr ""
msgid "Checking"
msgstr "Провера"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Pokušaj SFV provere"
@@ -1045,19 +1027,6 @@ msgstr "Вики"
msgid "Startup/Shutdown"
msgstr "Покретање/Гашење"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Пауза"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Настави"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1176,7 +1145,6 @@ msgstr "%s => фали на свим серверима, одбацивање"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Неважећи NZB %s, прескакање (разлог=%s, линија=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "Празан NZB %s"
@@ -1310,10 +1278,22 @@ msgstr "Очисти хронологију"
msgid "Limit Speed"
msgstr "Ограничење брзине"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Пауза"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "мин."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Настави"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1517,10 +1497,6 @@ msgstr "Преузимање је можда погрешно. има %s од п
msgid "Download failed - Not on your server(s)"
msgstr "Неуспешно преузимање - није на вашем серверу"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Пост-процесирање"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Премештање"
@@ -1582,6 +1558,10 @@ msgstr "Преузимање завршено"
msgid "Cannot create final folder %s"
msgstr "Немогуће креирање фасцикле %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Пост-процесирање"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Нема par2 датотеке"
@@ -1614,11 +1594,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1639,11 +1614,6 @@ msgstr "Неуспено постављање система у стању пр
msgid "Error while shutting down system"
msgstr "Greška pri gašenju sistema"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3587,16 +3557,6 @@ msgstr "Филтрирај примерне датотеке (нпр. видео
msgid "Delete after download"
msgstr "Обриши после преузимања"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Swedish (https://www.transifex.com/sabnzbd/teams/111101/sv/)\n"
@@ -87,11 +87,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -164,11 +159,6 @@ msgstr "Fel i tempfile.mkstemp"
msgid "Loading %s failed"
msgstr "Laddning av %s misslyckades"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "E-mail sändning lyckades"
@@ -223,15 +213,15 @@ msgstr "Kritiskt fel i Assembler"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr ""
#: sabnzbd/assembler.py
@@ -240,8 +230,9 @@ msgstr "Avbruten, kryptering detekterad."
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr ""
"Varning: I \"%s\" otillåten filändelse i RAR-filen. Otillåtna filen är %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -253,13 +244,13 @@ msgstr "Avbruten, oönskad filändelse detekterad"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "VARNING: Pausat jobb \"%s\" pga betyg (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr ""
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "VARNING: Avbrutet jobb \"%s\" pga betyg (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -729,11 +720,6 @@ msgstr "h"
msgid "m"
msgstr "m"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -746,21 +732,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "Kör skript"
@@ -1017,6 +988,16 @@ msgstr ""
msgid "Checking"
msgstr "Kontrollerar"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr ""
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "Försöker verifiera SFV"
@@ -1049,19 +1030,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "Starta/Stäng"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "Pausa"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "Återuppta"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1180,7 +1148,6 @@ msgstr "%s => saknas från alla servrar, kastar"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "Felaktig NZB fil %s, hoppar över (orsak=%s, linje=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "NZB filen %s är tom"
@@ -1314,10 +1281,22 @@ msgstr "Töm historik"
msgid "Limit Speed"
msgstr "Hastighetsbegränsning"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "Pausa"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "min."
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "Återuppta"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1523,10 +1502,6 @@ msgstr "Nerladdningen kan misslyckas, bara %s av krävda %s finns tillgängligt"
msgid "Download failed - Not on your server(s)"
msgstr "Nerladdning misslyckades - Inte på din server eller servrar"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Efterbehandling"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "Flyttar"
@@ -1588,6 +1563,10 @@ msgstr "Hämtningen slutfördes"
msgid "Cannot create final folder %s"
msgstr "Kan inte skapa slutgiltig mapp %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "Efterbehandling"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] Ingen par2 sats"
@@ -1620,11 +1599,6 @@ msgstr ""
msgid "RAR files failed to verify"
msgstr ""
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1645,11 +1619,6 @@ msgstr "Det gick inte att sätta systemet i viloläge"
msgid "Error while shutting down system"
msgstr "Fel uppstod då systemet skulle stängas"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3598,16 +3567,6 @@ msgstr "Filtrera ut sample-filer (ex. video samplingar)."
msgid "Delete after download"
msgstr "Ta bort efter nedladdning"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr ""

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.1.0-develop\n"
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Chinese (China) (https://www.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"
@@ -85,11 +85,6 @@ msgid ""
"with Unicoded file and directory names in downloads."
msgstr "SABnzbd 以 %s 编码启动了,正常应该是 UTF-8。会导致下载文件夹中统一标准编码的文件和文件夹名称出现问题。"
#. Warning message
#: SABnzbd.py
msgid "Could not load additional certificates from certifi package"
msgstr ""
#. Warning message
#: SABnzbd.py
msgid "Disabled HTTPS because of missing CERT and KEY files"
@@ -162,11 +157,6 @@ msgstr "tempfile.mkstemp 出错"
msgid "Loading %s failed"
msgstr "加载 %s 失败"
#. Warning message
#: sabnzbd/__init__.py
msgid "Cannot access PID file %s"
msgstr ""
#: sabnzbd/api.py, sabnzbd/emailer.py
msgid "Email succeeded"
msgstr "成功发送电子邮件"
@@ -221,16 +211,16 @@ msgstr "Assembler 出现致命错误"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Paused job \"%s\" because of encrypted RAR file (if supplied, all passwords "
"were tried)"
msgstr "\"%s\" 任务已暂停,因其包含加密 RAR 文件 (已尝试所有的密码,如果提供了的话)"
"WARNING: Paused job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr "警告:\"%s\" 任务已暂停,因其包含加密 RAR 文件 (已尝试所有的密码,如果提供了的话)"
#. Warning message
#: sabnzbd/assembler.py
msgid ""
"Aborted job \"%s\" because of encrypted RAR file (if supplied, all passwords"
" were tried)"
msgstr "\"%s\" 任务已终止,因其包含加密 RAR 文件 (已尝试所有的密码,如果提供了的话)"
"WARNING: Aborted job \"%s\" because of encrypted RAR file (if supplied, all "
"passwords were tried)"
msgstr "警告:\"%s\" 任务已终止,因其包含加密 RAR 文件 (已尝试所有的密码,如果提供了的话)"
#: sabnzbd/assembler.py
msgid "Aborted, encryption detected"
@@ -238,8 +228,8 @@ msgstr "已中止,发现加密文件"
#. Warning message
#: sabnzbd/assembler.py
msgid "In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "RAR 文件“%s”中出现不需要的扩展名。不需要的文件名为 %s "
msgid "WARNING: In \"%s\" unwanted extension in RAR file. Unwanted file is %s "
msgstr "*警告*: RAR 文件“%s”中出现不需要的扩展名。不需要的文件名为 %s "
#: sabnzbd/assembler.py
msgid "Unwanted extension is in rar file %s"
@@ -251,13 +241,13 @@ msgstr "已中止,侦测到不需要的扩展名"
#. Warning message
#: sabnzbd/assembler.py
msgid "Paused job \"%s\" because of rating (%s)"
msgstr "任务“%s”已暂停由于评分过低 (%s)"
msgid "WARNING: Paused job \"%s\" because of rating (%s)"
msgstr "*警告*: 任务“%s”已暂停由于评分过低 (%s)"
#. Warning message
#: sabnzbd/assembler.py
msgid "Aborted job \"%s\" because of rating (%s)"
msgstr "任务“%s”已中止由于评分过低 (%s)"
msgid "WARNING: Aborted job \"%s\" because of rating (%s)"
msgstr "*警告*: 任务“%s”已中止由于评分过低 (%s)"
#: sabnzbd/assembler.py
msgid "Aborted, rating filter matched (%s)"
@@ -719,11 +709,6 @@ msgstr "小时"
msgid "m"
msgstr "分钟"
#. Error message
#: sabnzbd/misc.py
msgid "Failed to upload file: %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Error creating SSL key and certificate"
@@ -736,21 +721,6 @@ msgid ""
"passwords takes a lot of time. Try to only list useful passwords."
msgstr ""
#. Warning message
#: sabnzbd/misc.py
msgid "Failed to read the password file %s"
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/misc.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Python 脚本 \"%s\" 不具有执行 (+x) 权限"
#: sabnzbd/newsunpack.py, sabnzbd/postproc.py
msgid "Running script"
msgstr "正在执行脚本"
@@ -1003,6 +973,16 @@ msgstr ""
msgid "Checking"
msgstr "正在检查"
#. Error message
#: sabnzbd/newsunpack.py
msgid "[%s] The command in build_command is undefined."
msgstr ""
#. Error message
#: sabnzbd/newsunpack.py
msgid "Python script \"%s\" does not have execute (+x) permission set"
msgstr "Python 脚本 \"%s\" 不具有执行 (+x) 权限"
#: sabnzbd/newsunpack.py
msgid "Trying SFV verification"
msgstr "正在尝试 SFV 验证"
@@ -1035,19 +1015,6 @@ msgstr "Wiki"
msgid "Startup/Shutdown"
msgstr "启动/关闭"
#. Notification - Pause downloading - Four way switch for duplicates -
#. Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Pause"
msgstr "暂停"
#. Notification - Resume downloading - Config->Scheduling
#: sabnzbd/notifier.py, sabnzbd/osxmenu.py, sabnzbd/sabtray.py,
#: sabnzbd/sabtraylinux.py, sabnzbd/skintext.py
msgid "Resume"
msgstr "续传"
#. Notification - Config->RSS after adding to queue
#: sabnzbd/notifier.py, sabnzbd/skintext.py
msgid "Added NZB"
@@ -1166,7 +1133,6 @@ msgstr "%s => 所有服务器均缺失,正在舍弃"
msgid "Invalid NZB file %s, skipping (reason=%s, line=%s)"
msgstr "无效 NZB 文件 %s正在跳过 (原因=%s, 行=%s)"
#. Warning message
#: sabnzbd/nzbstuff.py, sabnzbd/urlgrabber.py
msgid "Empty NZB file %s"
msgstr "空 NZB 文件 %s"
@@ -1300,10 +1266,22 @@ msgstr "清空历史"
msgid "Limit Speed"
msgstr "限速"
#. Pause downloading - Four way switch for duplicates - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Pause"
msgstr "暂停"
#: sabnzbd/osxmenu.py
msgid "min."
msgstr "分钟"
#. Resume downloading - Config->Scheduling
#: sabnzbd/osxmenu.py, sabnzbd/sabtray.py, sabnzbd/sabtraylinux.py,
#: sabnzbd/skintext.py
msgid "Resume"
msgstr "续传"
#. #: Config->Scheduler
#: sabnzbd/osxmenu.py, sabnzbd/skintext.py
msgid "Scan watched folder"
@@ -1507,10 +1485,6 @@ msgstr "下载可能会失败,只有 %s 块 (需要 %s) 可用"
msgid "Download failed - Not on your server(s)"
msgstr "下载失败 - 不在该服务器上"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "后期处理"
#: sabnzbd/postproc.py
msgid "Moving"
msgstr "正在移动"
@@ -1572,6 +1546,10 @@ msgstr "下载完成"
msgid "Cannot create final folder %s"
msgstr "无法创建最终文件夹 %s"
#: sabnzbd/postproc.py
msgid "Post-processing"
msgstr "后期处理"
#: sabnzbd/postproc.py
msgid "[%s] No par2 sets"
msgstr "[%s] 无 par2 集合"
@@ -1604,11 +1582,6 @@ msgstr "RAR 文件验证成功"
msgid "RAR files failed to verify"
msgstr "RAR 文件验证失败"
#. Warning message
#: sabnzbd/postproc.py
msgid "No matching earlier rar file for %s"
msgstr ""
#. Error message
#: sabnzbd/postproc.py
msgid "Removing %s failed"
@@ -1629,11 +1602,6 @@ msgstr "系统待机失败"
msgid "Error while shutting down system"
msgstr "关闭系统时出错"
#. Error message
#: sabnzbd/powersup.py
msgid "Received a DBus exception %s"
msgstr ""
#. Warning message
#: sabnzbd/rating.py
msgid "Indexer id (%s) not found for ratings file"
@@ -3537,16 +3505,6 @@ msgstr "过滤样本文件 (如视频样本)。"
msgid "Delete after download"
msgstr "下载后删除"
#: sabnzbd/skintext.py
msgid "Deobfuscate final filenames"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"If filenames of (large) files in the final folder look obfuscated or "
"meaningless they will be renamed to the job name."
msgstr ""
#: sabnzbd/skintext.py
msgid "HTTPS certificate verification"
msgstr "HTTPS 证书验证"

View File

@@ -1,73 +0,0 @@
# SABnzbd Translation Template file NSIS
# Copyright 2011-2020 The SABnzbd-Team
# team@sabnzbd.org
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Language-Team: Czech (https://www.transifex.com/sabnzbd/teams/111101/cs/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: cs\n"
"Plural-Forms: nplurals=4; plural=(n == 1 && n % 1 == 0) ? 0 : (n >= 2 && n <= 4 && n % 1 == 0) ? 1: (n % 1 != 0 ) ? 2 : 3;\n"
#: NSIS_Installer.nsi
msgid "Show Release Notes"
msgstr ""
#: NSIS_Installer.nsi
msgid "Support the project, Donate!"
msgstr ""
#: NSIS_Installer.nsi
msgid "Please close \"SABnzbd.exe\" first"
msgstr ""
#: NSIS_Installer.nsi
msgid ""
"The SABnzbd Windows Service changed in SABnzbd 3.0.0. \\nYou will need to "
"reinstall the SABnzbd service. \\n\\nClick `OK` to remove the existing "
"services or `Cancel` to cancel this upgrade."
msgstr ""
#: NSIS_Installer.nsi
msgid ""
"The installer only supports 64-bit Windows, use the standalone version to "
"run on 32-bit Windows."
msgstr ""
#: NSIS_Installer.nsi
msgid "This will uninstall SABnzbd from your system"
msgstr ""
#: NSIS_Installer.nsi
msgid "Run at startup"
msgstr ""
#: NSIS_Installer.nsi
msgid "Desktop Icon"
msgstr ""
#: NSIS_Installer.nsi
msgid "NZB File association"
msgstr ""
#: NSIS_Installer.nsi
msgid "Delete Program"
msgstr ""
#: NSIS_Installer.nsi
msgid "Delete Settings"
msgstr ""
#: NSIS_Installer.nsi
msgid ""
"You cannot overwrite an existing installation. \\n\\nClick `OK` to remove "
"the previous version or `Cancel` to cancel this upgrade."
msgstr ""
#: NSIS_Installer.nsi
msgid "Your settings and data will be preserved."
msgstr ""

View File

@@ -4,13 +4,12 @@
#
# Translators:
# Safihre <safihre@sabnzbd.org>, 2020
# Ester Molla Aragones <moarages@gmail.com>, 2020
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-3.0.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Ester Molla Aragones <moarages@gmail.com>, 2020\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2020\n"
"Language-Team: Spanish (https://www.transifex.com/sabnzbd/teams/111101/es/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -36,18 +35,12 @@ msgid ""
"reinstall the SABnzbd service. \\n\\nClick `OK` to remove the existing "
"services or `Cancel` to cancel this upgrade."
msgstr ""
"El servicio de Windows para SABnzbd ha cambiado en la versión SABnzbd "
"3.0.0.\\nNecesitará volver a instalar el servicio SABnzbd. \\n\\nHaga clic "
"en \"OK\" para eliminar los servicios existentes o \"Cancelar\" para "
"cancelar la actualización."
#: NSIS_Installer.nsi
msgid ""
"The installer only supports 64-bit Windows, use the standalone version to "
"run on 32-bit Windows."
msgstr ""
"El instalador solo admite Windows 64-bit, utilice la versión independiente "
"para ejecutar Windows 32-bit."
#: NSIS_Installer.nsi
msgid "This will uninstall SABnzbd from your system"

View File

@@ -24,6 +24,7 @@ import datetime
import tempfile
import pickle
import gzip
import subprocess
import time
import socket
import cherrypy
@@ -531,8 +532,8 @@ def guard_language():
def set_https_verification(value):
"""Set HTTPS-verification state while returning current setting
False = disable verification
""" Set HTTPS-verification state while returning current setting
False = disable verification
"""
prev = ssl._create_default_https_context == ssl.create_default_context
if value:
@@ -547,7 +548,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, password=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
@@ -566,12 +567,6 @@ def add_url(url, pp=None, script=None, cat=None, priority=None, nzbname=None, pa
# Generate the placeholder
future_nzo = NzbQueue.do.generate_future(msg, pp, script, cat, url=url, priority=priority, nzbname=nzbname)
# Set password
if not future_nzo.password:
future_nzo.password = password
# Get it!
URLGrabber.do.add(url, future_nzo)
return future_nzo.nzo_id
@@ -660,8 +655,8 @@ def add_nzbfile(
password=None,
nzo_id=None,
):
"""Add file, either a single NZB-file or an archive.
All other parameters are passed to the NZO-creation.
""" Add file, either a single NZB-file or an archive.
All other parameters are passed to the NZO-creation.
"""
if pp == "-1":
pp = None
@@ -815,9 +810,9 @@ def restart_program():
def change_queue_complete_action(action, new=True):
"""Action or script to be performed once the queue has been completed
Scripts are prefixed with 'script_'
When "new" is False, check whether non-script actions are acceptable
""" Action or script to be performed once the queue has been completed
Scripts are prefixed with 'script_'
When "new" is False, check whether non-script actions are acceptable
"""
global QUEUECOMPLETE, QUEUECOMPLETEACTION, QUEUECOMPLETEARG
@@ -856,10 +851,19 @@ def run_script(script):
script_path = filesystem.make_script_path(script)
if script_path:
try:
script_output = misc.run_command([script_path])
logging.info("Output of queue-complete script %s: \n%s", script, script_output)
stup, need_shell, command, creationflags = sabnzbd.newsunpack.build_command([script_path])
logging.info("Spawning external command %s", command)
subprocess.Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
except:
logging.info("Failed queue-complete script %s, Traceback: ", script, exc_info=True)
logging.debug("Failed script %s, Traceback: ", script, exc_info=True)
def empty_queues():
@@ -896,8 +900,8 @@ def keep_awake():
def get_new_id(prefix, folder, check_list=None):
"""Return unique prefixed admin identifier within folder
optionally making sure that id is not in the check_list.
""" Return unique prefixed admin identifier within folder
optionally making sure that id is not in the check_list.
"""
for n in range(100):
try:
@@ -1020,8 +1024,8 @@ def check_repair_request():
def check_all_tasks():
"""Check every task and restart safe ones, else restart program
Return True when everything is under control
""" Check every task and restart safe ones, else restart program
Return True when everything is under control
"""
if __SHUTTING_DOWN__ or not __INITIALIZED__:
return True
@@ -1087,7 +1091,7 @@ def pid_file(pid_path=None, pid_file=None, port=0):
else:
filesystem.remove_file(DIR_PID)
except:
logging.warning(T("Cannot access PID file %s"), DIR_PID)
logging.warning("Cannot access PID file %s", DIR_PID)
def check_incomplete_vs_complete():

View File

@@ -41,9 +41,11 @@ from sabnzbd.constants import (
VALID_ARCHIVES,
VALID_NZB_FILES,
Status,
FORCE_PRIORITY,
TOP_PRIORITY,
REPAIR_PRIORITY,
HIGH_PRIORITY,
NORMAL_PRIORITY,
INTERFACE_PRIORITIES,
LOW_PRIORITY,
KIBI,
MEBI,
GIGI,
@@ -66,7 +68,7 @@ from sabnzbd.misc import (
calc_age,
opts_to_pp,
)
from sabnzbd.filesystem import diskspace, get_ext, globber_full, clip_path, remove_all, userxbit
from sabnzbd.filesystem import diskspace, get_ext, globber_full, clip_path, remove_all
from sabnzbd.encoding import xml_name
from sabnzbd.postproc import PostProcessor
from sabnzbd.articlecache import ArticleCache
@@ -74,6 +76,7 @@ from sabnzbd.utils.servertests import test_nntp_server_dict
from sabnzbd.bpsmeter import BPSMeter
from sabnzbd.rating import Rating
from sabnzbd.getipaddress import localipv4, publicipv4, ipv6, addresslookup
from sabnzbd.newsunpack import userxbit
from sabnzbd.database import build_history_info, unpack_history_info, HistoryDB
import sabnzbd.notifier
import sabnzbd.rss
@@ -363,7 +366,6 @@ def _api_addfile(name, output, kwargs):
cat=cat,
priority=kwargs.get("priority"),
nzbname=kwargs.get("nzbname"),
password=kwargs.get("password"),
)
return report(output, keyword="", data={"status": res == 0, "nzo_ids": nzo_ids})
else:
@@ -408,18 +410,10 @@ def _api_addlocalfile(name, output, kwargs):
cat = cat_convert(xcat)
priority = kwargs.get("priority")
nzbname = kwargs.get("nzbname")
password = kwargs.get("password")
if get_ext(name) in VALID_ARCHIVES + VALID_NZB_FILES:
res, nzo_ids = sabnzbd.add_nzbfile(
name,
pp=pp,
script=script,
cat=cat,
priority=priority,
keep=True,
nzbname=nzbname,
password=password,
name, pp=pp, script=script, cat=cat, priority=priority, keep=True, nzbname=nzbname
)
return report(output, keyword="", data={"status": res == 0, "nzo_ids": nzo_ids})
else:
@@ -567,10 +561,9 @@ def _api_addurl(name, output, kwargs):
cat = kwargs.get("cat")
priority = kwargs.get("priority")
nzbname = kwargs.get("nzbname", "")
password = kwargs.get("password", "")
if name:
nzo_id = sabnzbd.add_url(name, pp, script, cat, priority, nzbname, password)
nzo_id = sabnzbd.add_url(name, pp, script, cat, priority, nzbname)
# Reporting a list of NZO's, for compatibility with other add-methods
return report(output, keyword="", data={"status": True, "nzo_ids": [nzo_id]})
else:
@@ -1001,10 +994,10 @@ def api_level(cmd, name):
def report(output, error=None, keyword="value", data=None):
"""Report message in json, xml or plain text
If error is set, only an status/error report is made.
If no error and no data, only a status report is made.
Else, a data report is made (optional 'keyword' for outer XML section).
""" Report message in json, xml or plain text
If error is set, only an status/error report is made.
If no error and no data, only a status report is made.
Else, a data report is made (optional 'keyword' for outer XML section).
"""
if output == "json":
content = "application/json;charset=UTF-8"
@@ -1048,10 +1041,10 @@ def report(output, error=None, keyword="value", data=None):
class xml_factory:
"""Recursive xml string maker. Feed it a mixed tuple/dict/item object and will output into an xml string
Current limitations:
In Two tiered lists hard-coded name of "item": <cat_list><item> </item></cat_list>
In Three tiered lists hard-coded name of "slot": <tier1><slot><tier2> </tier2></slot></tier1>
""" Recursive xml string maker. Feed it a mixed tuple/dict/item object and will output into an xml string
Current limitations:
In Two tiered lists hard-coded name of "item": <cat_list><item> </item></cat_list>
In Three tiered lists hard-coded name of "slot": <tier1><slot><tier2> </tier2></slot></tier1>
"""
def __init__(self):
@@ -1296,6 +1289,13 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None):
)
datestart = datetime.datetime.now()
priorities = {
TOP_PRIORITY: "Force",
REPAIR_PRIORITY: "Repair",
HIGH_PRIORITY: "High",
NORMAL_PRIORITY: "Normal",
LOW_PRIORITY: "Low",
}
limit = int_conv(limit)
start = int_conv(start)
@@ -1326,7 +1326,7 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None):
slot["index"] = n
slot["nzo_id"] = str(nzo_id)
slot["unpackopts"] = str(opts_to_pp(pnfo.repair, pnfo.unpack, pnfo.delete))
slot["priority"] = INTERFACE_PRIORITIES.get(priority, NORMAL_PRIORITY)
slot["priority"] = priorities[priority] if priority >= LOW_PRIORITY else priorities[NORMAL_PRIORITY]
slot["script"] = pnfo.script if pnfo.script else "None"
slot["filename"] = pnfo.filename
slot["labels"] = pnfo.labels
@@ -1352,7 +1352,7 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None):
slot["status"] = Status.DOWNLOADING
else:
# Ensure compatibility of API status
if status == Status.DELETED or priority == FORCE_PRIORITY:
if status == Status.DELETED or priority == TOP_PRIORITY:
status = Status.DOWNLOADING
slot["status"] = "%s" % status
@@ -1361,7 +1361,7 @@ def build_queue(start=0, limit=0, trans=False, output=None, search=None):
or Downloader.do.postproc
or is_propagating
or status not in (Status.DOWNLOADING, Status.FETCHING, Status.QUEUED)
) and priority != FORCE_PRIORITY:
) and priority != TOP_PRIORITY:
slot["timeleft"] = "0:00:00"
slot["eta"] = "unknown"
else:
@@ -1408,7 +1408,8 @@ def fast_queue():
def build_file_list(nzo_id):
"""Build file lists for specified job"""
""" Build file lists for specified job
"""
jobs = []
nzo = NzbQueue.do.get_nzo(nzo_id)
if nzo:
@@ -1539,9 +1540,9 @@ _SKIN_CACHE = {} # Stores pre-translated acronyms
def Ttemplate(txt):
"""Translation function for Skin texts
This special is to be used in interface.py for template processing
to be passed for the $T function: so { ..., 'T' : Ttemplate, ...}
""" Translation function for Skin texts
This special is to be used in interface.py for template processing
to be passed for the $T function: so { ..., 'T' : Ttemplate, ...}
"""
global _SKIN_CACHE
if txt in _SKIN_CACHE:
@@ -1887,8 +1888,8 @@ def list_scripts(default=False, none=True):
def list_cats(default=True):
"""Return list of (ordered) categories,
when default==False use '*' for Default category
""" Return list of (ordered) categories,
when default==False use '*' for Default category
"""
lst = [cat["name"] for cat in config.get_ordered_categories()]
if default:

View File

@@ -27,9 +27,9 @@ import sabnzbd
from sabnzbd.decorators import synchronized
from sabnzbd.constants import GIGI, ANFO, MEBI, LIMIT_DECODE_QUEUE, MIN_DECODE_QUEUE
# Operations on the article table are handled via try/except.
# The counters need to be made atomic to ensure consistency.
ARTICLE_COUNTER_LOCK = threading.RLock()
# Operations on lists and dicts are atomic, but for
# the bytes counter we do need a lock
ARTICLE_LOCK = threading.Lock()
class ArticleCache:
@@ -39,6 +39,7 @@ class ArticleCache:
self.__cache_limit_org = 0
self.__cache_limit = 0
self.__cache_size = 0
self.__article_list = [] # List of buffered articles
self.__article_table = {} # Dict of buffered articles
# Limit for the decoder is based on the total available cache
@@ -54,7 +55,7 @@ class ArticleCache:
ArticleCache.do = self
def cache_info(self):
return ANFO(len(self.__article_table), abs(self.__cache_size), self.__cache_limit_org)
return ANFO(len(self.__article_list), abs(self.__cache_size), self.__cache_limit_org)
def new_limit(self, limit):
""" Called when cache limit changes """
@@ -70,12 +71,12 @@ class ArticleCache:
# The cache should also not be too small
self.decoder_cache_article_limit = max(decoder_cache_limit, MIN_DECODE_QUEUE)
@synchronized(ARTICLE_COUNTER_LOCK)
@synchronized(ARTICLE_LOCK)
def reserve_space(self, data_size):
""" Reserve space in the cache """
self.__cache_size += data_size
@synchronized(ARTICLE_COUNTER_LOCK)
@synchronized(ARTICLE_LOCK)
def free_reserved_space(self, data_size):
""" Remove previously reserved space """
self.__cache_size -= data_size
@@ -107,6 +108,7 @@ class ArticleCache:
self.reserve_space(data_size)
if self.space_left():
# Add new article to the cache
self.__article_list.append(article)
self.__article_table[article] = data
else:
# Return the space and save to disk
@@ -121,47 +123,35 @@ class ArticleCache:
data = None
nzo = article.nzf.nzo
if article in self.__article_table:
try:
data = self.__article_table.pop(article)
self.free_reserved_space(len(data))
except KeyError:
# Could fail due the article already being deleted by purge_articles, for example
# when post-processing deletes the job while delayed articles still come in
logging.debug("Failed to load %s from cache, probably already deleted", article)
return data
if article in self.__article_list:
data = self.__article_table.pop(article)
self.__article_list.remove(article)
self.free_reserved_space(len(data))
elif article.art_id:
data = sabnzbd.load_data(article.art_id, nzo.workpath, remove=True, do_pickle=False, silent=True)
nzo.remove_saved_article(article)
return data
@synchronized(ARTICLE_LOCK)
def flush_articles(self):
logging.debug("Saving %s cached articles to disk", len(self.__article_table))
self.__cache_size = 0
while self.__article_table:
try:
article, data = self.__article_table.popitem()
self.__flush_article_to_disk(article, data)
except KeyError:
# Could fail if already deleted by purge_articles or load_data
logging.debug("Failed to flush item from cache, probably already deleted or written to disk")
while self.__article_list:
article = self.__article_list.pop(0)
data = self.__article_table.pop(article)
self.__flush_article_to_disk(article, data)
def purge_articles(self, articles):
""" Remove all saved articles, from memory and disk """
logging.debug("Purging %s articles from the cache/disk", len(articles))
for article in articles:
if article in self.__article_table:
try:
data = self.__article_table.pop(article)
self.free_reserved_space(len(data))
except KeyError:
# Could fail if already deleted by flush_articles or load_data
logging.debug("Failed to flush %s from cache, probably already deleted or written to disk", article)
elif article.art_id:
if article in self.__article_list:
self.__article_list.remove(article)
data = self.__article_table.pop(article)
self.free_reserved_space(len(data))
if article.art_id:
sabnzbd.remove_data(article.art_id, article.nzf.nzo.workpath)
@staticmethod
def __flush_article_to_disk(article, data):
def __flush_article_to_disk(self, article, data):
nzo = article.nzf.nzo
if nzo.is_gone():
# Don't store deleted jobs

View File

@@ -121,16 +121,20 @@ class Assembler(Thread):
if rar_encrypted:
if cfg.pause_on_pwrar() == 1:
logging.warning(
T(
'Paused job "%s" because of encrypted RAR file (if supplied, all passwords were tried)'
remove_warning_label(
T(
'WARNING: Paused job "%s" because of encrypted RAR file (if supplied, all passwords were tried)'
)
),
nzo.final_name,
)
nzo.pause()
else:
logging.warning(
T(
'Aborted job "%s" because of encrypted RAR file (if supplied, all passwords were tried)'
remove_warning_label(
T(
'WARNING: Aborted job "%s" because of encrypted RAR file (if supplied, all passwords were tried)'
)
),
nzo.final_name,
)
@@ -139,7 +143,9 @@ class Assembler(Thread):
if unwanted_file:
logging.warning(
T('In "%s" unwanted extension in RAR file. Unwanted file is %s '),
remove_warning_label(
T('WARNING: In "%s" unwanted extension in RAR file. Unwanted file is %s ')
),
nzo.final_name,
unwanted_file,
)
@@ -163,14 +169,14 @@ class Assembler(Thread):
filter_output, reason = nzo_filtered_by_rating(nzo)
if filter_output == 1:
logging.warning(
T('Paused job "%s" because of rating (%s)'),
remove_warning_label(T('WARNING: Paused job "%s" because of rating (%s)')),
nzo.final_name,
reason,
)
nzo.pause()
elif filter_output == 2:
logging.warning(
T('Aborted job "%s" because of rating (%s)'),
remove_warning_label(T('WARNING: Aborted job "%s" because of rating (%s)')),
nzo.final_name,
reason,
)
@@ -181,11 +187,10 @@ class Assembler(Thread):
sabnzbd.nzbqueue.NzbQueue.do.remove(nzo.nzo_id, add_to_history=False, cleanup=False)
PostProcessor.do.process(nzo)
@staticmethod
def assemble(nzf, file_done):
"""Assemble a NZF from its table of articles
1) Partial write: write what we have
2) Nothing written before: write all
def assemble(self, nzf, file_done):
""" Assemble a NZF from its table of articles
1) Partial write: write what we have
2) Nothing written before: write all
"""
# New hash-object needed?
if not nzf.md5:
@@ -227,8 +232,8 @@ class Assembler(Thread):
def file_has_articles(nzf):
"""Do a quick check to see if any articles are present for this file.
Destructive: only to be used to differentiate between unknown encoding and no articles.
""" Do a quick check to see if any articles are present for this file.
Destructive: only to be used to differentiate between unknown encoding and no articles.
"""
has = False
for article in nzf.decodetable:
@@ -412,3 +417,11 @@ def rating_filtered(rating, filename, abort):
if any(check_keyword(k) for k in keywords.split(",")):
return T("keywords")
return None
def remove_warning_label(msg):
""" Standardize errors by removing obsolete
"WARNING:" part in all languages """
if ":" in msg:
return msg.split(":")[1].strip()
return msg

View File

@@ -191,9 +191,12 @@ class BPSMeter:
self.update()
return res
def update(self, server=None, amount=0):
def update(self, server=None, amount=0, testtime=None):
""" Update counters for "server" with "amount" bytes """
t = time.time()
if testtime:
t = testtime
else:
t = time.time()
if t > self.end_of_day:
# current day passed. get new end of day
self.day_label = time.strftime("%Y-%m-%d")
@@ -321,9 +324,9 @@ class BPSMeter:
return self.bps_list[::refresh_rate]
def get_stable_speed(self, timespan=10):
"""See if there is a stable speed the last <timespan> seconds
None: indicates it can't determine yet
False: the speed was not stable during <timespan>
""" See if there is a stable speed the last <timespan> seconds
None: indicates it can't determine yet
False: the speed was not stable during <timespan>
"""
if len(self.bps_list) < timespan:
return None
@@ -347,8 +350,8 @@ class BPSMeter:
return None
def reset_quota(self, force=False):
"""Check if it's time to reset the quota, optionally resuming
Return True, when still paused
""" Check if it's time to reset the quota, optionally resuming
Return True, when still paused
"""
if force or (self.have_quota and time.time() > (self.q_time - 50)):
self.quota = self.left = cfg.quota_size.get_float()
@@ -461,8 +464,7 @@ class BPSMeter:
if action and not status:
self.resume()
@staticmethod
def resume():
def resume(self):
""" Resume downloading """
if cfg.quota_resume() and sabnzbd.downloader.Downloader.do and sabnzbd.downloader.Downloader.do.paused:
sabnzbd.downloader.Downloader.do.resume()

View File

@@ -34,7 +34,6 @@ from sabnzbd.config import (
create_api_key,
validate_notempty,
clean_nice_ionice_parameters,
validate_strip_right_slash,
)
from sabnzbd.constants import (
DEF_HOST,
@@ -45,7 +44,6 @@ from sabnzbd.constants import (
DEF_NZBBACK_DIR,
DEF_SCANRATE,
DEF_COMPLETE_DIR,
DEF_FOLDER_MAX,
)
##############################################################################
@@ -170,7 +168,6 @@ no_series_dupes = OptionNumber("misc", "no_series_dupes", 0)
series_propercheck = OptionBool("misc", "series_propercheck", True)
pause_on_pwrar = OptionNumber("misc", "pause_on_pwrar", 1)
ignore_samples = OptionBool("misc", "ignore_samples", False)
deobfuscate_final_filenames = OptionBool("misc", "deobfuscate_final_filenames", False)
auto_sort = OptionStr("misc", "auto_sort")
direct_unpack = OptionBool("misc", "direct_unpack", False)
direct_unpack_threads = OptionNumber("misc", "direct_unpack_threads", 3, 1)
@@ -257,16 +254,17 @@ enable_filejoin = OptionBool("misc", "enable_filejoin", True)
enable_tsjoin = OptionBool("misc", "enable_tsjoin", True)
overwrite_files = OptionBool("misc", "overwrite_files", False)
ignore_unrar_dates = OptionBool("misc", "ignore_unrar_dates", False)
ignore_wrong_unrar = OptionBool("misc", "ignore_wrong_unrar", False)
backup_for_duplicates = OptionBool("misc", "backup_for_duplicates", True)
empty_postproc = OptionBool("misc", "empty_postproc", False)
wait_for_dfolder = OptionBool("misc", "wait_for_dfolder", False)
warn_empty_nzb = OptionBool("misc", "warn_empty_nzb", True)
rss_filenames = OptionBool("misc", "rss_filenames", False)
api_logging = OptionBool("misc", "api_logging", True)
html_login = OptionBool("misc", "html_login", True)
osx_menu = OptionBool("misc", "osx_menu", True)
osx_speed = OptionBool("misc", "osx_speed", True)
warn_dupl_jobs = OptionBool("misc", "warn_dupl_jobs", True)
helpfull_warnings = OptionBool("misc", "helpfull_warnings", True)
keep_awake = OptionBool("misc", "keep_awake", True)
win_menu = OptionBool("misc", "win_menu", True)
allow_incomplete_nzb = OptionBool("misc", "allow_incomplete_nzb", False)
@@ -290,10 +288,9 @@ size_limit = OptionStr("misc", "size_limit", "0")
show_sysload = OptionNumber("misc", "show_sysload", 2, 0, 2)
history_limit = OptionNumber("misc", "history_limit", 10, 0)
wait_ext_drive = OptionNumber("misc", "wait_ext_drive", 5, 1, 60)
max_foldername_length = OptionNumber("misc", "max_foldername_length", DEF_FOLDER_MAX, 20, 65000)
marker_file = OptionStr("misc", "nomedia_marker", "")
ipv6_servers = OptionNumber("misc", "ipv6_servers", 1, 0, 2)
url_base = OptionStr("misc", "url_base", "/sabnzbd", validation=validate_strip_right_slash)
url_base = OptionStr("misc", "url_base", "/sabnzbd")
host_whitelist = OptionList("misc", "host_whitelist", validation=all_lowercase)
max_url_retries = OptionNumber("misc", "max_url_retries", 10, 1)
@@ -317,7 +314,6 @@ ncenter_enable = OptionBool("ncenter", "ncenter_enable", sabnzbd.DARWIN)
ncenter_cats = OptionList("ncenter", "ncenter_cats", ["*"])
ncenter_prio_startup = OptionBool("ncenter", "ncenter_prio_startup", True)
ncenter_prio_download = OptionBool("ncenter", "ncenter_prio_download", False)
ncenter_prio_pause_resume = OptionBool("ncenter", "ncenter_prio_pause_resume", False)
ncenter_prio_pp = OptionBool("ncenter", "ncenter_prio_pp", False)
ncenter_prio_complete = OptionBool("ncenter", "ncenter_prio_complete", True)
ncenter_prio_failed = OptionBool("ncenter", "ncenter_prio_failed", True)
@@ -333,7 +329,6 @@ acenter_enable = OptionBool("acenter", "acenter_enable", sabnzbd.WIN32)
acenter_cats = OptionList("acenter", "acenter_cats", ["*"])
acenter_prio_startup = OptionBool("acenter", "acenter_prio_startup", False)
acenter_prio_download = OptionBool("acenter", "acenter_prio_download", False)
acenter_prio_pause_resume = OptionBool("acenter", "acenter_prio_pause_resume", False)
acenter_prio_pp = OptionBool("acenter", "acenter_prio_pp", False)
acenter_prio_complete = OptionBool("acenter", "acenter_prio_complete", True)
acenter_prio_failed = OptionBool("acenter", "acenter_prio_failed", True)
@@ -349,7 +344,6 @@ ntfosd_enable = OptionBool("ntfosd", "ntfosd_enable", not sabnzbd.WIN32 and not
ntfosd_cats = OptionList("ntfosd", "ntfosd_cats", ["*"])
ntfosd_prio_startup = OptionBool("ntfosd", "ntfosd_prio_startup", True)
ntfosd_prio_download = OptionBool("ntfosd", "ntfosd_prio_download", False)
ntfosd_prio_pause_resume = OptionBool("ntfosd", "ntfosd_prio_pause_resume", False)
ntfosd_prio_pp = OptionBool("ntfosd", "ntfosd_prio_pp", False)
ntfosd_prio_complete = OptionBool("ntfosd", "ntfosd_prio_complete", True)
ntfosd_prio_failed = OptionBool("ntfosd", "ntfosd_prio_failed", True)
@@ -366,7 +360,6 @@ prowl_cats = OptionList("prowl", "prowl_cats", ["*"])
prowl_apikey = OptionStr("prowl", "prowl_apikey")
prowl_prio_startup = OptionNumber("prowl", "prowl_prio_startup", -3)
prowl_prio_download = OptionNumber("prowl", "prowl_prio_download", -3)
prowl_prio_pause_resume = OptionNumber("prowl", "prowl_prio_pause_resume", -3)
prowl_prio_pp = OptionNumber("prowl", "prowl_prio_pp", -3)
prowl_prio_complete = OptionNumber("prowl", "prowl_prio_complete", 0)
prowl_prio_failed = OptionNumber("prowl", "prowl_prio_failed", 1)
@@ -387,7 +380,6 @@ pushover_enable = OptionBool("pushover", "pushover_enable")
pushover_cats = OptionList("pushover", "pushover_cats", ["*"])
pushover_prio_startup = OptionNumber("pushover", "pushover_prio_startup", -3)
pushover_prio_download = OptionNumber("pushover", "pushover_prio_download", -2)
pushover_prio_pause_resume = OptionNumber("pushover", "pushover_prio_pause_resume", -2)
pushover_prio_pp = OptionNumber("pushover", "pushover_prio_pp", -3)
pushover_prio_complete = OptionNumber("pushover", "pushover_prio_complete", -1)
pushover_prio_failed = OptionNumber("pushover", "pushover_prio_failed", -1)
@@ -403,18 +395,17 @@ pushbullet_enable = OptionBool("pushbullet", "pushbullet_enable")
pushbullet_cats = OptionList("pushbullet", "pushbullet_cats", ["*"])
pushbullet_apikey = OptionStr("pushbullet", "pushbullet_apikey")
pushbullet_device = OptionStr("pushbullet", "pushbullet_device")
pushbullet_prio_startup = OptionBool("pushbullet", "pushbullet_prio_startup", False)
pushbullet_prio_download = OptionBool("pushbullet", "pushbullet_prio_download", False)
pushbullet_prio_pause_resume = OptionBool("pushbullet", "pushbullet_prio_pause_resume", False)
pushbullet_prio_pp = OptionBool("pushbullet", "pushbullet_prio_pp", False)
pushbullet_prio_complete = OptionBool("pushbullet", "pushbullet_prio_complete", True)
pushbullet_prio_failed = OptionBool("pushbullet", "pushbullet_prio_failed", True)
pushbullet_prio_disk_full = OptionBool("pushbullet", "pushbullet_prio_disk_full", True)
pushbullet_prio_new_login = OptionBool("pushbullet", "pushbullet_prio_new_login", False)
pushbullet_prio_warning = OptionBool("pushbullet", "pushbullet_prio_warning", False)
pushbullet_prio_error = OptionBool("pushbullet", "pushbullet_prio_error", False)
pushbullet_prio_queue_done = OptionBool("pushbullet", "pushbullet_prio_queue_done", False)
pushbullet_prio_other = OptionBool("pushbullet", "pushbullet_prio_other", False)
pushbullet_prio_startup = OptionNumber("pushbullet", "pushbullet_prio_startup", 0)
pushbullet_prio_download = OptionNumber("pushbullet", "pushbullet_prio_download", 0)
pushbullet_prio_pp = OptionNumber("pushbullet", "pushbullet_prio_pp", 0)
pushbullet_prio_complete = OptionNumber("pushbullet", "pushbullet_prio_complete", 1)
pushbullet_prio_failed = OptionNumber("pushbullet", "pushbullet_prio_failed", 1)
pushbullet_prio_disk_full = OptionNumber("pushbullet", "pushbullet_prio_disk_full", 1)
pushbullet_prio_new_login = OptionNumber("pushbullet", "pushbullet_prio_new_login", 0)
pushbullet_prio_warning = OptionNumber("pushbullet", "pushbullet_prio_warning", 0)
pushbullet_prio_error = OptionNumber("pushbullet", "pushbullet_prio_error", 0)
pushbullet_prio_queue_done = OptionNumber("pushbullet", "pushbullet_prio_queue_done", 0)
pushbullet_prio_other = OptionNumber("pushbullet", "pushbullet_prio_other", 0)
# [nscript]
nscript_enable = OptionBool("nscript", "nscript_enable")
@@ -423,7 +414,6 @@ nscript_script = OptionStr("nscript", "nscript_script")
nscript_parameters = OptionStr("nscript", "nscript_parameters")
nscript_prio_startup = OptionBool("nscript", "nscript_prio_startup", True)
nscript_prio_download = OptionBool("nscript", "nscript_prio_download", False)
nscript_prio_pause_resume = OptionBool("nscript", "nscript_prio_pause_resume", False)
nscript_prio_pp = OptionBool("nscript", "nscript_prio_pp", False)
nscript_prio_complete = OptionBool("nscript", "nscript_prio_complete", True)
nscript_prio_failed = OptionBool("nscript", "nscript_prio_failed", True)

View File

@@ -54,13 +54,13 @@ class Option:
""" Basic option class, basic fields """
def __init__(self, section, keyword, default_val=None, add=True, protect=False):
"""Basic option
`section` : single section or comma-separated list of sections
a list will be a hierarchy: "foo, bar" --> [foo][[bar]]
`keyword` : keyword in the (last) section
`default_val` : value returned when no value has been set
`callback` : procedure to call when value is successfully changed
`protect` : Do not allow setting via the API (specifically set_dict)
""" Basic option
`section` : single section or comma-separated list of sections
a list will be a hierarchy: "foo, bar" --> [foo][[bar]]
`keyword` : keyword in the (last) section
`default_val` : value returned when no value has been set
`callback` : procedure to call when value is successfully changed
`protect` : Do not allow setting via the API (specifically set_dict)
"""
self.__sections = section.split(",")
self.__keyword = keyword
@@ -230,10 +230,10 @@ class OptionDir(Option):
self.__root = root
def set(self, value, create=False):
"""Set new dir value, validate and create if needed
Return None when directory is accepted
Return error-string when not accepted, value will not be changed
'create' means try to create (but don't set permanent create flag)
""" Set new dir value, validate and create if needed
Return None when directory is accepted
Return error-string when not accepted, value will not be changed
'create' means try to create (but don't set permanent create flag)
"""
error = None
if value and (value != self.get() or create):
@@ -533,8 +533,8 @@ class OptionFilters(Option):
self.set(lst)
def update(self, pos, value):
"""Update filter 'pos' definition, value is a list
Append if 'pos' outside list
""" Update filter 'pos' definition, value is a list
Append if 'pos' outside list
"""
lst = self.get()
try:
@@ -637,8 +637,8 @@ class ConfigRSS:
def get_dconfig(section, keyword, nested=False):
"""Return a config values dictionary,
Single item or slices based on 'section', 'keyword'
""" Return a config values dictionary,
Single item or slices based on 'section', 'keyword'
"""
data = {}
if not section:
@@ -712,15 +712,15 @@ def delete(section, keyword):
##############################################################################
@synchronized(SAVE_CONFIG_LOCK)
def read_config(path):
"""Read the complete INI file and check its version number
if OK, pass values to config-database
""" Read the complete INI file and check its version number
if OK, pass values to config-database
"""
return _read_config(path)
def _read_config(path, try_backup=False):
"""Read the complete INI file and check its version number
if OK, pass values to config-database
""" Read the complete INI file and check its version number
if OK, pass values to config-database
"""
global CFG, database, modified
@@ -873,8 +873,8 @@ def save_config(force=False):
def define_servers():
"""Define servers listed in the Setup file
return a list of ConfigServer instances
""" Define servers listed in the Setup file
return a list of ConfigServer instances
"""
global CFG
try:
@@ -901,8 +901,8 @@ def get_servers():
def define_categories():
"""Define categories listed in the Setup file
return a list of ConfigCat instances
""" Define categories listed in the Setup file
return a list of ConfigCat instances
"""
global CFG, categories
try:
@@ -913,9 +913,9 @@ def define_categories():
def get_categories(cat=0):
"""Return link to categories section.
This section will always contain special category '*'
When 'cat' is given, a link to that category or to '*' is returned
""" Return link to categories section.
This section will always contain special category '*'
When 'cat' is given, a link to that category or to '*' is returned
"""
global database
if "categories" not in database:
@@ -942,8 +942,8 @@ def get_categories(cat=0):
def get_ordered_categories():
"""Return list-copy of categories section that's ordered
by user's ordering including Default-category
""" Return list-copy of categories section that's ordered
by user's ordering including Default-category
"""
database_cats = get_categories()
@@ -961,8 +961,8 @@ def get_ordered_categories():
def define_rss():
"""Define rss-feeds listed in the Setup file
return a list of ConfigRSS instances
""" Define rss-feeds listed in the Setup file
return a list of ConfigRSS instances
"""
global CFG
try:
@@ -1033,8 +1033,8 @@ def encode_password(pw):
def decode_password(pw, name):
"""Decode hexadecimal encoded password
but only decode when prefixed
""" Decode hexadecimal encoded password
but only decode when prefixed
"""
decPW = ""
if pw and pw.startswith(__PW_PREFIX):
@@ -1102,8 +1102,8 @@ def validate_no_unc(root, value, default):
def validate_safedir(root, value, default):
"""Allow only when queues are empty and no UNC
On Windows path should be small
""" Allow only when queues are empty and no UNC
On Windows path should be small
"""
if sabnzbd.WIN32 and value and len(real_path(root, value)) >= MAX_WIN_DFOLDER:
return T("Error: Path length should be below %s.") % MAX_WIN_DFOLDER, None
@@ -1121,16 +1121,9 @@ def validate_notempty(root, value, default):
return None, default
def validate_strip_right_slash(value):
"""Strips the right slash"""
if value:
return None, value.rstrip("/")
return None, value
def validate_single_tag(value):
"""Don't split single indexer tags like "TV > HD"
into ['TV', '>', 'HD']
""" Don't split single indexer tags like "TV > HD"
into ['TV', '>', 'HD']
"""
if len(value) == 3:
if value[1] == ">":

View File

@@ -37,10 +37,6 @@ QNFO = namedtuple("QNFO", "bytes bytes_left bytes_left_previous_page list q_size
ANFO = namedtuple("ANFO", "article_sum cache_size cache_limit")
# Leave some space for "_UNPACK_" which we append during post-proc
# Or, when extra ".1", ".2" etc. are added for identically named jobs
DEF_FOLDER_MAX = 256 - 10
GIGI = float(2 ** 30)
MEBI = float(2 ** 20)
KIBI = float(2 ** 10)
@@ -97,7 +93,7 @@ DIRECT_WRITE_TRIGGER = 35
MAX_ASSEMBLER_QUEUE = 5
REPAIR_PRIORITY = 3
FORCE_PRIORITY = 2
TOP_PRIORITY = 2
HIGH_PRIORITY = 1
NORMAL_PRIORITY = 0
LOW_PRIORITY = -1
@@ -106,14 +102,6 @@ PAUSED_PRIORITY = -2
DUP_PRIORITY = -3
STOP_PRIORITY = -4
INTERFACE_PRIORITIES = {
FORCE_PRIORITY: "Force",
REPAIR_PRIORITY: "Repair",
HIGH_PRIORITY: "High",
NORMAL_PRIORITY: "Normal",
LOW_PRIORITY: "Low",
}
STAGES = {"Source": 0, "Download": 1, "Servers": 2, "Repair": 3, "Filejoin": 4, "Unpack": 5, "Script": 6}
VALID_ARCHIVES = (".zip", ".rar", ".7z")
@@ -158,3 +146,18 @@ class Status:
VERIFYING = "Verifying" # PP: Job is being verified (by par2)
DELETED = "Deleted" # Q: Job has been deleted (and is almost gone)
PROP = "Propagating" # Q: Delayed download
NOTIFY_KEYS = (
"startup",
"download",
"pp",
"complete",
"failed",
"queue_done",
"disk_full",
"new_login",
"warning",
"error",
"other",
)

View File

@@ -34,7 +34,7 @@ from sabnzbd.bpsmeter import this_week, this_month
from sabnzbd.decorators import synchronized
from sabnzbd.encoding import ubtou, utob
from sabnzbd.misc import int_conv, caller_name, opts_to_pp
from sabnzbd.filesystem import remove_file, clip_path
from sabnzbd.filesystem import remove_file
DB_LOCK = threading.RLock()
@@ -61,10 +61,10 @@ def convert_search(search):
class HistoryDB:
"""Class to access the History database
Each class-instance will create an access channel that
can be used in one thread.
Each thread needs its own class-instance!
""" Class to access the History database
Each class-instance will create an access channel that
can be used in one thread.
Each thread needs its own class-instance!
"""
# These class attributes will be accessed directly because
@@ -275,9 +275,9 @@ class HistoryDB:
save=True,
)
def add_history_db(self, nzo, storage="", postproc_time=0, script_output="", script_line=""):
def add_history_db(self, nzo, storage="", path="", postproc_time=0, script_output="", script_line=""):
""" Add a new job entry to the database """
t = build_history_info(nzo, storage, postproc_time, script_output, script_line, series_info=True)
t = build_history_info(nzo, storage, path, postproc_time, script_output, script_line, series_info=True)
self.execute(
"""INSERT INTO history (completed, name, nzb_name, category, pp, script, report,
@@ -342,11 +342,11 @@ class HistoryDB:
if series and season and episode:
pattern = "%s/%s/%s" % (series, season, episode)
res = self.execute(
"""SELECT COUNT(*) FROM History WHERE series = ? AND STATUS != ?""", (pattern, Status.FAILED)
"select count(*) from History WHERE series = ? AND STATUS != ?", (pattern, Status.FAILED)
)
if res:
try:
total = self.c.fetchone().get("COUNT(*)")
total = self.c.fetchone().get("count(*)")
except AttributeError:
pass
return total > 0
@@ -354,20 +354,17 @@ class HistoryDB:
def have_name_or_md5sum(self, name, md5sum):
""" Check whether this name or md5sum is already in History """
total = 0
res = self.execute(
"""SELECT COUNT(*) FROM History WHERE ( LOWER(name) = LOWER(?) OR md5sum = ? ) AND STATUS != ?""",
(name, md5sum, Status.FAILED),
)
res = self.execute("select count(*) from History WHERE md5sum = ? AND STATUS != ?", (md5sum, Status.FAILED))
if res:
try:
total = self.c.fetchone().get("COUNT(*)")
total = self.c.fetchone().get("count(*)")
except AttributeError:
pass
return total > 0
def get_history_size(self):
"""Returns the total size of the history and
amounts downloaded in the last month and week
""" Returns the total size of the history and
amounts downloaded in the last month and week
"""
# Total Size of the history
total = 0
@@ -405,7 +402,7 @@ class HistoryDB:
""" Return decompressed log file """
data = ""
t = (nzo_id,)
if self.execute("""SELECT script_log FROM history WHERE nzo_id = ?""", t):
if self.execute("SELECT script_log FROM history WHERE nzo_id = ?", t):
try:
data = ubtou(zlib.decompress(self.c.fetchone().get("script_log")))
except:
@@ -416,7 +413,7 @@ class HistoryDB:
""" Return name of the job `nzo_id` """
t = (nzo_id,)
name = ""
if self.execute("""SELECT name FROM history WHERE nzo_id = ?""", t):
if self.execute("SELECT name FROM history WHERE nzo_id = ?", t):
try:
name = self.c.fetchone().get("name")
except AttributeError:
@@ -427,7 +424,7 @@ class HistoryDB:
""" Return the `incomplete` path of the job `nzo_id` if it is still there """
t = (nzo_id,)
path = ""
if self.execute("""SELECT path FROM history WHERE nzo_id = ?""", t):
if self.execute("SELECT path FROM history WHERE nzo_id = ?", t):
try:
path = self.c.fetchone().get("path")
except AttributeError:
@@ -439,7 +436,7 @@ class HistoryDB:
def get_other(self, nzo_id):
""" Return additional data for job `nzo_id` """
t = (nzo_id,)
if self.execute("""SELECT * FROM history WHERE nzo_id = ?""", t):
if self.execute("SELECT * FROM history WHERE nzo_id = ?", t):
try:
items = self.c.fetchone()
dtype = items.get("report")
@@ -464,9 +461,13 @@ def dict_factory(cursor, row):
_PP_LOOKUP = {0: "", 1: "R", 2: "U", 3: "D"}
def build_history_info(nzo, workdir_complete="", postproc_time=0, script_output="", script_line="", series_info=False):
def build_history_info(
nzo, storage="", downpath="", postproc_time=0, script_output="", script_line="", series_info=False
):
""" Collects all the information needed for the database """
completed = int(time.time())
if not downpath:
downpath = nzo.downpath
pp = _PP_LOOKUP.get(opts_to_pp(*nzo.repair_opts), "X")
if script_output:
@@ -506,8 +507,8 @@ def build_history_info(nzo, workdir_complete="", postproc_time=0, script_output=
nzo.url,
nzo.status,
nzo.nzo_id,
clip_path(workdir_complete),
clip_path(nzo.downpath),
storage,
downpath,
script_output,
script_line,
download_time,
@@ -525,8 +526,8 @@ def build_history_info(nzo, workdir_complete="", postproc_time=0, script_output=
def unpack_history_info(item):
"""Expands the single line stage_log from the DB
into a python dictionary for use in the history display
""" Expands the single line stage_log from the DB
into a python dictionary for use in the history display
"""
# Stage Name is separated by ::: stage lines by ; and stages by \r\n
lst = item["stage_log"]
@@ -537,7 +538,7 @@ def unpack_history_info(item):
logging.error(T("Invalid stage logging in history for %s") + " (\\r\\n)", item["name"])
logging.debug("Lines: %s", lst)
lines = []
lst = [None for _ in STAGES]
lst = [None for x in STAGES]
for line in lines:
stage = {}
try:

View File

@@ -1,165 +0,0 @@
#!/usr/bin/python3 -OO
# Copyright 2007-2020 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 large, not-excluded
files to the job-name in the queue if the filename looks obfuscated
Based on work by P1nGu1n
"""
import hashlib
import logging
import math
import os
import re
from sabnzbd.filesystem import get_unique_filename, globber_full, renamer, get_ext
from sabnzbd.par2file import is_parfile, parse_par2_file
# Files to exclude and minimal file size for renaming
EXCLUDED_FILE_EXTS = (".vob", ".rar", ".par2")
MIN_FILE_SIZE = 10 * 1024 * 1024
def decode_par2(parfile):
""" Parse a par2 file and rename files listed in the par2 to their real name """
# Check if really a par2 file
if not is_parfile(parfile):
logging.info("Par2 file %s was not really a par2 file")
return False
# Parse the par2 file
md5of16k = {}
parse_par2_file(parfile, md5of16k)
# Parse all files in the folder
dirname = os.path.dirname(parfile)
result = False
for fn in os.listdir(dirname):
filepath = os.path.join(dirname, fn)
# Only check files
if os.path.isfile(filepath):
with open(filepath, "rb") as fileToMatch:
first16k_data = fileToMatch.read(16384)
# Check if we have this hash
file_md5of16k = hashlib.md5(first16k_data).digest()
if file_md5of16k in md5of16k:
new_path = os.path.join(dirname, md5of16k[file_md5of16k])
# Make sure it's a unique name
renamer(filepath, get_unique_filename(new_path))
result = True
return result
def is_probably_obfuscated(myinputfilename):
"""Returns boolean if filename is likely obfuscated. Default: True
myinputfilename can be a plain file name, or a full path"""
# Find filebasename
path, filename = os.path.split(myinputfilename)
filebasename, fileextension = os.path.splitext(filename)
# ...blabla.H.264/b082fa0beaa644d3aa01045d5b8d0b36.mkv is certainly obfuscated
if re.findall("^[a-f0-9]{32}$", filebasename):
logging.debug("Obfuscated: 32 hex digit")
# exactly 32 hex digits, so:
return True
# these are signals for the obfuscation versus non-obfuscation
decimals = sum(1 for c in filebasename if c.isnumeric())
upperchars = sum(1 for c in filebasename if c.isupper())
lowerchars = sum(1 for c in filebasename if c.islower())
spacesdots = sum(1 for c in filebasename if c == " " or c == ".")
# Example: "Great Distro"
if upperchars >= 2 and lowerchars >= 2 and spacesdots >= 1:
logging.debug("Not obfuscated: upperchars >= 2 and lowerchars >= 2 and spacesdots >= 1")
return False
# Example: "this is a download"
if spacesdots >= 3:
logging.debug("Not obfuscated: spacesdots >= 3")
return False
# Example: "Beast 2020"
if (upperchars + lowerchars >= 4) and decimals > 3 and spacesdots >= 1:
logging.debug("Not obfuscated: (upperchars + lowerchars >= 4) and decimals > 3 and spacesdots > 1")
return False
# Example: "Catullus", starts with a capital, and most letters are lower case
if filebasename[0].isupper() and lowerchars > 2 and upperchars / lowerchars <= 0.25:
logging.debug("Not obfuscated: starts with a capital, and most letters are lower case")
return False
# If we get here, no trigger for a clear name was found, so let's default to obfuscated
logging.debug("Obfuscated (default)")
return True # default not obfuscated
def deobfuscate(workingdirectory, usefulname):
""" In workingdirectory, check all filenames, and if wanted, rename """
# Search for par2 files
par2_files = globber_full(workingdirectory, "*.par2")
# Found any par2 files we can use?
run_renamer = True
if not par2_files:
logging.debug("No par2 files found to process, running renamer.")
else:
# Run par2 from SABnzbd on them
for par2_file in par2_files:
# Analyse data and analyse result
logging.debug("Deobfuscate par2: handling %s", par2_file)
if decode_par2(par2_file):
logging.debug("Deobfuscate par2 repair/verify finished.")
run_renamer = False
else:
logging.debug("Deobfuscate par2 repair/verify did not find anything to rename.")
# No par2 files? Then we try to rename qualifying files to the job-name
if run_renamer:
logging.debug("Trying to see if there are qualifying files to be deobfuscated")
for root, dirnames, filenames in os.walk(workingdirectory):
for filename in filenames:
logging.debug("Deobfuscate inspecting %s", filename)
full_path = os.path.join(root, filename)
file_size = os.path.getsize(full_path)
# Do we need to rename this file?
# Criteria: big, not-excluded extension, obfuscated
if (
file_size > MIN_FILE_SIZE
and get_ext(filename) not in EXCLUDED_FILE_EXTS
and is_probably_obfuscated(filename) # this as last test to avoid unnecessary analysis
):
# OK, rename
new_name = get_unique_filename(
"%s%s" % (os.path.join(workingdirectory, usefulname), get_ext(filename))
)
logging.info("Deobfuscate renaming %s to %s", filename, new_name)
# Rename and make sure the new filename is unique
renamer(full_path, new_name)
else:
logging.info("No qualifying files found to deobfuscate")

View File

@@ -23,15 +23,17 @@ import os
import re
import time
import threading
import subprocess
import logging
from subprocess import Popen
import sabnzbd
import sabnzbd.cfg as cfg
from sabnzbd.misc import int_conv, format_time_string, build_and_run_command
from sabnzbd.misc import int_conv, format_time_string
from sabnzbd.filesystem import clip_path, long_path, remove_all, real_path, remove_file
from sabnzbd.encoding import platform_btou
from sabnzbd.decorators import synchronized
from sabnzbd.newsunpack import EXTRACTFROM_RE, EXTRACTED_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
@@ -75,8 +77,9 @@ class DirectUnpacker(threading.Thread):
pass
def reset_active(self):
# make sure the process and file handlers are closed nicely:
# make sure the process and filehandles are closed nicely:
try:
# Creation was done via "self.active_instance = Popen()", so:
if self.active_instance:
self.active_instance.stdout.close()
self.active_instance.stdin.close()
@@ -84,7 +87,6 @@ class DirectUnpacker(threading.Thread):
except:
logging.debug("Exception in reset_active()", exc_info=True)
pass
self.active_instance = None
self.cur_setname = None
self.cur_volume = 0
@@ -323,9 +325,9 @@ class DirectUnpacker(threading.Thread):
self.killed = True
def have_next_volume(self):
"""Check if next volume of set is available, start
from the end of the list where latest completed files are
Make sure that files are 100% written to disk by checking md5sum
""" Check if next volume of set is available, start
from the end of the list where latest completed files are
Make sure that files are 100% written to disk by checking md5sum
"""
for nzf_search in reversed(self.nzo.finished_files):
if nzf_search.setname == self.cur_setname and nzf_search.vol == (self.cur_volume + 1) and nzf_search.md5sum:
@@ -333,8 +335,8 @@ class DirectUnpacker(threading.Thread):
return False
def wait_for_next_volume(self):
"""Wait for the correct volume to appear
But stop if it was killed or the NZB is done
""" Wait for the correct volume to appear
But stop if it was killed or the NZB is done
"""
while not self.have_next_volume() and not self.killed and self.nzo.files:
with self.next_file_lock:
@@ -409,10 +411,19 @@ class DirectUnpacker(threading.Thread):
# Let's start from the first one!
self.cur_volume = 1
stup, need_shell, command, creationflags = build_command(command, flatten_command=True)
logging.debug("Running unrar for DirectUnpack %s", command)
# Need to disable buffer to have direct feedback
self.active_instance = build_and_run_command(command, flatten_command=True, bufsize=0)
self.active_instance = Popen(
command,
shell=False,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
bufsize=0,
)
# Add to runners
ACTIVE_UNPACKERS.append(self)
@@ -492,8 +503,8 @@ class DirectUnpacker(threading.Thread):
def analyze_rar_filename(filename):
"""Extract volume number and setname from rar-filenames
Both ".part01.rar" and ".r01"
""" Extract volume number and setname from rar-filenames
Both ".part01.rar" and ".r01"
"""
m = RAR_NR.search(filename)
if m:
@@ -516,8 +527,8 @@ def abort_all():
def test_disk_performance():
"""Test the incomplete-dir performance and enable
Direct Unpack if good enough (> 40MB/s)
""" Test the incomplete-dir performance and enable
Direct Unpack if good enough (> 40MB/s)
"""
if diskspeedmeasure(sabnzbd.cfg.download_dir.get_path()) > 40:
cfg.direct_unpack.set(True)

View File

@@ -59,10 +59,10 @@ def clean_file_list(inp_list, folder, files):
class DirScanner(threading.Thread):
"""Thread that periodically scans a given directory and picks up any
valid NZB, NZB.GZ ZIP-with-only-NZB and even NZB.GZ named as .NZB
Candidates which turned out wrong, will be remembered and skipped in
subsequent scans, unless changed.
""" Thread that periodically scans a given directory and picks up any
valid NZB, NZB.GZ ZIP-with-only-NZB and even NZB.GZ named as .NZB
Candidates which turned out wrong, will be remembered and skipped in
subsequent scans, unless changed.
"""
do = None # Access to instance of DirScanner

View File

@@ -110,12 +110,12 @@ class Server:
@property
def hostip(self):
"""In case a server still has active connections, we use the same IP again
If new connection then based on value of load_balancing() and self.info:
0 - return the first entry, so all threads use the same IP
1 - and self.info has more than 1 entry (read: IP address): Return a random entry from the possible IPs
2 - and self.info has more than 1 entry (read: IP address): Return the quickest IP based on the happyeyeballs algorithm
In case of problems: return the host name itself
""" In case a server still has active connections, we use the same IP again
If new connection then based on value of load_balancing() and self.info:
0 - return the first entry, so all threads use the same IP
1 - and self.info has more than 1 entry (read: IP address): Return a random entry from the possible IPs
2 - and self.info has more than 1 entry (read: IP address): Return the quickest IP based on the happyeyeballs algorithm
In case of problems: return the host name itself
"""
# Check if already a successful ongoing connection
if self.busy_threads and self.busy_threads[0].nntp:
@@ -213,9 +213,9 @@ class Downloader(Thread):
Downloader.do = self
def init_server(self, oldserver, newserver):
"""Setup or re-setup single server
When oldserver is defined and in use, delay startup.
Note that the server names are "host:port" strings!
""" Setup or re-setup single server
When oldserver is defined and in use, delay startup.
Note that the server names are "host:port" strings!
"""
create = False
@@ -286,7 +286,7 @@ class Downloader(Thread):
# Do not notify when SABnzbd is still starting
if self.paused and sabnzbd.WEB_DIR:
logging.info("Resuming")
notifier.send_notification("SABnzbd", T("Resuming"), "pause_resume")
notifier.send_notification("SABnzbd", T("Resuming"), "download")
self.paused = False
@NzbQueueLocker
@@ -295,7 +295,7 @@ class Downloader(Thread):
if not self.paused:
self.paused = True
logging.info("Pausing")
notifier.send_notification("SABnzbd", T("Paused"), "pause_resume")
notifier.send_notification("SABnzbd", T("Paused"), "download")
if self.is_paused():
BPSMeter.do.reset()
if cfg.autodisconnect():
@@ -314,9 +314,9 @@ class Downloader(Thread):
self.force_disconnect = True
def limit_speed(self, value):
"""Set the actual download speed in Bytes/sec
When 'value' ends with a '%' sign or is within 1-100, it is interpreted as a pecentage of the maximum bandwidth
When no '%' is found, it is interpreted as an absolute speed (including KMGT notation).
""" Set the actual download speed in Bytes/sec
When 'value' ends with a '%' sign or is within 1-100, it is interpreted as a pecentage of the maximum bandwidth
When no '%' is found, it is interpreted as an absolute speed (including KMGT notation).
"""
if value:
mx = cfg.bandwidth_max.get_int()
@@ -326,7 +326,7 @@ class Downloader(Thread):
if mx:
self.bandwidth_limit = mx * self.bandwidth_perc / 100
else:
logging.warning_helpful(T("You must set a maximum bandwidth before you can set a bandwidth limit"))
logging.warning(T("You must set a maximum bandwidth before you can set a bandwidth limit"))
else:
self.bandwidth_limit = from_units(value)
if mx:
@@ -363,8 +363,8 @@ class Downloader(Thread):
return True
def highest_server(self, me):
"""Return True when this server has the highest priority of the active ones
0 is the highest priority
""" Return True when this server has the highest priority of the active ones
0 is the highest priority
"""
for server in self.servers:
if server is not me and server.active and server.priority < me.priority:
@@ -406,8 +406,8 @@ class Downloader(Thread):
sabnzbd.nzbqueue.NzbQueue.do.reset_all_try_lists()
def decode(self, article, raw_data):
"""Decode article and check the status of
the decoder and the assembler
""" Decode article and check the status of
the decoder and the assembler
"""
# Handle broken articles directly
if not raw_data:
@@ -928,8 +928,8 @@ class Downloader(Thread):
self.init_server(server.id, server.id)
def update_server(self, oldserver, newserver):
"""Update the server and make sure we trigger
the update in the loop to do housekeeping"""
""" Update the server and make sure we trigger
the update in the loop to do housekeeping """
self.init_server(oldserver, newserver)
self.wakeup()

View File

@@ -42,9 +42,9 @@ def ubtou(str_in):
def platform_btou(str_in):
"""Return Unicode, if not already Unicode, decode with locale encoding.
NOTE: Used for POpen because universal_newlines/text parameter doesn't
always work! We cannot use encoding-parameter because it's Python 3.7+
""" Return Unicode, if not already Unicode, decode with locale encoding.
NOTE: Used for POpen because universal_newlines/text parameter doesn't
always work! We cannot use encoding-parameter because it's Python 3.7+
"""
if isinstance(str_in, bytes):
try:
@@ -56,10 +56,10 @@ def platform_btou(str_in):
def correct_unknown_encoding(str_or_bytes_in):
"""Files created on Windows but unpacked/repaired on
linux can result in invalid filenames. Try to fix this
encoding by going to bytes and then back to unicode again.
Last resort we use chardet package
""" Files created on Windows but unpacked/repaired on
linux can result in invalid filenames. Try to fix this
encoding by going to bytes and then back to unicode again.
Last resort we use chardet package
"""
# If already string, back to bytes
if not isinstance(str_or_bytes_in, bytes):

View File

@@ -93,9 +93,9 @@ _DEVICES = (
def replace_win_devices(name):
"""Remove reserved Windows device names from a name.
aux.txt ==> _aux.txt
txt.aux ==> txt.aux
""" Remove reserved Windows device names from a name.
aux.txt ==> _aux.txt
txt.aux ==> txt.aux
"""
if name:
lname = name.lower()
@@ -112,8 +112,8 @@ def replace_win_devices(name):
def has_win_device(p):
"""Return True if filename part contains forbidden name
Before and after sanitizing
""" Return True if filename part contains forbidden name
Before and after sanitizing
"""
p = os.path.split(p)[1].lower()
for dev in _DEVICES:
@@ -129,8 +129,8 @@ CH_LEGAL_WIN = "++{}!@#'+-"
def sanitize_filename(name):
"""Return filename with illegal chars converted to legal ones
and with the par2 extension always in lowercase
""" Return filename with illegal chars converted to legal ones
and with the par2 extension always in lowercase
"""
if not name:
return name
@@ -168,8 +168,8 @@ def sanitize_filename(name):
def sanitize_foldername(name):
"""Return foldername with dodgy chars converted to safe ones
Remove any leading and trailing dot and space characters
""" Return foldername with dodgy chars converted to safe ones
Remove any leading and trailing dot and space characters
"""
if not name:
return name
@@ -197,9 +197,6 @@ def sanitize_foldername(name):
if sabnzbd.WIN32 or sabnzbd.cfg.sanitize_safe():
name = replace_win_devices(name)
if len(name) >= sabnzbd.cfg.max_foldername_length():
name = name[: sabnzbd.cfg.max_foldername_length()]
# And finally, make sure it doesn't end in a dot
if name != "." and name != "..":
name = name.rstrip(".")
@@ -236,7 +233,8 @@ def sanitize_and_trim_path(path):
def sanitize_files_in_folder(folder):
"""Sanitize each file in the folder, return list of new names"""
""" Sanitize each file in the folder, return list of new names
"""
lst = []
for root, _, files in os.walk(folder):
for file_ in files:
@@ -253,16 +251,16 @@ def sanitize_files_in_folder(folder):
def is_obfuscated_filename(filename):
"""Check if this file has an extension, if not, it's
probably obfuscated and we don't use it
""" Check if this file has an extension, if not, it's
probably obfuscated and we don't use it
"""
return len(get_ext(filename)) < 2
def real_path(loc, path):
"""When 'path' is relative, return normalized join of 'loc' and 'path'
When 'path' is absolute, return normalized path
A path starting with ~ will be located in the user's Home folder
""" When 'path' is relative, return normalized join of 'loc' and 'path'
When 'path' is absolute, return normalized path
A path starting with ~ will be located in the user's Home folder
"""
# The Windows part is a bit convoluted because
# C: and C:\ are 2 different things
@@ -274,9 +272,6 @@ def real_path(loc, path):
if not sabnzbd.WIN32 and path.startswith("~/"):
path = path.replace("~", os.environ.get("HOME", sabnzbd.DIR_HOME), 1)
if sabnzbd.WIN32:
# The Windows-functions work differently on long-path
# So we bring it back to normal and make it long-path at the end
loc = clip_path(loc)
path = path.replace("/", "\\")
if len(path) > 1 and path[0].isalpha() and path[1] == ":":
if len(path) == 2 or path[2] != "\\":
@@ -297,12 +292,12 @@ def real_path(loc, path):
def create_real_path(name, loc, path, umask=False, writable=True):
"""When 'path' is relative, create join of 'loc' and 'path'
When 'path' is absolute, create normalized path
'name' is used for logging.
Optional 'umask' will be applied.
'writable' means that an existing folder should be writable
Returns ('success', 'full path', 'error_msg')
""" When 'path' is relative, create join of 'loc' and 'path'
When 'path' is absolute, create normalized path
'name' is used for logging.
Optional 'umask' will be applied.
'writable' means that an existing folder should be writable
Returns ('success', 'full path', 'error_msg')
"""
if path:
my_dir = real_path(loc, path)
@@ -325,9 +320,9 @@ def create_real_path(name, loc, path, umask=False, writable=True):
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
return 2 if B is a subfolder of A
""" Return 0 if A and B have nothing in common
return 1 if A and B are actually the same path
return 2 if B is a subfolder of A
"""
if sabnzbd.WIN32 or sabnzbd.DARWIN:
a = clip_path(a.lower())
@@ -354,7 +349,7 @@ def same_file(a, b):
def is_archive(path):
"""Check if file in path is an ZIP, RAR or 7z file
""" Check if file in path is an ZIP, RAR or 7z file
:param path: path to file
:return: (zf, status, expected_extension)
status: -1==Error/Retry, 0==OK, 1==Ignore
@@ -388,8 +383,8 @@ def is_archive(path):
def check_mount(path):
"""Return False if volume isn't mounted on Linux or OSX
Retry 6 times with an interval of 1 sec.
""" Return False if volume isn't mounted on Linux or OSX
Retry 6 times with an interval of 1 sec.
"""
if sabnzbd.DARWIN:
m = re.search(r"^(/Volumes/[^/]+)", path, re.I)
@@ -408,8 +403,8 @@ def check_mount(path):
def safe_fnmatch(f, pattern):
"""fnmatch will fail if the pattern contains any of it's
key characters, like [, ] or !.
""" fnmatch will fail if the pattern contains any of it's
key characters, like [, ] or !.
"""
try:
return fnmatch.fnmatch(f, pattern)
@@ -445,9 +440,9 @@ def trim_win_path(path):
def fix_unix_encoding(folder):
"""Fix bad name encoding for Unix systems
This happens for example when files are created
on Windows but unpacked/repaired on linux
""" Fix bad name encoding for Unix systems
This happens for example when files are created
on Windows but unpacked/repaired on linux
"""
if not sabnzbd.WIN32 and not sabnzbd.DARWIN:
for root, dirs, files in os.walk(folder):
@@ -476,8 +471,8 @@ def make_script_path(script):
def get_admin_path(name, future):
"""Return news-style full path to job-admin folder of names job
or else the old cache path
""" Return news-style full path to job-admin folder of names job
or else the old cache path
"""
if future:
return os.path.join(sabnzbd.cfg.admin_dir.get_path(), FUTURE_Q_FOLDER)
@@ -528,20 +523,6 @@ def set_permissions(path, recursive=True):
set_chmod(path, umask_file, report)
def userxbit(filename):
"""Returns boolean if the x-bit for user is set on the given file.
This is a workaround: os.access(filename, os.X_OK) does not work
on certain mounted file systems. Does not work at all on Windows.
"""
# rwx rwx rwx
# 876 543 210 # we want bit 6 from the right, counting from 0
userxbit = 1 << 6 # bit 6
rwxbits = os.stat(filename)[0] # the first element of os.stat() is "mode"
# do logical AND, check if it is not 0:
xbitset = (rwxbits & userxbit) > 0
return xbitset
def clip_path(path):
r""" Remove \\?\ or \\?\UNC\ prefix from Windows path """
if sabnzbd.WIN32 and path and "?" in path:
@@ -569,17 +550,14 @@ DIR_LOCK = threading.RLock()
@synchronized(DIR_LOCK)
def create_all_dirs(path, apply_umask=False):
"""Create all required path elements and set umask on all
The umask argument is ignored on Windows
Return path if elements could be made or exists
""" Create all required path elements and set umask on all
The umask argument is ignored on Windows
Return path if elements could be made or exists
"""
try:
logging.info("Creating directories: %s", path)
if sabnzbd.WIN32:
# On Windows it can fail on UNC-paths in long-path notation
# https://bugs.python.org/issue41705
if not os.path.exists(path):
os.makedirs(path)
os.makedirs(path, exist_ok=True)
else:
# We need to build the directory recursively so we can
# apply permissions to only the newly created folders
@@ -627,8 +605,8 @@ def get_unique_path(dirpath, n=0, create_dir=True):
@synchronized(DIR_LOCK)
def get_unique_filename(path):
"""Check if path is unique.
If not, add number like: "/path/name.NUM.ext".
""" Check if path is unique.
If not, add number like: "/path/name.NUM.ext".
"""
num = 1
new_path, fname = os.path.split(path)
@@ -656,8 +634,8 @@ def listdir_full(input_dir, recursive=True):
@synchronized(DIR_LOCK)
def move_to_path(path, new_path):
"""Move a file to a new path, optionally give unique filename
Return (ok, new_path)
""" Move a file to a new path, optionally give unique filename
Return (ok, new_path)
"""
ok = True
overwrite = sabnzbd.cfg.overwrite_files()
@@ -768,11 +746,11 @@ def renamer(old, new):
logging.debug('Renaming "%s" to "%s"', old, new)
if sabnzbd.WIN32:
retries = 10
retries = 15
while retries > 0:
try:
# First we try 3 times with os.rename
if retries > 7:
if retries > 12:
os.rename(old, new)
else:
# Now we try the back-up method
@@ -785,12 +763,11 @@ def renamer(old, new):
# Error 17 - Rename can't move to different disk
# Jump to moving with shutil.move
retries -= 3
elif err.winerror == 32 or err.winerror == 5:
elif err.winerror == 32:
# Error 32 - Used by another process
# Error 5 - Access is denied (virus scanners)
logging.debug("File busy, retrying rename %s to %s", old, new)
retries -= 1
# Wait for the other process
# Wait for the other process to finish
time.sleep(2)
else:
raise

View File

@@ -76,9 +76,9 @@ def localipv4():
def publicipv4():
"""Because of dual IPv4/IPv6 clients, finding the
public ipv4 needs special attention, meaning forcing
IPv4 connections, and not allowing IPv6 connections
""" Because of dual IPv4/IPv6 clients, finding the
public ipv4 needs special attention, meaning forcing
IPv4 connections, and not allowing IPv6 connections
"""
public_ipv4 = None
try:

View File

@@ -141,12 +141,12 @@ def secured_expose(wrap_func=None, check_configlock=False, check_api_key=False):
def check_access(access_type=4):
"""Check if external address is allowed given access_type:
1=nzb
2=api
3=full_api
4=webui
5=webui with login for external
""" Check if external address is allowed given access_type:
1=nzb
2=api
3=full_api
4=webui
5=webui with login for external
"""
referrer = cherrypy.request.remote.ip
@@ -162,9 +162,9 @@ def check_access(access_type=4):
def check_hostname():
"""Check if hostname is allowed, to mitigate DNS-rebinding attack.
Similar to CVE-2019-5702, we need to add protection even
if only allowed to be accessed via localhost.
""" Check if hostname is allowed, to mitigate DNS-rebinding attack.
Similar to CVE-2019-5702, we need to add protection even
if only allowed to be accessed via localhost.
"""
# If login is enabled, no API-key can be deducted
if cfg.username() and cfg.password():
@@ -202,10 +202,10 @@ COOKIE_SECRET = str(randint(1000, 100000) * os.getpid())
def set_login_cookie(remove=False, remember_me=False):
"""We try to set a cookie as unique as possible
to the current user. Based on it's IP and the
current process ID of the SAB instance and a random
number, so cookies cannot be re-used
""" We try to set a cookie as unique as possible
to the current user. Based on it's IP and the
current process ID of the SAB instance and a random
number, so cookies cannot be re-used
"""
salt = randint(1, 1000)
cookie_str = utob(str(salt) + cherrypy.request.remote.ip + COOKIE_SECRET)
@@ -268,18 +268,15 @@ def set_auth(conf):
}
)
conf.update(
{
"/api": {"tools.auth_basic.on": False},
"%s/api" % cfg.url_base(): {"tools.auth_basic.on": False},
}
{"/api": {"tools.auth_basic.on": False}, "%s/api" % cfg.url_base(): {"tools.auth_basic.on": False},}
)
else:
conf.update({"tools.auth_basic.on": False})
def check_apikey(kwargs):
"""Check API-key or NZB-key
Return None when OK, otherwise an error message
""" Check API-key or NZB-key
Return None when OK, otherwise an error message
"""
mode = kwargs.get("mode", "")
name = kwargs.get("name", "")
@@ -922,8 +919,8 @@ class QueuePage:
@secured_expose(check_api_key=True)
def change_queue_complete_action(self, **kwargs):
"""Action or script to be performed once the queue has been completed
Scripts are prefixed with 'script_'
""" Action or script to be performed once the queue has been completed
Scripts are prefixed with 'script_'
"""
action = kwargs.get("action")
sabnzbd.change_queue_complete_action(action)
@@ -1233,7 +1230,6 @@ SWITCH_LIST = (
"pre_script",
"pause_on_pwrar",
"sfv_check",
"deobfuscate_final_filenames",
"folder_rename",
"load_balancing",
"quota_size",
@@ -1329,11 +1325,11 @@ SPECIAL_BOOL_LIST = (
"start_paused",
"no_penalties",
"fast_fail",
"ignore_wrong_unrar",
"overwrite_files",
"enable_par_cleanup",
"queue_complete_pers",
"api_warnings",
"helpfull_warnings",
"ampm",
"enable_unrar",
"enable_unzip",
@@ -1352,6 +1348,7 @@ SPECIAL_BOOL_LIST = (
"html_login",
"wait_for_dfolder",
"max_art_opt",
"warn_empty_nzb",
"enable_bonjour",
"warn_dupl_jobs",
"replace_illegal",
@@ -1368,7 +1365,6 @@ SPECIAL_VALUE_LIST = (
"max_url_retries",
"req_completion_rate",
"wait_ext_drive",
"max_foldername_length",
"show_sysload",
"url_base",
"direct_unpack_threads",
@@ -1540,7 +1536,7 @@ class ConfigGeneral:
cfg.bandwidth_perc.set(bandwidth_perc)
bandwidth_perc = cfg.bandwidth_perc()
if bandwidth_perc and not bandwidth_max:
logging.warning_helpful(T("You must set a maximum bandwidth before you can set a bandwidth limit"))
logging.warning(T("You must set a maximum bandwidth before you can set a bandwidth limit"))
config.save_config()
@@ -1825,8 +1821,8 @@ class ConfigRss:
@secured_expose(check_api_key=True, check_configlock=True)
def upd_rss_feed(self, **kwargs):
"""Update Feed level attributes,
legacy version: ignores 'enable' parameter
""" Update Feed level attributes,
legacy version: ignores 'enable' parameter
"""
if kwargs.get("enable") is not None:
del kwargs["enable"]
@@ -2703,8 +2699,6 @@ LIST_NCENTER = (
"ncenter_cats",
"ncenter_prio_startup",
"ncenter_prio_download",
"ncenter_prio_pause_resume",
"ncenter_prio_pp",
"ncenter_prio_pp",
"ncenter_prio_complete",
"ncenter_prio_failed",
@@ -2720,7 +2714,6 @@ LIST_ACENTER = (
"acenter_cats",
"acenter_prio_startup",
"acenter_prio_download",
"acenter_prio_pause_resume",
"acenter_prio_pp",
"acenter_prio_complete",
"acenter_prio_failed",
@@ -2736,7 +2729,6 @@ LIST_NTFOSD = (
"ntfosd_cats",
"ntfosd_prio_startup",
"ntfosd_prio_download",
"ntfosd_prio_pause_resume",
"ntfosd_prio_pp",
"ntfosd_prio_complete",
"ntfosd_prio_failed",
@@ -2753,7 +2745,6 @@ LIST_PROWL = (
"prowl_apikey",
"prowl_prio_startup",
"prowl_prio_download",
"prowl_prio_pause_resume",
"prowl_prio_pp",
"prowl_prio_complete",
"prowl_prio_failed",
@@ -2772,7 +2763,6 @@ LIST_PUSHOVER = (
"pushover_device",
"pushover_prio_startup",
"pushover_prio_download",
"pushover_prio_pause_resume",
"pushover_prio_pp",
"pushover_prio_complete",
"pushover_prio_failed",
@@ -2792,7 +2782,6 @@ LIST_PUSHBULLET = (
"pushbullet_device",
"pushbullet_prio_startup",
"pushbullet_prio_download",
"pushbullet_prio_pause_resume",
"pushbullet_prio_pp",
"pushbullet_prio_complete",
"pushbullet_prio_failed",
@@ -2810,7 +2799,6 @@ LIST_NSCRIPT = (
"nscript_parameters",
"nscript_prio_startup",
"nscript_prio_download",
"nscript_prio_pause_resume",
"nscript_prio_pp",
"nscript_prio_complete",
"nscript_prio_failed",
@@ -2854,7 +2842,8 @@ class ConfigNotify:
conf[kw] = config.get_config("ntfosd", kw)()
for kw in LIST_NSCRIPT:
conf[kw] = config.get_config("nscript", kw)()
conf["notify_types"] = sabnzbd.notifier.NOTIFICATION
conf["notify_keys"] = sabnzbd.constants.NOTIFY_KEYS
conf["notify_texts"] = sabnzbd.notifier.NOTIFICATION
template = Template(
file=os.path.join(sabnzbd.WEB_DIR_CONFIG, "config_notify.tmpl"),

View File

@@ -62,10 +62,10 @@ def set_language(language=None):
def list_languages():
"""Return sorted list of (lang-code, lang-string) pairs,
representing the available languages.
When any language file is found, the default tuple ('en', 'English')
will be included. Otherwise an empty list is returned.
""" Return sorted list of (lang-code, lang-string) pairs,
representing the available languages.
When any language file is found, the default tuple ('en', 'English')
will be included. Otherwise an empty list is returned.
"""
# Find all the MO files.
lst = []

View File

@@ -36,7 +36,6 @@ from sabnzbd.constants import DEFAULT_PRIORITY, MEBI, DEF_ARTICLE_CACHE_DEFAULT,
import sabnzbd.config as config
import sabnzbd.cfg as cfg
from sabnzbd.encoding import ubtou, platform_btou
from sabnzbd.filesystem import get_ext, userxbit
TAB_UNITS = ("", "K", "M", "G", "T", "P")
RE_UNITS = re.compile(r"(\d+\.*\d*)\s*([KMGTP]{0,1})", re.I)
@@ -47,21 +46,6 @@ RE_IP6 = re.compile(r"inet6\s+(addr:\s*){0,1}([0-9a-f:]+)", re.I)
# Check if strings are defined for AM and PM
HAVE_AMPM = bool(time.strftime("%p", time.localtime()))
if sabnzbd.WIN32:
try:
import win32process
import win32con
# Define scheduling priorities
WIN_SCHED_PRIOS = {
1: win32process.IDLE_PRIORITY_CLASS,
2: win32process.BELOW_NORMAL_PRIORITY_CLASS,
3: win32process.NORMAL_PRIORITY_CLASS,
4: win32process.ABOVE_NORMAL_PRIORITY_CLASS,
}
except ImportError:
pass
def time_format(fmt):
""" Return time-format string adjusted for 12/24 hour clock setting """
@@ -72,9 +56,9 @@ def time_format(fmt):
def calc_age(date, trans=False):
"""Calculate the age difference between now and date.
Value is returned as either days, hours, or minutes.
When 'trans' is True, time symbols will be translated.
""" Calculate the age difference between now and date.
Value is returned as either days, hours, or minutes.
When 'trans' is True, time symbols will be translated.
"""
if trans:
d = T("d") # : Single letter abbreviation of day
@@ -147,9 +131,9 @@ def name_to_cat(fname, cat=None):
def cat_to_opts(cat, pp=None, script=None, priority=None):
"""Derive options from category, if options not already defined.
Specified options have priority over category-options.
If no valid category is given, special category '*' will supply default values
""" Derive options from category, if options not already defined.
Specified options have priority over category-options.
If no valid category is given, special category '*' will supply default values
"""
def_cat = config.get_categories("*")
cat = safe_lower(cat)
@@ -231,10 +215,10 @@ def wildcard_to_re(text):
def cat_convert(cat):
"""Convert indexer's category/group-name to user categories.
If no match found, but indexer-cat equals user-cat, then return user-cat
If no match found, but the indexer-cat starts with the user-cat, return user-cat
If no match found, return None
""" Convert indexer's category/group-name to user categories.
If no match found, but indexer-cat equals user-cat, then return user-cat
If no match found, but the indexer-cat starts with the user-cat, return user-cat
If no match found, return None
"""
if cat and cat.lower() != "none":
cats = config.get_ordered_categories()
@@ -271,8 +255,8 @@ def cat_convert(cat):
def windows_variant():
"""Determine Windows variant
Return vista_plus, x64
""" Determine Windows variant
Return vista_plus, x64
"""
from win32api import GetVersionEx
from win32con import VER_PLATFORM_WIN32_NT
@@ -376,26 +360,26 @@ def convert_version(text):
def check_latest_version():
"""Do an online check for the latest version
""" Do an online check for the latest version
Perform an online version check
Syntax of online version file:
<current-final-release>
<url-of-current-final-release>
<latest-alpha/beta-or-rc>
<url-of-latest-alpha/beta/rc-release>
The latter two lines are only present when an alpha/beta/rc is available.
Formula for the version numbers (line 1 and 3).
<major>.<minor>.<bugfix>[rc|beta|alpha]<cand>
Perform an online version check
Syntax of online version file:
<current-final-release>
<url-of-current-final-release>
<latest-alpha/beta-or-rc>
<url-of-latest-alpha/beta/rc-release>
The latter two lines are only present when an alpha/beta/rc is available.
Formula for the version numbers (line 1 and 3).
<major>.<minor>.<bugfix>[rc|beta|alpha]<cand>
The <cand> value for a final version is assumned to be 99.
The <cand> value for the beta/rc version is 1..98, with RC getting
a boost of 80 and Beta of 40.
This is done to signal alpha/beta/rc users of availability of the final
version (which is implicitly 99).
People will only be informed to upgrade to a higher alpha/beta/rc version, if
they are already using an alpha/beta/rc.
RC's are valued higher than Beta's, which are valued higher than Alpha's.
The <cand> value for a final version is assumned to be 99.
The <cand> value for the beta/rc version is 1..98, with RC getting
a boost of 80 and Beta of 40.
This is done to signal alpha/beta/rc users of availability of the final
version (which is implicitly 99).
People will only be informed to upgrade to a higher alpha/beta/rc version, if
they are already using an alpha/beta/rc.
RC's are valued higher than Beta's, which are valued higher than Alpha's.
"""
if not cfg.version_check():
@@ -447,7 +431,7 @@ def check_latest_version():
url = url_beta
if testver and current < latest:
# This is a test version, but user hasn't seen the
# This is a test version, but user has't seen the
# "Final" of this one yet, so show the Final
sabnzbd.NEW_VERSION = (latest_label, url)
elif current < latest:
@@ -475,7 +459,7 @@ def upload_file_to_sabnzbd(url, fp):
url = "%s&ma_username=%s&ma_password=%s" % (url, username, password)
get_from_url(url)
except:
logging.error(T("Failed to upload file: %s"), fp)
logging.error("Failed to upload file: %s", fp)
logging.info("Traceback: ", exc_info=True)
@@ -483,7 +467,7 @@ def from_units(val):
""" Convert K/M/G/T/P notation to float """
val = str(val).strip().upper()
if val == "-1":
return float(val)
return val
m = RE_UNITS.search(val)
if m:
if m.group(2):
@@ -504,8 +488,8 @@ def from_units(val):
def to_units(val, postfix=""):
"""Convert number to K/M/G/T/P notation
Show single decimal for M and higher
""" Convert number to K/M/G/T/P notation
Show single decimal for M and higher
"""
dec_limit = 1
if val < 0:
@@ -534,8 +518,8 @@ def to_units(val, 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
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:
@@ -544,7 +528,7 @@ def caller_name(skip=2):
parentframe = sys._getframe(skip)
function_name = parentframe.f_code.co_name
# Module name is not available in the binaries, we can use the filename instead
# Modulename not available in the binaries, we can use the filename instead
if hasattr(sys, "frozen"):
module_name = inspect.getfile(parentframe)
else:
@@ -592,9 +576,9 @@ def split_host(srv):
def get_cache_limit():
"""Depending on OS, calculate cache limits.
In ArticleCache it will make sure we stay
within system limits for 32/64 bit
""" Depending on OS, calculate cache limits.
In ArticleCache it will make sure we stay
within system limits for 32/64 bit
"""
# Calculate, if possible
try:
@@ -657,7 +641,7 @@ def get_windows_memory():
def get_darwin_memory():
""" Use system-call to extract total memory on macOS """
system_output = run_command(["sysctl", "hw.memsize"])
system_output = sabnzbd.newsunpack.run_simple(["sysctl", "hw.memsize"])
return float(system_output.split()[1])
@@ -808,13 +792,13 @@ def get_all_passwords(nzo):
# Check size
if len(pws) > 30:
logging.warning_helpful(
logging.warning(
T(
"Your password file contains more than 30 passwords, testing all these passwords takes a lot of time. Try to only list useful passwords."
)
)
except:
logging.warning(T("Failed to read the password file %s"), pw_file)
logging.warning("Failed to read the passwords file %s", pw_file)
if nzo.password:
# If an explicit password was set, add a retry without password, just in case.
@@ -880,7 +864,17 @@ def ip_extract():
for item in info:
ips.append(item[4][0])
else:
output = run_command(program)
p = subprocess.Popen(
program,
shell=False,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=None,
creationflags=0,
)
output = platform_btou(p.stdout.read())
p.wait()
for line in output.split("\n"):
m = RE_IP4.search(line)
if not (m and m.group(2)):
@@ -891,8 +885,8 @@ def ip_extract():
def get_base_url(url):
"""Return only the true root domain for the favicon, so api.oznzb.com -> oznzb.com
But also api.althub.co.za -> althub.co.za
""" Return only the true root domain for the favicon, so api.oznzb.com -> oznzb.com
But also api.althub.co.za -> althub.co.za
"""
url_host = urllib.parse.urlparse(url).hostname
if url_host:
@@ -925,72 +919,3 @@ def nntp_to_msg(text):
else:
lines = text.split(b"\r\n")
return ubtou(lines[0])
def build_and_run_command(command, flatten_command=False, **kwargs):
"""Builds and then runs command with nessecary flags and optional
IONice and Nice commands. Optional Popen arguments can be supplied.
On Windows we need to run our own list2cmdline for Unrar.
Returns the Popen-instance.
"""
# command[0] should be set, and thus not None
if not command[0]:
logging.error(T("[%s] The command in build_command is undefined."), caller_name())
raise IOError
if not sabnzbd.WIN32:
if command[0].endswith(".py"):
with open(command[0], "r") as script_file:
if not userxbit(command[0]):
# Inform user that Python scripts need x-bit and then stop
logging.error(T('Python script "%s" does not have execute (+x) permission set'), command[0])
raise IOError
elif script_file.read(2) != "#!":
# No shebang (#!) defined, add default python
command.insert(0, "python")
if sabnzbd.newsunpack.IONICE_COMMAND and cfg.ionice():
ionice = cfg.ionice().split()
command = ionice + command
command.insert(0, sabnzbd.newsunpack.IONICE_COMMAND)
if sabnzbd.newsunpack.NICE_COMMAND and cfg.nice():
nice = cfg.nice().split()
command = nice + command
command.insert(0, sabnzbd.newsunpack.NICE_COMMAND)
creationflags = 0
startupinfo = None
else:
# For Windows we always need to add python interpreter
if command[0].endswith(".py"):
command.insert(0, "python.exe")
if flatten_command:
command = sabnzbd.newsunpack.list2cmdline(command)
# On some Windows platforms we need to supress a quick pop-up of the command window
startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags = win32process.STARTF_USESHOWWINDOW
startupinfo.wShowWindow = win32con.SW_HIDE
creationflags = WIN_SCHED_PRIOS[cfg.win_process_prio()]
# Set the basic Popen arguments
popen_kwargs = {
"stdin": subprocess.PIPE,
"stdout": subprocess.PIPE,
"stderr": subprocess.STDOUT,
"startupinfo": startupinfo,
"creationflags": creationflags,
}
# Update with the supplied ones
popen_kwargs.update(kwargs)
# Run the command
logging.info("[%s] Running external command: %s", caller_name(), command)
logging.debug("Popen arguments: %s", popen_kwargs)
return subprocess.Popen(command, **popen_kwargs)
def run_command(cmd):
""" Run simple external command and return output as a string. """
with build_and_run_command(cmd) as p:
txt = platform_btou(p.stdout.read())
p.wait()
return txt

View File

@@ -28,20 +28,12 @@ import time
import zlib
import shutil
import functools
from subprocess import Popen
import sabnzbd
from sabnzbd.encoding import platform_btou, correct_unknown_encoding, ubtou
import sabnzbd.utils.rarfile as rarfile
from sabnzbd.misc import (
format_time_string,
find_on_path,
int_conv,
get_all_passwords,
calc_age,
cmp,
run_command,
build_and_run_command,
)
from sabnzbd.misc import format_time_string, find_on_path, int_conv, get_all_passwords, calc_age, cmp, caller_name
from sabnzbd.filesystem import (
make_script_path,
real_path,
@@ -60,6 +52,23 @@ from sabnzbd.sorting import SeriesSorter
import sabnzbd.cfg as cfg
from sabnzbd.constants import Status
if sabnzbd.WIN32:
try:
import win32api
import win32con
import win32process
# Define scheduling priorities
WIN_SCHED_PRIOS = {
1: win32process.IDLE_PRIORITY_CLASS,
2: win32process.BELOW_NORMAL_PRIORITY_CLASS,
3: win32process.NORMAL_PRIORITY_CLASS,
4: win32process.ABOVE_NORMAL_PRIORITY_CLASS,
}
except ImportError:
pass
# 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?\d)$", re.I)
RAR_RE_V3 = re.compile(r"\.(?P<ext>part\d*)$", re.I)
@@ -115,14 +124,7 @@ def find_programs(curdir):
if not sabnzbd.newsunpack.PAR2_COMMAND:
sabnzbd.newsunpack.PAR2_COMMAND = find_on_path("par2")
if not sabnzbd.newsunpack.RAR_COMMAND:
sabnzbd.newsunpack.RAR_COMMAND = find_on_path(
(
"unrar",
"rar",
"unrar3",
"rar3",
)
)
sabnzbd.newsunpack.RAR_COMMAND = find_on_path(("unrar", "rar", "unrar3", "rar3",))
sabnzbd.newsunpack.NICE_COMMAND = find_on_path("nice")
sabnzbd.newsunpack.IONICE_COMMAND = find_on_path("ionice")
if not sabnzbd.newsunpack.ZIP_COMMAND:
@@ -198,7 +200,31 @@ def external_processing(extern_proc, nzo, complete_dir, nicename, status):
}
try:
p = build_and_run_command(command, env=create_env(nzo, extra_env_fields))
stup, need_shell, command, creationflags = build_command(command)
env = create_env(nzo, extra_env_fields)
logging.info(
"Running external script %s(%s, %s, %s, %s, %s, %s, %s, %s)",
extern_proc,
complete_dir,
nzo.filename,
nicename,
"",
nzo.cat,
nzo.group,
status,
failure_url,
)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
env=env,
creationflags=creationflags,
)
# Follow the output, so we can abort it
proc = p.stdout
@@ -232,6 +258,33 @@ def external_processing(extern_proc, nzo, complete_dir, nicename, status):
return output, ret
def external_script(script, p1, p2, p3=None, p4=None):
""" Run a user script with two parameters, return console output and exit value """
command = [script, p1, p2, p3, p4]
try:
stup, need_shell, command, creationflags = build_command(command)
env = create_env()
logging.info("Running user script %s(%s, %s)", script, p1, p2)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
env=env,
creationflags=creationflags,
)
except:
logging.debug("Failed script %s, Traceback: ", script, exc_info=True)
return "Cannot run script %s\r\n" % script, -1
output = platform_btou(p.stdout.read())
ret = p.wait()
return output, ret
def unpack_magic(nzo, workdir, workdir_complete, dele, one_folder, joinables, zips, rars, sevens, ts, depth=0):
""" Do a recursive unpack from all archives in 'workdir' to 'workdir_complete' """
if depth > 5:
@@ -381,8 +434,8 @@ def get_seq_number(name):
def file_join(nzo, workdir, workdir_complete, delete, joinables):
"""Join and joinable files in 'workdir' to 'workdir_complete' and
when successful, delete originals
""" Join and joinable files in 'workdir' to 'workdir_complete' and
when successful, delete originals
"""
newfiles = []
bufsize = 24 * 1024 * 1024
@@ -472,9 +525,9 @@ def file_join(nzo, workdir, workdir_complete, delete, joinables):
# (Un)Rar Functions
##############################################################################
def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
"""Unpack multiple sets 'rars' of RAR files from 'workdir' to 'workdir_complete.
When 'delete' is set, originals will be deleted.
When 'one_folder' is set, all files will be in a single folder
""" Unpack multiple sets 'rars' of RAR files from 'workdir' to 'workdir_complete.
When 'delete' is set, originals will be deleted.
When 'one_folder' is set, all files will be in a single folder
"""
newfiles = extracted_files = []
rar_sets = {}
@@ -595,9 +648,9 @@ def rar_unpack(nzo, workdir, workdir_complete, delete, one_folder, rars):
def rar_extract(rarfile_path, numrars, one_folder, nzo, setname, extraction_path):
"""Unpack single rar set 'rarfile' to 'extraction_path',
with password tries
Return fail==0(ok)/fail==1(error)/fail==2(wrong password), new_files, rars
""" Unpack single rar set 'rarfile' to 'extraction_path',
with password tries
Return fail==0(ok)/fail==1(error)/fail==2(wrong password), new_files, rars
"""
fail = 0
new_files = None
@@ -622,8 +675,8 @@ def rar_extract(rarfile_path, numrars, one_folder, nzo, setname, extraction_path
def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction_path, password):
"""Unpack single rar set 'rarfile_path' to 'extraction_path'
Return fail==0(ok)/fail==1(error)/fail==2(wrong password)/fail==3(crc-error), new_files, rars
""" Unpack single rar set 'rarfile_path' to 'extraction_path'
Return fail==0(ok)/fail==1(error)/fail==2(wrong password)/fail==3(crc-error), new_files, rars
"""
start = time.time()
@@ -689,9 +742,20 @@ 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, 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))
p = build_and_run_command(command, flatten_command=True)
logging.debug("Running unrar %s", command)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
proc = p.stdout
if p.stdin:
@@ -857,8 +921,8 @@ def rar_extract_core(rarfile_path, numrars, one_folder, nzo, setname, extraction
# (Un)Zip Functions
##############################################################################
def unzip(nzo, workdir, workdir_complete, delete, one_folder, zips):
"""Unpack multiple sets 'zips' of ZIP files from 'workdir' to 'workdir_complete.
When 'delete' is ste, originals will be deleted.
""" Unpack multiple sets 'zips' of ZIP files from 'workdir' to 'workdir_complete.
When 'delete' is ste, originals will be deleted.
"""
try:
@@ -924,10 +988,23 @@ def ZIP_Extract(zipfile, extraction_path, one_folder):
if one_folder or cfg.flat_unpack():
command.insert(3, "-j") # Unpack without folders
p = build_and_run_command(command)
stup, need_shell, command, creationflags = build_command(command)
logging.debug("Starting unzip: %s", command)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
output = platform_btou(p.stdout.read())
ret = p.wait()
logging.debug("unzip output: \n%s", output)
ret = p.wait()
return ret
@@ -935,8 +1012,8 @@ def ZIP_Extract(zipfile, extraction_path, one_folder):
# 7Zip Functions
##############################################################################
def unseven(nzo, workdir, workdir_complete, delete, one_folder, sevens):
"""Unpack multiple sets '7z' of 7Zip files from 'workdir' to 'workdir_complete.
When 'delete' is set, originals will be deleted.
""" Unpack multiple sets '7z' of 7Zip files from 'workdir' to 'workdir_complete.
When 'delete' is set, originals will be deleted.
"""
i = 0
unseven_failed = False
@@ -983,8 +1060,8 @@ def unseven(nzo, workdir, workdir_complete, delete, one_folder, sevens):
def seven_extract(nzo, sevenset, extensions, extraction_path, one_folder, delete):
"""Unpack single set 'sevenset' to 'extraction_path', with password tries
Return fail==0(ok)/fail==1(error)/fail==2(wrong password), new_files, sevens
""" Unpack single set 'sevenset' to 'extraction_path', with password tries
Return fail==0(ok)/fail==1(error)/fail==2(wrong password), new_files, sevens
"""
# Before we start, make sure the 7z binary SEVEN_COMMAND is defined
if not SEVEN_COMMAND:
@@ -1016,8 +1093,8 @@ def seven_extract(nzo, sevenset, extensions, extraction_path, one_folder, delete
def seven_extract_core(sevenset, extensions, extraction_path, one_folder, delete, password):
"""Unpack single 7Z set 'sevenset' to 'extraction_path'
Return fail==0(ok)/fail==1(error)/fail==2(wrong password), new_files, message
""" Unpack single 7Z set 'sevenset' to 'extraction_path'
Return fail==0(ok)/fail==1(error)/fail==2(wrong password), new_files, message
"""
if one_folder:
method = "e" # Unpack without folders
@@ -1050,7 +1127,19 @@ def seven_extract_core(sevenset, extensions, extraction_path, one_folder, delete
orig_dir_content = listdir_full(extraction_path)
command = [SEVEN_COMMAND, method, "-y", overwrite, parm, case, password, "-o%s" % extraction_path, name]
p = build_and_run_command(command)
stup, need_shell, command, creationflags = build_command(command)
logging.debug("Starting 7za: %s", command)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
output = platform_btou(p.stdout.read())
logging.debug("7za output: %s", output)
@@ -1246,7 +1335,7 @@ def PAR_Verify(parfile, nzo, setname, joinables, single=False):
# Or the one that complains about basepath
# Only if we're not doing multicore
if not sabnzbd.WIN32 and not sabnzbd.DARWIN:
par2text = run_command([command[0], "-h"])
par2text = run_simple([command[0], "-h"])
if "No data skipping" in par2text:
logging.info("Detected par2cmdline version that skips blocks, adding -N parameter")
command.insert(2, "-N")
@@ -1255,13 +1344,24 @@ def PAR_Verify(parfile, nzo, setname, joinables, single=False):
command.insert(2, "-B")
command.insert(3, parfolder)
stup, need_shell, command, creationflags = build_command(command)
# par2multicore wants to see \\.\ paths on Windows
# See: https://github.com/sabnzbd/sabnzbd/pull/771
if sabnzbd.WIN32:
command = [clip_path(x) if x.startswith("\\\\?\\") else x for x in command]
# Run the external command
p = build_and_run_command(command)
logging.info("Starting par2: %s", command)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
proc = p.stdout
if p.stdin:
@@ -1571,14 +1671,26 @@ def MultiPar_Verify(parfile, nzo, setname, joinables, single=False):
wildcard = setname + "*"
command.append(os.path.join(parfolder, wildcard))
# Run MultiPar
p = build_and_run_command(command)
stup, need_shell, command, creationflags = build_command(command)
logging.info("Starting MultiPar: %s", command)
lines = []
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
proc = p.stdout
if p.stdin:
p.stdin.close()
# Set up our variables
lines = []
datafiles = []
renames = {}
reconstructed = []
@@ -1916,9 +2028,9 @@ def MultiPar_Verify(parfile, nzo, setname, joinables, single=False):
def create_env(nzo=None, extra_env_fields={}):
"""Modify the environment for pp-scripts with extra information
OSX: Return copy of environment without PYTHONPATH and PYTHONHOME
other: return None
""" Modify the environment for pp-scripts with extra information
OSX: Return copy of environment without PYTHONPATH and PYTHONHOME
other: return None
"""
env = os.environ.copy()
@@ -1975,9 +2087,76 @@ def create_env(nzo=None, extra_env_fields={}):
return env
def userxbit(filename):
# Returns boolean if the x-bit for user is set on the given file
# This is a workaround: os.access(filename, os.X_OK) does not work on certain mounted file systems
# Does not work on Windows, but it is not called on Windows
# rwx rwx rwx
# 876 543 210 # we want bit 6 from the right, counting from 0
userxbit = 1 << 6 # bit 6
rwxbits = os.stat(filename)[0] # the first element of os.stat() is "mode"
# do logical AND, check if it is not 0:
xbitset = (rwxbits & userxbit) > 0
return xbitset
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
"""
# command[0] should be set, and thus not None
if not command[0]:
logging.error(T("[%s] The command in build_command is undefined."), caller_name())
raise IOError
if not sabnzbd.WIN32:
if command[0].endswith(".py"):
with open(command[0], "r") as script_file:
if not userxbit(command[0]):
# Inform user that Python scripts need x-bit and then stop
logging.error(T('Python script "%s" does not have execute (+x) permission set'), command[0])
raise IOError
elif script_file.read(2) != "#!":
# No shebang (#!) defined, add default python
command.insert(0, "python")
if IONICE_COMMAND and cfg.ionice().strip():
lst = cfg.ionice().split()
lst.reverse()
for arg in lst:
command.insert(0, arg)
command.insert(0, IONICE_COMMAND)
if NICE_COMMAND and cfg.nice().strip():
lst = cfg.nice().split()
lst.reverse()
for arg in lst:
command.insert(0, arg)
command.insert(0, NICE_COMMAND)
need_shell = False
stup = None
creationflags = 0
else:
# For Windows we always need to add python interpreter
if command[0].endswith(".py"):
command.insert(0, "python")
need_shell = os.path.splitext(command[0])[1].lower() not in (".exe", ".com")
stup = subprocess.STARTUPINFO()
stup.dwFlags = win32process.STARTF_USESHOWWINDOW
stup.wShowWindow = win32con.SW_HIDE
creationflags = WIN_SCHED_PRIOS[cfg.win_process_prio()]
if need_shell or flatten_command:
command = list2cmdline(command)
return stup, need_shell, command, creationflags
def rar_volumelist(rarfile_path, password, known_volumes):
"""Extract volumes that are part of this rarset
and merge them with existing list, removing duplicates
""" Extract volumes that are part of this rarset
and merge them with existing list, removing duplicates
"""
# UnRar is required to read some RAR files
# RarFile can fail in special cases
@@ -2021,9 +2200,9 @@ def rar_sort(a, b):
def build_filelists(workdir, workdir_complete=None, check_both=False, check_rar=True):
"""Build filelists, if workdir_complete has files, ignore workdir.
Optionally scan both directories.
Optionally test content to establish RAR-ness
""" Build filelists, if workdir_complete has files, ignore workdir.
Optionally scan both directories.
Optionally test content to establish RAR-ness
"""
sevens, joinables, zips, rars, ts, filelist = ([], [], [], [], [], [])
@@ -2130,15 +2309,15 @@ def quick_check_set(set, nzo):
def unrar_check(rar):
"""Return version number of unrar, where "5.01" returns 501
Also return whether an original version is found
(version, original)
""" Return version number of unrar, where "5.01" returns 501
Also return whether an original version is found
(version, original)
"""
version = 0
original = ""
if rar:
try:
version = run_command([rar])
version = run_simple(rar)
except:
return version, original
original = "Alexander Roshal" in version
@@ -2153,7 +2332,7 @@ def unrar_check(rar):
def par2_mt_check(par2_path):
""" Detect if we have multicore par2 variants """
try:
par2_version = run_command([par2_path, "-h"])
par2_version = run_simple([par2_path, "-h"])
# Look for a threads option
if "-t<" in par2_version:
return True
@@ -2330,8 +2509,8 @@ def analyse_show(name):
def pre_queue(nzo, pp, cat):
"""Run pre-queue script (if any) and process results.
pp and cat are supplied seperate since they can change.
""" Run pre-queue script (if any) and process results.
pp and cat are supplied seperate since they can change.
"""
def fix(p):
@@ -2367,7 +2546,19 @@ def pre_queue(nzo, pp, cat):
}
try:
p = build_and_run_command(command, env=create_env(nzo, extra_env_fields))
stup, need_shell, command, creationflags = build_command(command)
env = create_env(nzo, extra_env_fields)
logging.info("Running pre-queue script %s", command)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
env=env,
creationflags=creationflags,
)
except:
logging.debug("Failed script %s, Traceback: ", script_path, exc_info=True)
return values
@@ -2420,8 +2611,20 @@ class SevenZip:
names = []
# Future extension: use '-sccUTF-8' to get names in UTF8 encoding
command = [SEVEN_COMMAND, "l", "-p", "-y", "-slt", self.path]
output = run_command(command)
stup, need_shell, command, creationflags = build_command(command)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
startupinfo=stup,
creationflags=creationflags,
)
output = platform_btou(p.stdout.read())
_ = p.wait()
re_path = re.compile("^Path = (.+)")
for line in output.split("\n"):
m = re_path.search(line)
@@ -2435,12 +2638,30 @@ class SevenZip:
def read(self, name):
""" Read named file from 7Zip and return data """
command = [SEVEN_COMMAND, "e", "-p", "-y", "-so", self.path, name]
stup, need_shell, command, creationflags = build_command(command)
# Ignore diagnostic output, otherwise it will be appended to content
p = build_and_run_command(command, stderr=subprocess.DEVNULL)
p = Popen(
command,
shell=need_shell,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.DEVNULL,
startupinfo=stup,
creationflags=creationflags,
)
output = platform_btou(p.stdout.read())
p.wait()
_ = p.wait()
return output
def close(self):
""" Close file """
pass
def run_simple(cmd):
""" Run simple external command and return output """
with Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) as p:
txt = platform_btou(p.stdout.read())
p.wait()
return txt

View File

@@ -30,10 +30,8 @@ from threading import Thread
import sabnzbd
import sabnzbd.cfg
from sabnzbd.encoding import platform_btou
from sabnzbd.filesystem import make_script_path
from sabnzbd.misc import build_and_run_command
from sabnzbd.newsunpack import create_env
from sabnzbd.newsunpack import external_script
if sabnzbd.FOUNDATION:
import Foundation
@@ -58,7 +56,6 @@ except:
TT = lambda x: x
NOTIFICATION = {
"startup": TT("Startup/Shutdown"), #: Notification
"pause_resume": TT("Pause") + "/" + TT("Resume"), #: Notification
"download": TT("Added NZB"), #: Notification
"pp": TT("Post-processing started"), # : Notification
"complete": TT("Job finished"), #: Notification
@@ -102,8 +99,8 @@ def get_prio(gtype, section):
def check_cat(section, job_cat, keyword=None):
"""Check if `job_cat` is enabled in `section`.
* = All, if no other categories selected.
""" Check if `job_cat` is enabled in `section`.
* = All, if no other categories selected.
"""
if not job_cat:
return True
@@ -119,7 +116,6 @@ def check_cat(section, job_cat, keyword=None):
def send_notification(title, msg, gtype, job_cat=None):
""" Send Notification message """
logging.info("Sending notification: %s - %s (type=%s, job_cat=%s)", title, msg, gtype, job_cat)
# Notification Center
if sabnzbd.DARWIN and sabnzbd.cfg.ncenter_enable():
if check_classes(gtype, "ncenter") and check_cat("ncenter", job_cat):
@@ -174,7 +170,7 @@ def send_notify_osd(title, message):
# Wrap notify2.init to prevent blocking in dbus
# when there's no active notification daemon
try:
_NTFOSD = _NTFOSD or notify2.init("SABnzbd")
_NTFOSD = _NTFOSD or notify2.init("icon-summary-body")
except:
_NTFOSD = False
@@ -349,11 +345,10 @@ def send_nscript(title, msg, gtype, force=False, test=None):
""" Run user's notification script """
if test:
script = test.get("nscript_script")
nscript_parameters = test.get("nscript_parameters")
parameters = test.get("nscript_parameters")
else:
script = sabnzbd.cfg.nscript_script()
nscript_parameters = sabnzbd.cfg.nscript_parameters()
nscript_parameters = nscript_parameters.split()
parameters = sabnzbd.cfg.nscript_parameters()
if not script:
return T("Cannot send, missing required data")
title = "SABnzbd: " + T(NOTIFICATION.get(gtype, "other"))
@@ -361,20 +356,12 @@ def send_nscript(title, msg, gtype, force=False, test=None):
if force or check_classes(gtype, "nscript"):
script_path = make_script_path(script)
if script_path:
ret = -1
output = None
try:
p = build_and_run_command([script_path, gtype, title, msg] + nscript_parameters, env=create_env())
output = platform_btou(p.stdout.read())
ret = p.wait()
except:
logging.info("Failed script %s, Traceback: ", script, exc_info=True)
output, ret = external_script(script_path, gtype, title, msg, parameters)
if ret:
logging.error(T('Script returned exit code %s and output "%s"'), ret, output)
return T('Script returned exit code %s and output "%s"') % (ret, output)
else:
logging.info("Successfully executed notification script %s", script_path)
logging.info("Successfully executed notification script " + script_path)
else:
return T('Notification script "%s" does not exist') % script_path
return ""

View File

@@ -169,10 +169,10 @@ def process_nzb_archive_file(
password=None,
nzo_id=None,
):
"""Analyse ZIP file and create job(s).
Accepts ZIP files with ONLY nzb/nfo/folder files in it.
returns (status, nzo_ids)
status: -1==Error, 0==OK, 1==Ignore
""" Analyse ZIP file and create job(s).
Accepts ZIP files with ONLY nzb/nfo/folder files in it.
returns (status, nzo_ids)
status: -1==Error, 0==OK, 1==Ignore
"""
nzo_ids = []
if catdir is None:
@@ -270,10 +270,10 @@ def process_single_nzb(
password=None,
nzo_id=None,
):
"""Analyze file and create a job from it
Supports NZB, NZB.BZ2, NZB.GZ and GZ.NZB-in-disguise
returns (status, nzo_ids)
status: -2==Error/retry, -1==Error, 0==OK
""" Analyze file and create a job from it
Supports NZB, NZB.BZ2, NZB.GZ and GZ.NZB-in-disguise
returns (status, nzo_ids)
status: -2==Error/retry, -1==Error, 0==OK
"""
nzo_ids = []
if catdir is None:

View File

@@ -42,7 +42,7 @@ from sabnzbd.constants import (
LOW_PRIORITY,
NORMAL_PRIORITY,
HIGH_PRIORITY,
FORCE_PRIORITY,
TOP_PRIORITY,
REPAIR_PRIORITY,
STOP_PRIORITY,
VERIFIED_FILE,
@@ -72,10 +72,10 @@ class NzbQueue:
NzbQueue.do = self
def read_queue(self, repair):
"""Read queue from disk, supporting repair modes
0 = no repairs
1 = use existing queue, add missing "incomplete" folders
2 = Discard all queue admin, reconstruct from "incomplete" folders
""" Read queue from disk, supporting repair modes
0 = no repairs
1 = use existing queue, add missing "incomplete" folders
2 = Discard all queue admin, reconstruct from "incomplete" folders
"""
nzo_ids = []
if repair < 2:
@@ -132,10 +132,10 @@ class NzbQueue:
@NzbQueueLocker
def scan_jobs(self, all_jobs=False, action=True):
"""Scan "incomplete" for missing folders,
'all' is True: Include active folders
'action' is True, do the recovery action
returns list of orphaned folders
""" Scan "incomplete" for missing folders,
'all' is True: Include active folders
'action' is True, do the recovery action
returns list of orphaned folders
"""
result = []
# Folders from the download queue
@@ -374,9 +374,9 @@ class NzbQueue:
@NzbQueueLocker
def remove(self, nzo_id, add_to_history=True, cleanup=True, delete_all_data=True):
"""Remove NZO from queue.
It can be added to history directly.
Or, we do some clean-up, sometimes leaving some data.
""" Remove NZO from queue.
It can be added to history directly.
Or, we do some clean-up, sometimes leaving some data.
"""
if nzo_id in self.__nzo_table:
nzo = self.__nzo_table.pop(nzo_id)
@@ -442,11 +442,9 @@ class NzbQueue:
else:
self.remove(nzo_id, add_to_history=False, keep_basic=False)
elif force_delete:
# Force-remove all trace and update counters
# Force-remove all trace
nzo.bytes -= nzf.bytes
nzo.bytes_tried -= nzf.bytes - nzf.bytes_left
if nzf.is_par2 or sabnzbd.par2file.is_parfile(nzf.filename):
nzo.bytes_par2 -= nzf.bytes
del nzo.files_table[nzf_id]
nzo.finished_files.remove(nzf)
logging.info("Removed NZFs %s from job %s", removed, nzo.final_name)
@@ -579,8 +577,8 @@ class NzbQueue:
self.__nzo_list = sort_queue_function(self.__nzo_list, _nzo_size_cmp, reverse)
def sort_queue(self, field, reverse=None):
"""Sort queue by field: "name", "size" or "avg_age"
Direction is specified as "desc"/True or "asc"/False
""" Sort queue by field: "name", "size" or "avg_age"
Direction is specified as "desc"/True or "asc"/False
"""
if isinstance(reverse, str):
if reverse.lower() == "desc":
@@ -635,7 +633,7 @@ class NzbQueue:
if nzo_id_pos1 != -1:
del self.__nzo_list[nzo_id_pos1]
if priority == FORCE_PRIORITY:
if priority == TOP_PRIORITY:
# A top priority item (usually a completed download fetching pars)
# is added to the top of the queue
self.__nzo_list.insert(0, nzo)
@@ -686,8 +684,7 @@ class NzbQueue:
except:
return -1
@staticmethod
def reset_try_lists(article, article_reset=True):
def reset_try_lists(self, article, article_reset=True):
""" Let article get new fetcher and reset trylists """
article.fetcher = None
if article_reset:
@@ -700,27 +697,27 @@ class NzbQueue:
nzo.reset_all_try_lists()
def has_forced_items(self):
"""Check if the queue contains any Forced
Priority items to download while paused
""" Check if the queue contains any Forced
Priority items to download while paused
"""
for nzo in self.__nzo_list:
if nzo.priority == FORCE_PRIORITY and nzo.status not in (Status.PAUSED, Status.GRABBING):
if nzo.priority == TOP_PRIORITY and nzo.status not in (Status.PAUSED, Status.GRABBING):
return True
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
""" Get next article for jobs in the queue
Not locked for performance, since it only reads the queue
"""
# Pre-calculate propagation delay
propagation_delay = float(cfg.propagation_delay() * 60)
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 == FORCE_PRIORITY:
if nzo.status not in (Status.PAUSED, Status.GRABBING) or nzo.priority == TOP_PRIORITY:
# Check if past propagation delay, or forced
if (
not propagation_delay
or nzo.priority == FORCE_PRIORITY
or nzo.priority == TOP_PRIORITY
or (nzo.avg_stamp + propagation_delay) < time.time()
):
if not nzo.server_in_try_list(server):
@@ -732,8 +729,8 @@ class NzbQueue:
return
def register_article(self, article, success=True):
"""Register the articles we tried
Not locked for performance, since it only modifies individual NZOs
""" Register the articles we tried
Not locked for performance, since it only modifies individual NZOs
"""
nzf = article.nzf
nzo = nzf.nzo
@@ -784,7 +781,7 @@ class NzbQueue:
if nzo.precheck:
nzo.save_to_disk()
# Check result
enough, _ = nzo.check_availability_ratio()
enough, _ratio = nzo.check_availability_ratio()
if enough:
# Enough data present, do real download
self.send_back(nzo)
@@ -795,8 +792,8 @@ class NzbQueue:
Assembler.do.process((nzo, None, None))
def actives(self, grabs=True):
"""Return amount of non-paused jobs, optionally with 'grabbing' items
Not locked for performance, only reads the queue
""" 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:
@@ -808,9 +805,9 @@ class NzbQueue:
return n
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
""" 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()
@@ -822,7 +819,7 @@ class NzbQueue:
n = 0
for nzo in self.__nzo_list:
if nzo.status not in (Status.PAUSED, Status.CHECKING) or nzo.priority == FORCE_PRIORITY:
if nzo.status not in (Status.PAUSED, Status.CHECKING) or nzo.priority == TOP_PRIORITY:
b_left = nzo.remaining
bytes_total += nzo.bytes
bytes_left += b_left
@@ -841,8 +838,8 @@ class NzbQueue:
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
Not locked for performance, only reads the queue
""" 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:
@@ -947,7 +944,7 @@ def _nzo_size_cmp(nzo1, nzo2):
def sort_queue_function(nzo_list, method, reverse):
ultra_high_priority = [nzo for nzo in nzo_list if nzo.priority == REPAIR_PRIORITY]
super_high_priority = [nzo for nzo in nzo_list if nzo.priority == FORCE_PRIORITY]
super_high_priority = [nzo for nzo in nzo_list if nzo.priority == TOP_PRIORITY]
high_priority = [nzo for nzo in nzo_list if nzo.priority == HIGH_PRIORITY]
normal_priority = [nzo for nzo in nzo_list if nzo.priority == NORMAL_PRIORITY]
low_priority = [nzo for nzo in nzo_list if nzo.priority == LOW_PRIORITY]

View File

@@ -20,6 +20,7 @@ sabnzbd.nzbstuff - misc
"""
import os
import pickle
import time
import re
import logging
@@ -35,7 +36,7 @@ from sabnzbd.constants import (
ATTRIB_FILE,
JOB_ADMIN,
REPAIR_PRIORITY,
FORCE_PRIORITY,
TOP_PRIORITY,
HIGH_PRIORITY,
NORMAL_PRIORITY,
LOW_PRIORITY,
@@ -77,6 +78,7 @@ from sabnzbd.filesystem import (
renamer,
remove_file,
get_filepath,
globber,
make_script_path,
)
from sabnzbd.decorators import synchronized
@@ -90,6 +92,7 @@ from sabnzbd.rating import Rating
# Name patterns
SUBJECT_FN_MATCHER = re.compile(r'"([^"]*)"')
RE_NORMAL_NAME = re.compile(r"\.\w{1,5}$") # Test reasonably sized extension at the end
RE_QUICK_PAR2_CHECK = re.compile(r"\.par2\W*", re.I)
RE_RAR = re.compile(r"(\.rar|\.r\d\d|\.s\d\d|\.t\d\d|\.u\d\d|\.v\d\d)$", re.I)
RE_PROPER = re.compile(r"(^|[\. _-])(PROPER|REAL|REPACK)([\. _-]|$)")
@@ -102,7 +105,8 @@ TRYLIST_LOCK = threading.Lock()
class TryList:
"""TryList keeps track of which servers have been tried for a specific article"""
""" TryList keeps track of which servers have been tried for a specific article
"""
# Pre-define attributes to save memory
__slots__ = ("try_list", "fetcher_priority")
@@ -198,6 +202,7 @@ class Article(TryList):
for server_check in servers:
if log:
logging.debug("Article %s | Server: %s | checking", self.article, server.host)
# if (server_check.priority() < found_priority and server_check.priority() < server.priority and not self.server_in_try_list(server_check)):
if server_check.active and (server_check.priority < found_priority):
if server_check.priority < server.priority:
if not self.server_in_try_list(server_check):
@@ -275,9 +280,9 @@ class Article(TryList):
return self.article == other.article
def __hash__(self):
"""Required because we implement eq. Articles with the same
usenet address can appear in different NZF's. So we make every
article object unique, even though it is bad pratice.
""" Required because we implement eq. Articles with the same
usenet address can appear in different NZF's. So we make every
article object unique, even though it is bad pratice.
"""
return id(self)
@@ -361,11 +366,10 @@ class NzbFile(TryList):
first_article.lowest_partnum = True
# For non-par2 files we also use it to do deobfuscate-during-download
# And we count how many bytes are available for repair
if sabnzbd.par2file.is_parfile(self.filename):
setname, vol, block = sabnzbd.par2file.analyse_par2(self.filename)
if not vol and not block:
self.nzo.first_articles.append(first_article)
self.nzo.first_articles_count += 1
self.nzo.bytes_par2 += self.bytes
# Any articles left?
if raw_article_db:
@@ -478,8 +482,8 @@ class NzbFile(TryList):
self.md5 = None
def __eq__(self, other):
"""Assume it's the same file if the numer bytes and first article
are the same or if there are no articles left, use the filenames
""" Assume it's the same file if the numer bytes and first article
are the same or if there are no articles left, use the filenames
"""
if self.bytes == other.bytes:
if self.decodetable and other.decodetable:
@@ -489,9 +493,9 @@ class NzbFile(TryList):
return False
def __hash__(self):
"""Required because we implement eq. The same file can be spread
over multiple NZO's so we make every NZF unique. Even though
it's considered bad pratice.
""" Required because we implement eq. The same file can be spread
over multiple NZO's so we make every NZF unique. Even though
it's considered bad pratice.
"""
return id(self)
@@ -511,7 +515,6 @@ NzbObjectSaver = (
"bytes_downloaded",
"bytes_tried",
"bytes_missing",
"bytes_par2",
"repair",
"unpack",
"delete",
@@ -636,7 +639,6 @@ class NzbObject(TryList):
self.created = False # dirprefixes + work_name created
self.direct_unpacker = None # Holds the DirectUnpacker instance
self.bytes = 0 # Original bytesize
self.bytes_par2 = 0 # Bytes available for repair
self.bytes_downloaded = 0 # Downloaded byte
self.bytes_tried = 0 # Which bytes did we try
self.bytes_missing = 0 # Bytes missing
@@ -762,10 +764,14 @@ class NzbObject(TryList):
if not self.files and not reuse:
self.purge_data()
if self.url:
logging.warning(T("Empty NZB file %s") + " [%s]", filename, self.url)
if cfg.warn_empty_nzb():
mylog = logging.warning
else:
logging.warning(T("Empty NZB file %s"), filename)
mylog = logging.info
if self.url:
mylog(T("Empty NZB file %s") + " [%s]", filename, self.url)
else:
mylog(T("Empty NZB file %s"), filename)
raise ValueError
if cat is None:
@@ -830,11 +836,6 @@ class NzbObject(TryList):
else:
accept = 1
# Pause if requested by the NZB-adding or the pre-queue script
if self.priority == PAUSED_PRIORITY:
self.pause()
self.priority = NORMAL_PRIORITY
# Pause job when above size limit
limit = cfg.size_limit.get_int()
if not reuse and abs(limit) > 0.5 and self.bytes > limit:
@@ -888,11 +889,17 @@ class NzbObject(TryList):
self.fail_msg = T("Aborted, unwanted extension detected")
accept = 2
if self.priority == PAUSED_PRIORITY:
self.pause()
self.priority = NORMAL_PRIORITY
if reuse:
self.check_existing_files(work_dir)
# Sort the files in the queue
self.sort_nzfs()
if cfg.auto_sort():
self.files.sort(key=functools.cmp_to_key(nzf_cmp_date))
else:
self.files.sort(key=functools.cmp_to_key(nzf_cmp_name))
# Copy meta fields to nzo_info, if not already set
for kw in self.meta:
@@ -904,7 +911,7 @@ class NzbObject(TryList):
self.password = self.meta.get("password", [None])[0]
# Set nzo save-delay to minimum 120 seconds
self.save_timeout = max(120, min(6.0 * self.bytes / GIGI, 300.0))
self.save_timeout = max(120, min(6.0 * float(self.bytes) / GIGI, 300.0))
# In case pre-queue script or duplicate check want to move
# to history we first need an nzo_id by entering the NzbQueue
@@ -936,20 +943,24 @@ class NzbObject(TryList):
return not bool(self.files)
def sort_nzfs(self):
"""Sort the files in the NZO based on name and type
and then optimize for unwanted extensions search.
""" Sort the files in the NZO, respecting
date sorting and unwanted extensions
"""
self.files.sort(key=functools.cmp_to_key(nzf_cmp_name))
if cfg.auto_sort():
self.files.sort(key=functools.cmp_to_key(nzf_cmp_date))
else:
self.files.sort(key=functools.cmp_to_key(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():
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")
firstrarpos = lastrarpos = 0
for nzfposcounter, nzf in enumerate(self.files):
if RE_RAR.search(nzf.filename.lower()):
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
@@ -960,11 +971,10 @@ class NzbObject(TryList):
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", lastrarnzf.filename)
logging.debug("Unwanted Extension: Last rar is %s", str(lastrarnzf))
try:
# Remove and add it back after the position of the first rar
self.files.remove(lastrarnzf)
self.files.insert(firstrarpos + 1, lastrarnzf)
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")
@@ -1018,7 +1028,7 @@ class NzbObject(TryList):
nzf.set_par2(setname, vol, block)
# Parse the file contents for hashes
pack = sabnzbd.par2file.parse_par2_file(filepath, nzf.nzo.md5of16k)
pack = sabnzbd.par2file.parse_par2_file(nzf, filepath)
# If we couldn't parse it, we ignore it
if pack:
@@ -1057,8 +1067,8 @@ class NzbObject(TryList):
@synchronized(NZO_LOCK)
def promote_par2(self, nzf):
"""In case of a broken par2 or missing par2, move another
of the same set to the top (if we can find it)
""" In case of a broken par2 or missing par2, move another
of the same set to the top (if we can find it)
"""
setname, vol, block = sabnzbd.par2file.analyse_par2(nzf.filename)
# Now we need to identify if we have more in this set
@@ -1076,11 +1086,11 @@ class NzbObject(TryList):
break
def get_extra_blocks(self, setname, needed_blocks):
"""We want par2-files of all sets that are similar to this one
So that we also can handle multi-sets with duplicate filenames
Returns number of added blocks in case they are available
In case of duplicate files for the same set, we might add too
little par2 on the first add-run, but that's a risk we need to take.
""" We want par2-files of all sets that are similar to this one
So that we also can handle multi-sets with duplicate filenames
Returns number of added blocks in case they are available
In case of duplicate files for the same set, we might add too
little par2 on the first add-run, but that's a risk we need to take.
"""
logging.info("Need %s more blocks, checking blocks", needed_blocks)
@@ -1121,25 +1131,6 @@ class NzbObject(TryList):
job_can_succeed = True
nzf = article.nzf
# Update all statistics
# Ignore bytes from par2 files that were postponed
if nzf in self.files:
self.bytes_tried += article.bytes
if not success:
# Increase missing bytes counter
self.bytes_missing += article.bytes
# Add extra parfiles when there was a damaged article and not pre-checking
if self.extrapars and not self.precheck:
self.prospective_add(nzf)
# Sometimes a few CRC errors are still fine, abort otherwise
if self.bad_articles > MAX_BAD_ARTICLES:
self.abort_direct_unpacker()
else:
# Increase counter of actually finished bytes
self.bytes_downloaded += article.bytes
# First or regular article?
if article.lowest_partnum and self.first_articles and article in self.first_articles:
self.first_articles.remove(article)
@@ -1158,18 +1149,16 @@ class NzbObject(TryList):
articles_left = nzf.remove_article(article, success)
file_done = not articles_left
# Only on fully loaded files we can know if it's really done
# 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)
# Check if we can succeed when we have missing articles
# Skip check if retry or first articles already deemed it hopeless
if not success and job_can_succeed and not self.reuse and cfg.fail_hopeless_jobs():
job_can_succeed, _ = self.check_availability_ratio()
# Skip check if retry or first articles already deemed it hopeless
if job_can_succeed and not self.reuse and cfg.fail_hopeless_jobs():
job_can_succeed, _ratio = self.check_availability_ratio(99)
# Abort the job due to failure
if not job_can_succeed:
@@ -1181,6 +1170,23 @@ class NzbObject(TryList):
logging.debug('Abort job "%s", due to impossibility to complete it', self.final_name)
return True, True, True
if not success:
# Add extra parfiles when there was a damaged article and not pre-checking
if self.extrapars and not self.precheck:
self.prospective_add(nzf)
# Sometimes a few CRC errors are still fine, so we continue
if self.bad_articles > MAX_BAD_ARTICLES:
self.abort_direct_unpacker()
# Increase missing bytes counter
self.bytes_missing += article.bytes
else:
# Increase counter of actually finished bytes
self.bytes_downloaded += article.bytes
# All the bytes that were tried
self.bytes_tried += article.bytes
post_done = False
if not self.files:
post_done = True
@@ -1246,7 +1252,6 @@ class NzbObject(TryList):
filepath = os.path.join(wdir, filename)
if sabnzbd.par2file.is_parfile(filepath):
self.handle_par2(nzf, filepath)
self.bytes_par2 += nzf.bytes
break
# Create an NZF for each remaining existing file
@@ -1271,7 +1276,6 @@ class NzbObject(TryList):
# Process par2 files
if sabnzbd.par2file.is_parfile(filepath):
self.handle_par2(nzf, filepath)
self.bytes_par2 += nzf.bytes
logging.info("Existing file %s added to job", filename)
except:
logging.error(T("Error importing %s"), self.final_name)
@@ -1302,7 +1306,7 @@ class NzbObject(TryList):
value = int_conv(value)
if value in (
REPAIR_PRIORITY,
FORCE_PRIORITY,
TOP_PRIORITY,
HIGH_PRIORITY,
NORMAL_PRIORITY,
LOW_PRIORITY,
@@ -1342,7 +1346,7 @@ class NzbObject(TryList):
# Propagation delay label
propagation_delay = float(cfg.propagation_delay() * 60)
if propagation_delay and self.avg_stamp + propagation_delay > time.time() and self.priority != FORCE_PRIORITY:
if propagation_delay and self.avg_stamp + propagation_delay > time.time() and self.priority != TOP_PRIORITY:
wait_time = int((self.avg_stamp + propagation_delay - time.time()) / 60 + 0.5)
labels.append(T("PROPAGATING %s min") % wait_time) # Queue indicator while waiting for propagation of post
@@ -1391,9 +1395,9 @@ class NzbObject(TryList):
@synchronized(NZO_LOCK)
def add_parfile(self, parfile):
"""Add parfile to the files to be downloaded
Resets trylist just to be sure
Adjust download-size accordingly
""" Add parfile to the files to be downloaded
Resets trylist just to be sure
Adjust download-size accordingly
"""
if not parfile.completed and parfile not in self.files and parfile not in self.finished_files:
parfile.reset_all_try_lists()
@@ -1416,8 +1420,8 @@ class NzbObject(TryList):
@synchronized(NZO_LOCK)
def prospective_add(self, nzf):
"""Add par2 files to compensate for missing articles
This fails in case of multi-sets with identical setnames
""" Add par2 files to compensate for missing articles
This fails in case of multi-sets with identical setnames
"""
# Make sure to also select a parset if it was in the original filename
original_filename = self.renames.get(nzf.filename, "")
@@ -1449,42 +1453,48 @@ class NzbObject(TryList):
if self.direct_unpacker:
self.direct_unpacker.abort()
def check_availability_ratio(self):
""" Determine if we are still meeting the required ratio """
availability_ratio = req_ratio = cfg.req_completion_rate()
# Rare case where the NZB only consists of par2 files
if self.bytes > self.bytes_par2:
# Calculate ratio based on byte-statistics
availability_ratio = 100 * (self.bytes - self.bytes_missing) / (self.bytes - self.bytes_par2)
logging.debug(
"Availability ratio=%.2f, bad articles=%d, total bytes=%d, missing bytes=%d, par2 bytes=%d",
availability_ratio,
self.bad_articles,
self.bytes,
self.bytes_missing,
self.bytes_par2,
)
# When there is no or little par2, we allow a few bad articles
# This way RAR-only jobs might still succeed
def check_availability_ratio(self, req_ratio=0):
""" Determine amount of articles present on servers
and return (gross available, nett) bytes
"""
# Few missing articles in RAR-only job might still work
if self.bad_articles <= MAX_BAD_ARTICLES:
return True, req_ratio
logging.debug("Download Quality: bad-articles=%s", self.bad_articles)
return True, 200
# Check based on availability ratio
return availability_ratio >= req_ratio, availability_ratio
# Do the full check
need = 0
pars = 0
short = 0
anypars = False
for nzf_id in self.files_table:
nzf = self.files_table[nzf_id]
if nzf.deleted:
short += nzf.bytes_left
if RE_QUICK_PAR2_CHECK.search(nzf.subject):
pars += nzf.bytes
anypars = True
else:
need += nzf.bytes
have = need + pars - short
ratio = float(have) / float(max(1, need))
if anypars:
enough = ratio * 100.0 >= (req_ratio or float(cfg.req_completion_rate()))
else:
enough = have >= need
logging.debug("Download Quality: enough=%s, have=%s, need=%s, ratio=%s", enough, have, need, ratio)
return enough, ratio
def check_first_article_availability(self):
"""Use the first articles to see if
it's likely the job will succeed
""" Use the first articles to see if
it's likely the job will succeed
"""
# Ignore this check on retry
if not self.reuse:
# Ignore undamaged or small downloads
if self.bad_articles and self.first_articles_count >= 10:
# We need a float-division, see if more than 80% is there
if self.bad_articles / self.first_articles_count >= 0.8:
if (float(self.bad_articles) / self.first_articles_count) >= 0.8:
return False
return True
@@ -1715,8 +1725,8 @@ class NzbObject(TryList):
@synchronized(NZO_LOCK)
def renamed_file(self, name_set, old_name=None):
"""Save renames at various stages (Download/PP)
to be used on Retry. Accepts strings and dicts.
""" Save renames at various stages (Download/PP)
to be used on Retry. Accepts strings and dicts.
"""
if not old_name:
# Add to dict
@@ -1758,6 +1768,9 @@ class NzbObject(TryList):
except:
pass
## end nzo.Mutators #######################################################
###########################################################################
@property
def workpath(self):
""" Return the full path for my job-admin folder """
@@ -1851,8 +1864,8 @@ class NzbObject(TryList):
@synchronized(NZO_LOCK)
def set_unpack_info(self, key, msg, setname=None, unique=False):
"""Builds a dictionary containing the stage name (key) and a message
If unique is present, it will only have a single line message
""" Builds a dictionary containing the stage name (key) and a message
If unique is present, it will only have a single line message
"""
# Add name of the set
if setname:
@@ -1938,9 +1951,9 @@ class NzbObject(TryList):
nzf_ids.remove(nzf_id)
def has_duplicates(self):
"""Return (res, series)
where "res" is True when this is a duplicate
where "series" is True when this is an episode
""" Return (res, series)
where "res" is True when this is a duplicate
where "series" is True when this is an episode
"""
no_dupes = cfg.no_dupes()
@@ -2032,30 +2045,44 @@ class NzbObject(TryList):
self.bytes_tried += nzf.bytes
for nzf in self.files:
self.bytes_tried += nzf.bytes - nzf.bytes_left
if self.bytes_par2 is None:
self.bytes_par2 = 0
for nzf in self.files + self.finished_files:
if sabnzbd.par2file.is_parfile(nzf.filename):
self.bytes_par2 += nzf.bytes
def __repr__(self):
return "<NzbObject: filename=%s, bytes=%s, nzo_id=%s>" % (self.filename, self.bytes, self.nzo_id)
def nzf_cmp_name(nzf1, nzf2):
def nzf_get_filename(nzf):
""" Return filename, if the filename not set, try the
the full subject line instead. Can produce non-ideal results
"""
name = nzf.filename
if not name:
name = nzf.subject
if not name:
name = ""
return name.lower()
def nzf_cmp_date(nzf1, nzf2):
""" Compare files based on date, but give vol-par files preference.
Wrapper needed, because `cmp` function doesn't handle extra parms.
"""
return nzf_cmp_name(nzf1, nzf2, name=False)
def nzf_cmp_name(nzf1, nzf2, name=True):
# The comparison will sort .par2 files to the top of the queue followed by .rar files,
# they will then be sorted by name.
nzf1_name = nzf1.filename.lower()
nzf2_name = nzf2.filename.lower()
name1 = nzf_get_filename(nzf1)
name2 = nzf_get_filename(nzf2)
# Determine vol-pars
is_par1 = ".vol" in nzf1_name and ".par2" in nzf1_name
is_par2 = ".vol" in nzf2_name and ".par2" in nzf2_name
is_par1 = ".vol" in name1 and ".par2" in name1
is_par2 = ".vol" in name2 and ".par2" in name2
# mini-par2 in front
if not is_par1 and nzf1_name.endswith(".par2"):
if not is_par1 and name1.endswith(".par2"):
return -1
if not is_par2 and nzf2_name.endswith(".par2"):
if not is_par2 and name2.endswith(".par2"):
return 1
# vol-pars go to the back
@@ -2064,19 +2091,23 @@ def nzf_cmp_name(nzf1, nzf2):
if is_par2 and not is_par1:
return -1
# Prioritize .rar files above any other type of file (other than vol-par)
m1 = RE_RAR.search(nzf1_name)
m2 = RE_RAR.search(nzf2_name)
if m1 and not (is_par2 or m2):
return -1
elif m2 and not (is_par1 or m1):
return 1
# Force .rar to come before 'r00'
if m1 and m1.group(1) == ".rar":
nzf1_name = nzf1_name.replace(".rar", ".r//")
if m2 and m2.group(1) == ".rar":
nzf2_name = nzf2_name.replace(".rar", ".r//")
return cmp(nzf1_name, nzf2_name)
if name:
# Prioritize .rar files above any other type of file (other than vol-par)
m1 = RE_RAR.search(name1)
m2 = RE_RAR.search(name2)
if m1 and not (is_par2 or m2):
return -1
elif m2 and not (is_par1 or m1):
return 1
# Force .rar to come before 'r00'
if m1 and m1.group(1) == ".rar":
name1 = name1.replace(".rar", ".r//")
if m2 and m2.group(1) == ".rar":
name2 = name2.replace(".rar", ".r//")
return cmp(name1, name2)
else:
# Do date comparison
return cmp(nzf1.date, nzf2.date)
def create_work_name(name):
@@ -2118,12 +2149,8 @@ def scan_password(name):
return name[:pw].strip(". "), name[pw + 9 :]
# Look for name{{password}}
if braces < len(name) and "}}" in name:
closing_braces = name.find("}}")
if closing_braces < 0:
closing_braces = len(name)
return name[:braces].strip(". "), name[braces + 2 : closing_braces]
if braces < len(name) and name.endswith("}}"):
return name[:braces].strip(". "), name[braces + 2 : len(name) - 2]
# Look again for name/password
if slash >= 0:

View File

@@ -250,8 +250,8 @@ def launch_a_browser(url, force=False):
def show_error_dialog(msg):
"""Show a pop-up when program cannot start
Windows-only, otherwise only print to console
""" Show a pop-up when program cannot start
Windows-only, otherwise only print to console
"""
if sabnzbd.WIN32:
ctypes.windll.user32.MessageBoxW(0, msg, T("Fatal error"), 0)

View File

@@ -18,12 +18,11 @@
"""
sabnzbd.par2file - All par2-related functionality
"""
import hashlib
import logging
import os
import logging
import re
import hashlib
import struct
from sabnzbd.encoding import correct_unknown_encoding
PROBABLY_PAR2_RE = re.compile(r"(.*)\.vol(\d*)[\+\-](\d*)\.par2", re.I)
@@ -34,25 +33,20 @@ PAR_RECOVERY_ID = b"RecvSlic"
def is_parfile(filename):
"""Check quickly whether file has par2 signature
or if the filename has '.par2' in it
"""
if os.path.exists(filename):
try:
with open(filename, "rb") as f:
buf = f.read(8)
return buf.startswith(PAR_PKT_ID)
except:
pass
elif ".par2" in filename.lower():
return True
""" Check quickly whether file has par2 signature """
try:
with open(filename, "rb") as f:
buf = f.read(8)
return buf.startswith(PAR_PKT_ID)
except:
pass
return False
def analyse_par2(name, filepath=None):
"""Check if file is a par2-file and determine vol/block
return setname, vol, block
setname is empty when not a par2 file
""" Check if file is a par2-file and determine vol/block
return setname, vol, block
setname is empty when not a par2 file
"""
name = name.strip()
vol = block = 0
@@ -82,13 +76,11 @@ def analyse_par2(name, filepath=None):
return setname, vol, block
def parse_par2_file(fname, md5of16k):
"""Get the hash table and the first-16k hash table from a PAR2 file
Return as dictionary, indexed on names or hashes for the first-16 table
The input md5of16k is modified in place and thus not returned!
For a full description of the par2 specification, visit:
http://parchive.sourceforge.net/docs/specifications/parity-volume-spec/article-spec.html
def parse_par2_file(nzf, fname):
""" Get the hash table and the first-16k hash table from a PAR2 file
Return as dictionary, indexed on names or hashes for the first-16 table
For a full description of the par2 specification, visit:
http://parchive.sourceforge.net/docs/specifications/parity-volume-spec/article-spec.html
"""
table = {}
duplicates16k = []
@@ -100,9 +92,9 @@ def parse_par2_file(fname, md5of16k):
name, filehash, hash16k = parse_par2_file_packet(f, header)
if name:
table[name] = filehash
if hash16k not in md5of16k:
md5of16k[hash16k] = name
elif md5of16k[hash16k] != name:
if hash16k not in nzf.nzo.md5of16k:
nzf.nzo.md5of16k[hash16k] = name
elif nzf.nzo.md5of16k[hash16k] != name:
# Not unique and not already linked to this file
# Remove to avoid false-renames
duplicates16k.append(hash16k)
@@ -121,8 +113,8 @@ def parse_par2_file(fname, md5of16k):
# Have to remove duplicates at the end to make sure
# no trace is left in case of multi-duplicates
for hash16k in duplicates16k:
if hash16k in md5of16k:
old_name = md5of16k.pop(hash16k)
if hash16k in nzf.nzo.md5of16k:
old_name = nzf.nzo.md5of16k.pop(hash16k)
logging.debug("Par2-16k signature of %s not unique, discarding", old_name)
return table

View File

@@ -65,7 +65,7 @@ from sabnzbd.filesystem import (
from sabnzbd.sorting import Sorter
from sabnzbd.constants import (
REPAIR_PRIORITY,
FORCE_PRIORITY,
TOP_PRIORITY,
POSTPROC_QUEUE_FILE_NAME,
POSTPROC_QUEUE_VERSION,
sample_match,
@@ -86,8 +86,6 @@ import sabnzbd.notifier as notifier
import sabnzbd.utils.rarfile as rarfile
import sabnzbd.utils.rarvolinfo as rarvolinfo
import sabnzbd.utils.checkdir
import sabnzbd.deobfuscate_filenames as deobfuscate
MAX_FAST_JOB_COUNT = 3
@@ -222,7 +220,7 @@ class PostProcessor(Thread):
# First we do a dircheck
complete_dir = sabnzbd.cfg.complete_dir.get_path()
if sabnzbd.utils.checkdir.isFAT(complete_dir):
logging.warning_helpful(
logging.warning(
T("Completed Download Folder %s is on FAT file system, limiting maximum file size to 4GB")
% complete_dir
)
@@ -342,8 +340,15 @@ def process_job(nzo):
# if no files are present (except __admin__), fail the job
if all_ok and len(globber(workdir)) < 2:
if nzo.precheck:
_, ratio = nzo.check_availability_ratio()
emsg = T("Download might fail, only %s of required %s available") % (ratio, cfg.req_completion_rate())
_enough, ratio = nzo.check_availability_ratio()
req_ratio = float(cfg.req_completion_rate()) / 100.0
# Make sure that rounded ratio doesn't equal required ratio
# when it is actually below required
if (ratio < req_ratio) and (req_ratio - ratio) < 0.001:
ratio = req_ratio - 0.001
emsg = "%.1f%%" % (ratio * 100.0)
emsg2 = "%.1f%%" % float(cfg.req_completion_rate())
emsg = T("Download might fail, only %s of required %s available") % (emsg, emsg2)
else:
emsg = T("Download failed - Not on your server(s)")
empty = True
@@ -372,9 +377,6 @@ def process_job(nzo):
# Set complete dir to workdir in case we need to abort
workdir_complete = workdir
# Send post-processing notification
notifier.send_notification(T("Post-processing"), nzo.final_name, "pp", nzo.cat)
# Par processing, if enabled
if all_ok and flag_repair:
par_error, re_add = parring(nzo, workdir)
@@ -488,9 +490,7 @@ def process_job(nzo):
newfiles = rename_and_collapse_folder(tmp_workdir_complete, workdir_complete, newfiles)
except:
logging.error(
T('Error renaming "%s" to "%s"'),
clip_path(tmp_workdir_complete),
clip_path(workdir_complete),
T('Error renaming "%s" to "%s"'), clip_path(tmp_workdir_complete), clip_path(workdir_complete),
)
logging.info("Traceback: ", exc_info=True)
# Better disable sorting because filenames are all off now
@@ -515,11 +515,6 @@ def process_job(nzo):
nzo.set_unpack_info("Unpack", T("Failed to move files"))
all_ok = False
if cfg.deobfuscate_final_filenames() and all_ok and not nzb_list and not one_folder:
# deobfuscate the filenames
logging.info("Running deobfuscate on directory %s", workdir_complete)
deobfuscate.deobfuscate(workdir_complete, nzo.final_name)
# Run the user script
script_path = make_script_path(script)
if (all_ok or not cfg.safe_postproc()) and (not nzb_list) and script_path:
@@ -657,7 +652,7 @@ def process_job(nzo):
history_db = database.HistoryDB()
# Add the nzo to the database. Only the path, script and time taken is passed
# Other information is obtained from the nzo
history_db.add_history_db(nzo, workdir_complete, postproc_time, script_log, script_line)
history_db.add_history_db(nzo, clip_path(workdir_complete), nzo.downpath, postproc_time, script_log, script_line)
# Purge items
history_db.auto_history_purge()
# The connection is only used once, so close it here
@@ -667,9 +662,9 @@ def process_job(nzo):
def prepare_extraction_path(nzo):
"""Based on the information that we have, generate
the extraction path and create the directory.
Separated so it can be called from DirectUnpacker
""" Based on the information that we have, generate
the extraction path and create the directory.
Separated so it can be called from DirectUnpacker
"""
one_folder = False
marker_file = None
@@ -722,21 +717,19 @@ def prepare_extraction_path(nzo):
def parring(nzo, workdir):
""" Perform par processing. Returns: (par_error, re_add) """
logging.info("Starting verification and repair of %s", nzo.final_name)
par_error = False
re_add = False
job_name = nzo.final_name
notifier.send_notification(T("Post-processing"), job_name, "pp", nzo.cat)
logging.info("Starting verification and repair of %s", job_name)
# Get verification status of sets
verified = sabnzbd.load_data(VERIFIED_FILE, nzo.workpath, remove=False) or {}
# If all were verified successfully, we skip the rest of the checks
if verified and all(verified.values()):
logging.info("Skipping repair, all sets previously verified: %s", verified)
return par_error, re_add
re_add = False
par_error = False
single = len(nzo.extrapars) == 1
if nzo.extrapars:
# Need to make a copy because it can change during iteration
single = len(nzo.extrapars) == 1
for setname in list(nzo.extrapars):
if cfg.ignore_samples() and RE_SAMPLE.search(setname.lower()):
continue
@@ -763,8 +756,8 @@ def parring(nzo, workdir):
elif not verified.get("", False):
# No par2-sets found, skipped if already tried before
logging.info("No par2 sets for %s", nzo.final_name)
nzo.set_unpack_info("Repair", T("[%s] No par2 sets") % nzo.final_name)
logging.info("No par2 sets for %s", job_name)
nzo.set_unpack_info("Repair", T("[%s] No par2 sets") % job_name)
# Try SFV-based verification and rename
sfv_check_result = None
@@ -789,8 +782,8 @@ def parring(nzo, workdir):
verified[""] = not par_error
if re_add:
logging.info("Re-added %s to queue", nzo.final_name)
if nzo.priority != FORCE_PRIORITY:
logging.info("Re-added %s to queue", job_name)
if nzo.priority != TOP_PRIORITY:
nzo.priority = REPAIR_PRIORITY
nzo.status = Status.FETCHING
sabnzbd.nzbqueue.NzbQueue.do.add(nzo)
@@ -798,13 +791,13 @@ def parring(nzo, workdir):
sabnzbd.save_data(verified, VERIFIED_FILE, nzo.workpath)
logging.info("Verification and repair finished for %s", nzo.final_name)
logging.info("Verification and repair finished for %s", job_name)
return par_error, re_add
def try_sfv_check(nzo, workdir):
"""Attempt to verify set using SFV file
Return None if no SFV-sets, True/False based on verification
""" Attempt to verify set using SFV file
Return None if no SFV-sets, True/False based on verification
"""
# Get list of SFV names
sfvs = globber_full(workdir, "*.sfv")
@@ -835,10 +828,10 @@ def try_sfv_check(nzo, workdir):
def try_rar_check(nzo, rars):
"""Attempt to verify set using the RARs
Return True if verified, False when failed
When setname is '', all RAR files will be used, otherwise only the matching one
If no RAR's are found, returns True
""" Attempt to verify set using the RARs
Return True if verified, False when failed
When setname is '', all RAR files will be used, otherwise only the matching one
If no RAR's are found, returns True
"""
# Sort for better processing
rars.sort(key=functools.cmp_to_key(rar_sort))
@@ -971,7 +964,7 @@ def rar_renamer(nzo, workdir):
rarsetname[next_obfuscated_filename] = rarsetname[base_obfuscated_filename]
matchcounter += 1
except KeyError:
logging.warning(T("No matching earlier rar file for %s"), next_obfuscated_filename)
logging.warning("No matching earlier rar file for %s", next_obfuscated_filename)
if matchcounter > 1:
logging.info("Deobfuscate: more than one match, so risk on false positive matching.")
@@ -1007,8 +1000,8 @@ def handle_empty_queue():
def cleanup_list(wdir, skip_nzb):
"""Remove all files whose extension matches the cleanup list,
optionally ignoring the nzb extension
""" Remove all files whose extension matches the cleanup list,
optionally ignoring the nzb extension
"""
if cfg.cleanup_list():
try:
@@ -1033,17 +1026,17 @@ def cleanup_list(wdir, skip_nzb):
def prefix(path, pre):
"""Apply prefix to last part of path
'/my/path' and 'hi_' will give '/my/hi_path'
""" Apply prefix to last part of path
'/my/path' and 'hi_' will give '/my/hi_path'
"""
p, d = os.path.split(path)
return os.path.join(p, pre + d)
def nzb_redirect(wdir, nzbname, pp, script, cat, priority):
"""Check if this job contains only NZB files,
if so send to queue and remove if on clean-up list
Returns list of processed NZB's
""" Check if this job contains only NZB files,
if so send to queue and remove if on clean-up list
Returns list of processed NZB's
"""
files = listdir_full(wdir)
@@ -1105,8 +1098,8 @@ def get_last_line(txt):
def remove_samples(path):
"""Remove all files that match the sample pattern
Skip deleting if it matches all files or there is only 1 file
""" Remove all files that match the sample pattern
Skip deleting if it matches all files or there is only 1 file
"""
files_to_delete = []
nr_files = 0
@@ -1130,9 +1123,9 @@ def remove_samples(path):
def rename_and_collapse_folder(oldpath, newpath, files):
"""Rename folder, collapsing when there's just a single subfolder
oldpath --> newpath OR oldpath/subfolder --> newpath
Modify list of filenames accordingly
""" Rename folder, collapsing when there's just a single subfolder
oldpath --> newpath OR oldpath/subfolder --> newpath
Modify list of filenames accordingly
"""
orgpath = oldpath
items = globber(oldpath)

View File

@@ -196,7 +196,7 @@ def linux_shutdown():
else:
logging.info("DBus does not support Stop (shutdown)")
except dbus.exceptions.DBusException as msg:
logging.error(T("Received a DBus exception %s"), msg)
logging.error("Received a DBus exception %s", msg)
os._exit(0)
@@ -226,7 +226,7 @@ def linux_hibernate():
logging.info("DBus does not support Hibernate")
time.sleep(10)
except dbus.exceptions.DBusException as msg:
logging.error(T("Received a DBus exception %s"), msg)
logging.error("Received a DBus exception %s", msg)
def linux_standby():
@@ -255,4 +255,4 @@ def linux_standby():
logging.info("DBus does not support Suspend (standby)")
time.sleep(10)
except dbus.exceptions.DBusException as msg:
logging.error(T("Received a DBus exception %s"), msg)
logging.error("Received a DBus exception %s", msg)

View File

@@ -128,9 +128,9 @@ def notdefault(item):
def convert_filter(text):
"""Return compiled regex.
If string starts with re: it's a real regex
else quote all regex specials, replace '*' by '.*'
""" Return compiled regex.
If string starts with re: it's a real regex
else quote all regex specials, replace '*' by '.*'
"""
text = text.strip().lower()
if text.startswith("re:"):
@@ -145,8 +145,8 @@ def convert_filter(text):
def remove_obsolete(jobs, new_jobs):
"""Expire G/B links that are not in new_jobs (mark them 'X')
Expired links older than 3 days are removed from 'jobs'
""" Expire G/B links that are not in new_jobs (mark them 'X')
Expired links older than 3 days are removed from 'jobs'
"""
now = time.time()
limit = now - 259200 # 3days (3x24x3600)
@@ -625,8 +625,8 @@ class RSSQueue:
self.jobs[feed][item]["status"] = "D-"
def check_duplicate(self, title):
"""Check if this title was in this or other feeds
Return matching feed name
""" Check if this title was in this or other feeds
Return matching feed name
"""
title = title.lower()
for fd in self.jobs:
@@ -638,31 +638,18 @@ class RSSQueue:
def patch_feedparser():
"""Apply options that work for SABnzbd
Add additional parsing of attributes
""" Apply options that work for SABnzbd
Add additional parsing of attributes
"""
feedparser.SANITIZE_HTML = 0
feedparser.RESOLVE_RELATIVE_URIS = 0
# Support both feedparser 5 and 6
try:
feedparser_mixin = feedparser._FeedParserMixin
feedparser_parse_date = feedparser._parse_date
except AttributeError:
feedparser_mixin = feedparser.mixin._FeedParserMixin
feedparser_parse_date = feedparser.datetimes._parse_date
feedparser.PARSE_MICROFORMATS = 0
# Add our own namespace
feedparser_mixin.namespaces["http://www.newznab.com/DTD/2010/feeds/attributes/"] = "newznab"
feedparser._FeedParserMixin.namespaces["http://www.newznab.com/DTD/2010/feeds/attributes/"] = "newznab"
# Add parsers for the namespace
def _start_newznab_attr(self, attrsD):
# Support both feedparser 5 and 6
try:
context = self._getContext()
except AttributeError:
context = self._get_context()
context = self._getContext()
# Add the dict
if "newznab" not in context:
context["newznab"] = {}
@@ -672,14 +659,14 @@ def patch_feedparser():
context["newznab"][attrsD["name"]] = attrsD["value"]
# Try to get date-object
if attrsD["name"] == "usenetdate":
context["newznab"][attrsD["name"] + "_parsed"] = feedparser_parse_date(attrsD["value"])
context["newznab"][attrsD["name"] + "_parsed"] = feedparser._parse_date(attrsD["value"])
except KeyError:
pass
feedparser_mixin._start_newznab_attr = _start_newznab_attr
feedparser_mixin._start_nZEDb_attr = _start_newznab_attr
feedparser_mixin._start_nzedb_attr = _start_newznab_attr
feedparser_mixin._start_nntmux_attr = _start_newznab_attr
feedparser._FeedParserMixin._start_newznab_attr = _start_newznab_attr
feedparser._FeedParserMixin._start_nZEDb_attr = _start_newznab_attr
feedparser._FeedParserMixin._start_nzedb_attr = _start_newznab_attr
feedparser._FeedParserMixin._start_nntmux_attr = _start_newznab_attr
def _HandleLink(
@@ -741,8 +728,8 @@ def _HandleLink(
def _get_link(entry):
"""Retrieve the post link from this entry
Returns (link, category, size)
""" Retrieve the post link from this entry
Returns (link, category, size)
"""
size = 0
age = datetime.datetime.now()
@@ -822,8 +809,8 @@ def special_rss_site(url):
def ep_match(season, episode, expr, title=None):
"""Return True if season, episode is at or above expected
Optionally `title` can be matched
""" Return True if season, episode is at or above expected
Optionally `title` can be matched
"""
m = _RE_SP.search(expr)
if m:

View File

@@ -113,7 +113,7 @@ class SABTrayThread(SysTrayIconThread):
else:
self.hover_text = self.txt_idle
self.icon = self.sabicons["default"]
self.hover_text = "SABnzbd %s\n%s" % (sabnzbd.__version__, self.hover_text)
self.refresh_icon()
self.counter = 0

View File

@@ -276,10 +276,10 @@ def abort():
def sort_schedules(all_events, now=None):
"""Sort the schedules, based on order of happening from now
`all_events=True`: Return an event for each active day
`all_events=False`: Return only first occurring event of the week
`now` : for testing: simulated localtime()
""" Sort the schedules, based on order of happening from now
`all_events=True`: Return an event for each active day
`all_events=False`: Return only first occurring event of the week
`now` : for testing: simulated localtime()
"""
day_min = 24 * 60
@@ -321,8 +321,8 @@ def sort_schedules(all_events, now=None):
def analyse(was_paused=False, priority=None):
"""Determine what pause/resume state we would have now.
'priority': evaluate only effect for given priority, return True for paused
""" Determine what pause/resume state we would have now.
'priority': evaluate only effect for given priority, return True for paused
"""
global PP_PAUSE_EVENT
PP_PAUSE_EVENT = False
@@ -438,8 +438,8 @@ def scheduled_resume():
def __oneshot_resume(when):
"""Called by delayed resume schedule
Only resumes if call comes at the planned time
""" Called by delayed resume schedule
Only resumes if call comes at the planned time
"""
global __PAUSE_END
if __PAUSE_END is not None and (when > __PAUSE_END - 5) and (when < __PAUSE_END + 55):

View File

@@ -544,10 +544,6 @@ SKIN_TEXT = {
"opt-ignore_samples": TT("Ignore Samples"),
"explain-ignore_samples": TT("Filter out sample files (e.g. video samples)."),
"igsam-del": TT("Delete after download"),
"opt-deobfuscate_final_filenames": TT("Deobfuscate final filenames"),
"explain-deobfuscate_final_filenames": TT(
"If filenames of (large) files in the final folder look obfuscated or meaningless they will be renamed to the job name."
),
"opt-enable_https_verification": TT("HTTPS certificate verification"),
"explain-enable_https_verification": TT(
"Verify certificates when connecting to indexers and RSS-sources using HTTPS."

View File

@@ -284,8 +284,7 @@ class SeriesSorter:
# Error Sorting
return os.path.join(self.original_path, self.original_job_name)
@staticmethod
def get_multi_ep_naming(one, two, extras):
def get_multi_ep_naming(self, one, two, extras):
""" Returns a list of unique values joined into a string and separated by - (ex:01-02-03-04) """
extra_list = [one]
extra2_list = [two]
@@ -979,10 +978,10 @@ class DateSorter:
def path_subst(path, mapping):
"""Replace the sort sting elements by real values.
Non-elements are copied literally.
path = the sort string
mapping = array of tuples that maps all elements to their values
""" Replace the sort sting elements by real values.
Non-elements are copied literally.
path = the sort string
mapping = array of tuples that maps all elements to their values
"""
# Added ugly hack to prevent %ext from being masked by %e
newpath = []
@@ -1002,11 +1001,11 @@ def path_subst(path, mapping):
def get_titles(nzo, match, name, titleing=False):
"""The title will be the part before the match
Clean it up and title() it
""" The title will be the part before the match
Clean it up and title() it
''.title() isn't very good under python so this contains
a lot of little hacks to make it better and for more control
''.title() isn't very good under python so this contains
a lot of little hacks to make it better and for more control
"""
if nzo:
title = nzo.nzo_info.get("propername")
@@ -1088,9 +1087,9 @@ def replace_word(word_input, one, two):
def get_descriptions(nzo, match, name):
"""If present, get a description from the nzb name.
A description has to be after the matched item, separated either
like ' - Description' or '_-_Description'
""" If present, get a description from the nzb name.
A description has to be after the matched item, separated either
like ' - Description' or '_-_Description'
"""
if nzo:
ep_name = nzo.nzo_info.get("episodename")
@@ -1151,8 +1150,8 @@ def to_lowercase(path):
def strip_folders(path):
"""Return 'path' without leading and trailing spaces and underscores in each element
For Windows, also remove leading and trailing dots
""" Return 'path' without leading and trailing spaces and underscores in each element
For Windows, also remove leading and trailing dots
"""
unc = sabnzbd.WIN32 and (path.startswith("//") or path.startswith("\\\\"))
f = path.strip("/").split("/")
@@ -1179,10 +1178,10 @@ def strip_folders(path):
def rename_similar(folder, skip_ext, name, skipped_files):
"""Rename all other files in the 'folder' hierarchy after 'name'
and move them to the root of 'folder'.
Files having extension 'skip_ext' will be moved, but not renamed.
Don't touch files in list `skipped_files`
""" Rename all other files in the 'folder' hierarchy after 'name'
and move them to the root of 'folder'.
Files having extension 'skip_ext' will be moved, but not renamed.
Don't touch files in list `skipped_files`
"""
logging.debug('Give files in set "%s" matching names.', name)
folder = os.path.normpath(folder)
@@ -1214,9 +1213,9 @@ def rename_similar(folder, skip_ext, name, skipped_files):
def check_regexs(filename, matchers):
"""Regular Expression match for a list of regexes
Returns the MatchObject if a match is made
This version checks for an additional match
""" Regular Expression match for a list of regexes
Returns the MatchObject if a match is made
This version checks for an additional match
"""
extras = []
for expressions in matchers:
@@ -1237,8 +1236,8 @@ def check_regexs(filename, matchers):
def check_for_date(filename, matcher):
"""Regular Expression match for date based files
Returns the MatchObject if a match is made
""" Regular Expression match for date based files
Returns the MatchObject if a match is made
"""
x = 0
if matcher:

View File

@@ -273,7 +273,6 @@ class URLGrabber(Thread):
nzo_info=nzo_info,
url=future_nzo.url,
keep=False,
password=future_nzo.password,
nzo_id=future_nzo.nzo_id,
)
# -2==Error/retry, -1==Error, 0==OK, 1==Empty
@@ -299,11 +298,10 @@ class URLGrabber(Thread):
logging.error(T("URLGRABBER CRASHED"), exc_info=True)
logging.debug("URLGRABBER Traceback: ", exc_info=True)
@staticmethod
def fail_to_history(nzo, url, msg="", content=False):
"""Create History entry for failed URL Fetch
msg: message to be logged
content: report in history that cause is a bad NZB file
def fail_to_history(self, nzo, url, msg="", content=False):
""" Create History entry for failed URL Fetch
msg: message to be logged
content: report in history that cause is a bad NZB file
"""
# Remove the "Trying to fetch" part
if url:
@@ -358,8 +356,8 @@ def _build_request(url):
def _analyse(fetch_request, future_nzo):
"""Analyze response of indexer
returns fetch_request|None, error-message|None, retry, wait-seconds, data
""" Analyze response of indexer
returns fetch_request|None, error-message|None, retry, wait-seconds, data
"""
data = None
if not fetch_request or fetch_request.code != 200:

View File

@@ -36,8 +36,8 @@ def reg_info(user):
def get_connection_info(user=True):
"""Return URL of the API running SABnzbd instance
'user' == True will first try user's registry, otherwise system is used
""" Return URL of the API running SABnzbd instance
'user' == True will first try user's registry, otherwise system is used
"""
section, keypath = reg_info(user)
url = None

View File

@@ -17,8 +17,8 @@ from sabnzbd.getipaddress import localipv4
def generate_key(key_size=2048, output_file="key.pem"):
"""Generate the private-key file for the self-signed certificate
Ported from cryptography docs/x509/tutorial.rst (set with no encryption)
""" Generate the private-key file for the self-signed certificate
Ported from cryptography docs/x509/tutorial.rst (set with no encryption)
"""
# Generate our key
private_key = rsa.generate_private_key(public_exponent=65537, key_size=key_size, backend=default_backend())
@@ -38,8 +38,8 @@ def generate_key(key_size=2048, output_file="key.pem"):
def generate_local_cert(private_key, days_valid=3560, output_file="cert.cert", LN="SABnzbd", ON="SABnzbd"):
"""Generate a certificate, using basic information.
Ported from cryptography docs/x509/tutorial.rst
""" Generate a certificate, using basic information.
Ported from cryptography docs/x509/tutorial.rst
"""
# Various details about who we are. For a self-signed certificate the
# subject and issuer are always the same.

View File

@@ -18,9 +18,9 @@ def getcmdoutput(cmd):
def isFAT(check_dir):
"""Check if "check_dir" is on FAT. FAT considered harmful (for big files)
Works for Linux, Windows, MacOS
NB: On Windows, full path with drive letter is needed!
""" Check if "check_dir" is on FAT. FAT considered harmful (for big files)
Works for Linux, Windows, MacOS
NB: On Windows, full path with drive letter is needed!
"""
if not (os.path.isdir(check_dir) or os.path.isfile(check_dir)):
# Not a dir, not a file ... so not FAT:
@@ -71,12 +71,12 @@ def isFAT(check_dir):
# MacOS formerly known as OSX
"""
MacOS needs a two-step approach:
# First: directory => device
server:~ sander$ df /Volumes/CARTUNES/Tuna/
Filesystem 512-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk9s1 120815744 108840000 11975744 91% 0 0 100% /Volumes/CARTUNES
# Then: device => filesystem type
server:~ sander$ mount | grep /dev/disk9s1
/dev/disk9s1 on /Volumes/CARTUNES (msdos, local, nodev, nosuid, noowners)

View File

@@ -9,10 +9,10 @@ _DUMP_DATA = os.urandom(_DUMP_DATA_SIZE)
def diskspeedmeasure(dirname):
"""Returns writing speed to dirname in MB/s
method: keep writing a file, until 1 second is passed.
Then divide bytes written by time passed
In case of problems (ie non-writable dir or file), return None
""" Returns writing speed to dirname in MB/s
method: keep writing a file, until 1 second is passed.
Then divide bytes written by time passed
In case of problems (ie non-writable dir or file), return None
"""
maxtime = 1.0 # sec
total_written = 0

View File

@@ -56,8 +56,8 @@ _JUNKFOLDERS = (
def get_win_drives():
"""Return list of detected drives, adapted from:
http://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python/827490
""" Return list of detected drives, adapted from:
http://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python/827490
"""
assert NT
drives = []
@@ -70,9 +70,9 @@ def get_win_drives():
def folders_at_path(path, include_parent=False, show_hidden=False):
"""Returns a list of dictionaries with the folders contained at the given path
Give the empty string as the path to list the contents of the root path
under Unix this means "/", on Windows this will be a list of drive letters)
""" Returns a list of dictionaries with the folders contained at the given path
Give the empty string as the path to list the contents of the root path
under Unix this means "/", on Windows this will be a list of drive letters)
"""
if path == "":
if NT:

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