mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-06 06:28:45 -05:00
Compare commits
52 Commits
3.1.0Beta2
...
3.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
971e4fc909 | ||
|
|
51cc765949 | ||
|
|
19c6a4fffa | ||
|
|
105ac32d2f | ||
|
|
57550675d2 | ||
|
|
e674abc5c0 | ||
|
|
f965c96f51 | ||
|
|
c76b8ed9e0 | ||
|
|
4fbd0d8a7b | ||
|
|
2186c0fff6 | ||
|
|
1adca9a9c1 | ||
|
|
9408353f2b | ||
|
|
84f4d453d2 | ||
|
|
d10209f2a1 | ||
|
|
3ae149c72f | ||
|
|
47385acc3b | ||
|
|
814eeaa900 | ||
|
|
5f2ea13aad | ||
|
|
41ca217931 | ||
|
|
b57d36e8dd | ||
|
|
9a4be70734 | ||
|
|
a8443595a6 | ||
|
|
fd0a70ac58 | ||
|
|
8a8685c968 | ||
|
|
9e6cb8da8e | ||
|
|
054ec54d51 | ||
|
|
272ce773cb | ||
|
|
050b925f7b | ||
|
|
0087940898 | ||
|
|
e323c014f9 | ||
|
|
cc465c7554 | ||
|
|
14cb37564f | ||
|
|
094db56c3b | ||
|
|
aabb709b8b | ||
|
|
0833dd2db9 | ||
|
|
cd3f912be4 | ||
|
|
665c516db6 | ||
|
|
b670da9fa0 | ||
|
|
80bee9bffe | ||
|
|
d85a70e8ad | ||
|
|
8f21533e76 | ||
|
|
89996482a1 | ||
|
|
03c10dce91 | ||
|
|
bd5331be05 | ||
|
|
46e1645289 | ||
|
|
4ce3965747 | ||
|
|
9d4af19db3 | ||
|
|
48e034f4be | ||
|
|
f8959baa2f | ||
|
|
8ed5997eae | ||
|
|
daf9f50ac8 | ||
|
|
6b11013c1a |
33
.github/workflows/translations.yml
vendored
33
.github/workflows/translations.yml
vendored
@@ -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>
|
||||
@@ -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
|
||||
|
||||
|
||||
24
.tx/config
24
.tx/config
@@ -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
16
ABOUT.txt
Normal 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"
|
||||
@@ -1,4 +1,4 @@
|
||||
SABnzbd 3.1.0
|
||||
SABnzbd 3.0.0
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
0) LICENSE
|
||||
|
||||
@@ -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.
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -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
|
||||
|
||||
100
README.mkd
100
README.mkd
@@ -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
|
||||
|
||||
60
SABnzbd.py
60
SABnzbd.py
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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#-->
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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#-->
|
||||
|
||||
@@ -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"#-->
|
||||
|
||||
<%
|
||||
|
||||
@@ -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"#-->
|
||||
|
||||
<!--
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 ""#--> />
|
||||
|
||||
@@ -439,7 +439,7 @@
|
||||
<button type="button" class="close" data-dismiss="modal">×</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>
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
BIN
osx/unrar/unrar
BIN
osx/unrar/unrar
Binary file not shown.
@@ -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"
|
||||
|
||||
114
po/email/cs.po
114
po/email/cs.po
@@ -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 ""
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
5055
po/main/cs.po
5055
po/main/cs.po
File diff suppressed because it is too large
Load Diff
124
po/main/da.po
124
po/main/da.po
@@ -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"
|
||||
|
||||
125
po/main/de.po
125
po/main/de.po
@@ -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"
|
||||
|
||||
375
po/main/es.po
375
po/main/es.po
File diff suppressed because it is too large
Load Diff
116
po/main/fi.po
116
po/main/fi.po
@@ -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"
|
||||
|
||||
138
po/main/fr.po
138
po/main/fr.po
@@ -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 d’exé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 d’exé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"
|
||||
|
||||
120
po/main/he.po
120
po/main/he.po
@@ -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 וידוא אישור"
|
||||
|
||||
116
po/main/nb.po
116
po/main/nb.po
@@ -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 ""
|
||||
|
||||
133
po/main/nl.po
133
po/main/nl.po
@@ -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"
|
||||
|
||||
116
po/main/pl.po
116
po/main/pl.po
@@ -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 ""
|
||||
|
||||
116
po/main/pt_BR.po
116
po/main/pt_BR.po
@@ -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 ""
|
||||
|
||||
116
po/main/ro.po
116
po/main/ro.po
@@ -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 ""
|
||||
|
||||
110
po/main/ru.po
110
po/main/ru.po
@@ -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 ""
|
||||
|
||||
116
po/main/sr.po
116
po/main/sr.po
@@ -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 ""
|
||||
|
||||
115
po/main/sv.po
115
po/main/sv.po
@@ -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 ""
|
||||
|
||||
120
po/main/zh_CN.po
120
po/main/zh_CN.po
@@ -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 证书验证"
|
||||
|
||||
@@ -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 ""
|
||||
@@ -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"
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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] == ">":
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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")
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
189
sabnzbd/misc.py
189
sabnzbd/misc.py
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user