mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-06 06:28:45 -05:00
Compare commits
259 Commits
4.0.0Alpha
...
3.7.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
479daf0e76 | ||
|
|
bf0fbb7b10 | ||
|
|
d3c91f1585 | ||
|
|
ca165b328a | ||
|
|
fa2ffeea92 | ||
|
|
0d00965ac3 | ||
|
|
7d7bec1f80 | ||
|
|
b6fd915365 | ||
|
|
fecae72267 | ||
|
|
7bffd91e3f | ||
|
|
f859521a7e | ||
|
|
a869386fac | ||
|
|
8bc7885b7a | ||
|
|
78be46738d | ||
|
|
6fce73855c | ||
|
|
fa844a6223 | ||
|
|
906379dd09 | ||
|
|
37cded612f | ||
|
|
73e8fade61 | ||
|
|
758cc7afab | ||
|
|
d74b7b06d2 | ||
|
|
39009f2f71 | ||
|
|
9fdc1c6813 | ||
|
|
c5568fe830 | ||
|
|
bad81f84b9 | ||
|
|
2ac08dd0e6 | ||
|
|
408ffc4539 | ||
|
|
eb958327c5 | ||
|
|
e157d77a1e | ||
|
|
e961c9ea8f | ||
|
|
258c4f769d | ||
|
|
b31fedd857 | ||
|
|
eafe69500b | ||
|
|
ae09990c43 | ||
|
|
cf54b65c32 | ||
|
|
7974421fa1 | ||
|
|
847a098d4e | ||
|
|
eb4de0ae0f | ||
|
|
bca9f3b753 | ||
|
|
cad8a9a5d3 | ||
|
|
f5f36d21e8 | ||
|
|
c51435c114 | ||
|
|
2a7f1780b4 | ||
|
|
98a44e40fb | ||
|
|
65cf6fa9a1 | ||
|
|
b2e32d1720 | ||
|
|
f0bfedbe8e | ||
|
|
fd4e059c13 | ||
|
|
a53575e154 | ||
|
|
4a73484603 | ||
|
|
03b380f90b | ||
|
|
a2bd3b2dfe | ||
|
|
56fe140ebf | ||
|
|
4fafcce740 | ||
|
|
02352c4ae6 | ||
|
|
4b74aab335 | ||
|
|
2d67ac189d | ||
|
|
8ece62e23d | ||
|
|
56c2bdd77d | ||
|
|
1f555f1930 | ||
|
|
8496432c14 | ||
|
|
1672ffa670 | ||
|
|
6aab199f12 | ||
|
|
46d0c379a4 | ||
|
|
99240f145a | ||
|
|
3c9079d73c | ||
|
|
0eb98b9a6c | ||
|
|
76bfd98b77 | ||
|
|
3348640c88 | ||
|
|
d81c64fd2b | ||
|
|
8b4c919617 | ||
|
|
76c58953df | ||
|
|
4ddc5caa49 | ||
|
|
694663bd95 | ||
|
|
62aba5844e | ||
|
|
d0d60cef05 | ||
|
|
3d293fdcb0 | ||
|
|
96e9528046 | ||
|
|
4ea24b3203 | ||
|
|
a756eea25a | ||
|
|
210020e489 | ||
|
|
e586ead024 | ||
|
|
14c80bf1dc | ||
|
|
bdd56e794a | ||
|
|
a544548934 | ||
|
|
e06c1d61fb | ||
|
|
600c5209c6 | ||
|
|
bee90366ee | ||
|
|
e9bc4e9417 | ||
|
|
f01ff15761 | ||
|
|
356ada159d | ||
|
|
cc831e16d8 | ||
|
|
b8dc46ad01 | ||
|
|
d8ab19087d | ||
|
|
ec8a79eedd | ||
|
|
f1e2a8e9d8 | ||
|
|
4042a5fe5d | ||
|
|
a4752751ed | ||
|
|
e23ecf46d1 | ||
|
|
70a8c597a6 | ||
|
|
fa639bdb53 | ||
|
|
233bdd5b1d | ||
|
|
a0ab6d35c7 | ||
|
|
bd29680ce7 | ||
|
|
7139e92554 | ||
|
|
897df53466 | ||
|
|
58281711f6 | ||
|
|
b524383aa3 | ||
|
|
75a16e3588 | ||
|
|
1453032ad6 | ||
|
|
824ab4afad | ||
|
|
73dd41c67f | ||
|
|
59ee77355d | ||
|
|
5c758773ad | ||
|
|
46de49df06 | ||
|
|
d1c54a9a74 | ||
|
|
e7527c45cd | ||
|
|
7d5207aa67 | ||
|
|
654302e691 | ||
|
|
ee673b57fd | ||
|
|
2be374b841 | ||
|
|
906e1eda89 | ||
|
|
ece02cc4fa | ||
|
|
876ad60ddf | ||
|
|
862da354ac | ||
|
|
8fd477b979 | ||
|
|
2d7005655c | ||
|
|
7322f8348a | ||
|
|
e3e3a12e73 | ||
|
|
77cdd057a4 | ||
|
|
e8206fbdd9 | ||
|
|
589f15a77b | ||
|
|
7bb443678a | ||
|
|
6390415101 | ||
|
|
4abf192e11 | ||
|
|
1fed37f9da | ||
|
|
a9d86a7447 | ||
|
|
2abe4c3cef | ||
|
|
0542c25003 | ||
|
|
1b8ee4e290 | ||
|
|
51128cba55 | ||
|
|
3612432581 | ||
|
|
deca000a1b | ||
|
|
39cccb5653 | ||
|
|
f6838dc985 | ||
|
|
8cd4d92395 | ||
|
|
3bf9906f45 | ||
|
|
9f7daf96ef | ||
|
|
67de4df155 | ||
|
|
bc51a4bd1c | ||
|
|
bb54616018 | ||
|
|
6bcff5e014 | ||
|
|
8970a03a9a | ||
|
|
3ad717ca35 | ||
|
|
b14f72c67a | ||
|
|
45d036804f | ||
|
|
8f606db233 | ||
|
|
3766ba5402 | ||
|
|
e851813cef | ||
|
|
4d49ad9141 | ||
|
|
16618b3af2 | ||
|
|
0e5c0f664f | ||
|
|
7be9281431 | ||
|
|
ee0327fac1 | ||
|
|
9930de3e7f | ||
|
|
e8503e89c6 | ||
|
|
1d9ed419eb | ||
|
|
0207652e3e | ||
|
|
0f1e99c5cb | ||
|
|
f134bc7efb | ||
|
|
dcd7c7180e | ||
|
|
fbbfcd075b | ||
|
|
f42d2e4140 | ||
|
|
88882cebbc | ||
|
|
17a979675c | ||
|
|
4642850c79 | ||
|
|
e8d6eebb04 | ||
|
|
864c5160c0 | ||
|
|
99b5a00c12 | ||
|
|
85ee1f07d7 | ||
|
|
e58b4394e0 | ||
|
|
1e91a57bf1 | ||
|
|
39cee52a7e | ||
|
|
72068f939d | ||
|
|
096d0d3cad | ||
|
|
2472ab0121 | ||
|
|
00421717b8 | ||
|
|
ae96d93f94 | ||
|
|
8522c40c8f | ||
|
|
23f86e95f1 | ||
|
|
eed2045189 | ||
|
|
217785bf0f | ||
|
|
6aef50dc5d | ||
|
|
16b6e3caa7 | ||
|
|
3de4c99a8a | ||
|
|
980aa19a75 | ||
|
|
fb4b57e056 | ||
|
|
03638365ea | ||
|
|
157cb1c83d | ||
|
|
e51f11c2b1 | ||
|
|
1ad0961dd8 | ||
|
|
46ff7dd4e2 | ||
|
|
8b067df914 | ||
|
|
ef43b13272 | ||
|
|
e8e9974224 | ||
|
|
feebbb9f04 | ||
|
|
bc4f06dd1d | ||
|
|
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 |
9
.github/workflows/build_release.yml
vendored
9
.github/workflows/build_release.yml
vendored
@@ -87,7 +87,7 @@ jobs:
|
||||
# We need the official Python, because the GA ones only support newer macOS versions
|
||||
# The deployment target is picked up by the Python build tools automatically
|
||||
# If updated, make sure to also set LSMinimumSystemVersion in SABnzbd.spec
|
||||
PYTHON_VERSION: "3.11.2"
|
||||
PYTHON_VERSION: "3.11.0"
|
||||
MACOSX_DEPLOYMENT_TARGET: "10.9"
|
||||
# We need to force compile for universal2 support
|
||||
CFLAGS: -arch x86_64 -arch arm64
|
||||
@@ -123,6 +123,7 @@ jobs:
|
||||
# https://github.com/pyca/cryptography/issues/5918
|
||||
# 2. We need to build the PyInstaller bootloader:
|
||||
# https://github.com/pyinstaller/pyinstaller/issues/6235
|
||||
# 3. TEMPORARY: Add aarch64 for orjson universal2 build, until they provide a wheel
|
||||
if: steps.cache-virtualenv.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
python3 --version
|
||||
@@ -131,9 +132,11 @@ jobs:
|
||||
pip3 install --upgrade -r requirements.txt --no-binary cffi
|
||||
|
||||
pip3 uninstall cryptography -y
|
||||
pip3 download -r builder/osx/requirements.txt --platform macosx_10_12_universal2 --only-binary :all: --no-deps --dest .
|
||||
pip3 download -r builder/osx/requirements.txt --platform macosx_10_10_universal2 --only-binary :all: --no-deps --dest .
|
||||
pip3 install -r builder/osx/requirements.txt --no-cache-dir --no-index --find-links .
|
||||
|
||||
|
||||
rustup target add aarch64-apple-darwin
|
||||
|
||||
PYINSTALLER_COMPILE_BOOTLOADER=1 pip3 install --upgrade -r builder/requirements.txt --no-binary pyinstaller
|
||||
- name: Import macOS codesign certificates
|
||||
# Taken from https://github.com/Apple-Actions/import-codesign-certs/pull/27 (comments)
|
||||
|
||||
7
.github/workflows/integration_testing.yml
vendored
7
.github/workflows/integration_testing.yml
vendored
@@ -20,7 +20,7 @@ jobs:
|
||||
builder/SABnzbd.spec
|
||||
tests
|
||||
--line-length=120
|
||||
--target-version=py38
|
||||
--target-version=py37
|
||||
--check
|
||||
--diff
|
||||
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.8", "3.9", "3.10", "3.11"]
|
||||
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11"]
|
||||
os: [ubuntu-20.04]
|
||||
include:
|
||||
- name: macOS
|
||||
@@ -39,7 +39,8 @@ jobs:
|
||||
python-version: "3.11"
|
||||
- name: Windows
|
||||
os: windows-latest
|
||||
python-version: "3.11"
|
||||
# lxml is not yet available for Python 3.11, so CI is stuck on 3.10 for now
|
||||
python-version: "3.10"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
2
.github/workflows/translations.yml
vendored
2
.github/workflows/translations.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
if: env.TX_TOKEN
|
||||
run: |
|
||||
curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
|
||||
./tx push --translation --source
|
||||
./tx push --source
|
||||
./tx pull --all --force
|
||||
- name: Compile translations to validate them
|
||||
run: |
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
(c) Copyright 2007-2023 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
(c) Copyright 2007-2022 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
The SABnzbd-team is:
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
0) LICENSE
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
(c) Copyright 2007-2023 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
(c) Copyright 2007-2022 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
@@ -52,7 +52,7 @@ Specific guides to install from source are available for Windows and macOS:
|
||||
https://sabnzbd.org/wiki/installation/install-macos
|
||||
https://sabnzbd.org/wiki/installation/install-from-source-windows
|
||||
|
||||
Only Python 3.8 and above is supported.
|
||||
Only Python 3.7 and above is supported.
|
||||
|
||||
On Linux systems you need to install:
|
||||
par2 unrar unzip python3-setuptools python3-pip
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
(c) Copyright 2007-2023 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
(c) Copyright 2007-2022 by "The SABnzbd-team" <team@sabnzbd.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
||||
4
PKG-INFO
4
PKG-INFO
@@ -1,7 +1,7 @@
|
||||
Metadata-Version: 1.0
|
||||
Name: SABnzbd
|
||||
Version: 4.0.0Alpha2
|
||||
Summary: SABnzbd-4.0.0Alpha2
|
||||
Version: 3.7.1
|
||||
Summary: SABnzbd-3.7.1
|
||||
Home-page: https://sabnzbd.org
|
||||
Author: The SABnzbd Team
|
||||
Author-email: team@sabnzbd.org
|
||||
|
||||
@@ -16,7 +16,7 @@ If you want to know more you can head over to our website: https://sabnzbd.org.
|
||||
|
||||
SABnzbd has a few dependencies you'll need before you can get running. If you've previously run SABnzbd from one of the various Linux packages, then you likely already have all the needed dependencies. If not, here's what you're looking for:
|
||||
|
||||
- `python` (Python 3.8 and above, often called `python3`)
|
||||
- `python` (Python 3.7 and above, often called `python3`)
|
||||
- Python modules listed in `requirements.txt`. Install with `python3 -m pip install -r requirements.txt -U`
|
||||
- `par2` (Multi-threaded par2 installation guide can be found [here](https://sabnzbd.org/wiki/installation/multicore-par2))
|
||||
- `unrar` (make sure you get the "official" non-free version of unrar)
|
||||
|
||||
68
README.mkd
68
README.mkd
@@ -1,30 +1,50 @@
|
||||
Release Notes - SABnzbd 4.0.0 Alpha 2
|
||||
Release Notes - SABnzbd 3.7.1
|
||||
=========================================================
|
||||
|
||||
## Changes since 4.0.0 Alpha 1
|
||||
- There are now multiple settings that can tweak performance, see:
|
||||
https://github.com/sabnzbd/sabnzbd/discussions/2474
|
||||
We are trying to find the most optimal default settings, so you
|
||||
can help us by letting us know the results on your system!
|
||||
## Bugfixes and changes since 3.7.0
|
||||
- Minor improvements in download performance.
|
||||
- Scripts set `On queue finish` are no longer persistent by default.
|
||||
- Improved `Test Server` to handle more failure cases.
|
||||
- Priority list in `Add NZB`-window was missing `Paused` priority.
|
||||
- Keyboard shortcuts did not work if not in Tabbed-mode.
|
||||
- Keyboard shortcut `S` did not reload status information.
|
||||
- In `history` API-call the `stage_log` could be empty.
|
||||
- Using the `-` character broke the queue/history search.
|
||||
- Improved detection and handling of stuck jobs.
|
||||
|
||||
## Changes since 3.7.2
|
||||
- In this major update we replaced a core part of Python's SSL handling
|
||||
with our own improved version. This results in large performance increases
|
||||
when downloading from news servers with SSL enabled.
|
||||
In addition, the general connection handling was overhauled, resulting in
|
||||
performance improvements for all news servers.
|
||||
Special thanks to: mnightingale, puzzledsab and animetosho!
|
||||
- When adding a new news server, SSL is enabled by default.
|
||||
- File assembly performance significantly improved by relying on the
|
||||
CRC32 instead of the MD5 to perform QuickCheck of files.
|
||||
- Slowdown more gracefully when the cache fills up.
|
||||
- HTTPS files are included in the `Backup`.
|
||||
- Improved `Watched Folder` scanning and processing.
|
||||
- Dropped support for Python 3.7.
|
||||
## Changes since 3.6.1
|
||||
- The queue and history can be filtered using keywords:
|
||||
`cat` and `priority`. For example: `show name cat:tv`.
|
||||
- Use shortcut `shift + arrow-key` to navigate the queue/history pages.
|
||||
- The backup is now created in a local folder for security.
|
||||
- Recurring backups can be configured using the scheduler.
|
||||
- Improvements to Deobfuscate Final Filenames.
|
||||
- RSS overview shows the rule that accepted the job.
|
||||
- Added option to sort the queue by `% downloaded`.
|
||||
- Added option to replace underscores with dots in folder names.
|
||||
- SABnzbd Host input will be validated before being applied.
|
||||
- Moved system load information from the main page to the Status window.
|
||||
- Console logging is now written to `stdout` instead of `stderr`.
|
||||
- Removed Special settings `enable_meta`, `disable_key`,
|
||||
`replace_illegal`, `osx_speed` and `show_sysload`.
|
||||
- Merged Special settings `win_menu` and `osx_menu` into `tray_icon`.
|
||||
- macOS/Windows: Use Python 3.11, slightly boosting overall performance.
|
||||
- macOS/Windows: Updated UnRar to 6.12.
|
||||
- Windows: Updated MultiPar to 1.3.2.5.
|
||||
|
||||
# Bugfixes since 3.7.2
|
||||
- Restore applying `History Retention` setting at startup.
|
||||
- Windows: Not all invalid characters were removed from filenames.
|
||||
# API changes since 3.6.1
|
||||
- Minor improvements in API performance.
|
||||
- Removed fields `scripts` and `categories` from `queue` API call.
|
||||
- Moved `loadavg` from `queue` to `status` API call.
|
||||
|
||||
# Bugfixes since 3.6.1
|
||||
- Free Space Detection was too strict when using Direct Unpack.
|
||||
- File uploads with special characters would be parsed incorrectly.
|
||||
- Passwords from NZB meta-data were tried multiple times.
|
||||
- Passwords were not always supplied to the pre-queue script.
|
||||
- RSS-feed names were not sanitized when renamed.
|
||||
- Make sure short-dates are detected as `YY-MM-DD` in Sorting.
|
||||
- Show the custom job name in History when the NZB could not be fetched.
|
||||
|
||||
## Upgrade notices
|
||||
- The download statistics file `totals10.sab` is updated in 3.2.x
|
||||
@@ -41,4 +61,4 @@ Release Notes - SABnzbd 4.0.0 Alpha 2
|
||||
that automatically verify, repair, extract and clean up posts downloaded
|
||||
from Usenet.
|
||||
|
||||
(c) Copyright 2007-2023 by "The SABnzbd-team" \<team@sabnzbd.org\>
|
||||
(c) Copyright 2007-2022 by "The SABnzbd-team" \<team@sabnzbd.org\>
|
||||
|
||||
59
SABnzbd.py
59
SABnzbd.py
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
import sys
|
||||
|
||||
if sys.hexversion < 0x03080000:
|
||||
print("Sorry, requires Python 3.8 or above")
|
||||
if sys.hexversion < 0x03070000:
|
||||
print("Sorry, requires Python 3.7 or above")
|
||||
print("You can read more at: https://sabnzbd.org/wiki/installation/install-off-modules")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -40,7 +40,6 @@ import gc
|
||||
from typing import List, Dict, Any
|
||||
|
||||
try:
|
||||
import sabctools
|
||||
import Cheetah
|
||||
import feedparser
|
||||
import configobj
|
||||
@@ -77,7 +76,6 @@ from sabnzbd.constants import (
|
||||
DEF_LOG_FILE,
|
||||
DEF_STD_CONFIG,
|
||||
DEF_LOG_CHERRY,
|
||||
CONFIG_BACKUP_HTTPS,
|
||||
)
|
||||
import sabnzbd.newsunpack
|
||||
from sabnzbd.misc import (
|
||||
@@ -242,7 +240,7 @@ def print_version():
|
||||
"""
|
||||
%s-%s
|
||||
|
||||
Copyright (C) 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
Copyright (C) 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
SABnzbd comes with ABSOLUTELY NO WARRANTY.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions. It is licensed under the
|
||||
@@ -400,13 +398,15 @@ def get_user_profile_paths():
|
||||
return
|
||||
|
||||
elif sabnzbd.MACOS:
|
||||
if home := os.environ.get("HOME"):
|
||||
home = os.environ.get("HOME")
|
||||
if home:
|
||||
sabnzbd.DIR_LCLDATA = "%s/Library/Application Support/SABnzbd" % home
|
||||
sabnzbd.DIR_HOME = home
|
||||
return
|
||||
else:
|
||||
# Unix/Linux
|
||||
if home := os.environ.get("HOME"):
|
||||
home = os.environ.get("HOME")
|
||||
if home:
|
||||
sabnzbd.DIR_LCLDATA = "%s/.%s" % (home, DEF_WORKDIR)
|
||||
sabnzbd.DIR_HOME = home
|
||||
return
|
||||
@@ -418,26 +418,25 @@ def get_user_profile_paths():
|
||||
|
||||
def print_modules():
|
||||
"""Log all detected optional or external modules"""
|
||||
if sabnzbd.decoder.SABCTOOLS_ENABLED:
|
||||
# Yes, we have SABCTools, and it's the correct version, so it's enabled
|
||||
logging.info("SABCTools module (v%s)... found!", sabnzbd.decoder.SABCTOOLS_VERSION)
|
||||
logging.info("SABCTools module is using SIMD set: %s", sabnzbd.decoder.SABCTOOLS_SIMD)
|
||||
logging.info("SABCTools module is linked to OpenSSL: %s", sabnzbd.decoder.SABCTOOLS_OPENSSL_LINKED)
|
||||
|
||||
# Check if we managed to link, warning for now
|
||||
if not sabnzbd.decoder.SABCTOOLS_OPENSSL_LINKED:
|
||||
logging.warning(
|
||||
"Could not link to OpenSSL library, please report here: "
|
||||
"https://github.com/sabnzbd/sabnzbd/issues/2421"
|
||||
)
|
||||
if sabnzbd.decoder.SABYENC_ENABLED:
|
||||
# Yes, we have SABYenc, and it's the correct version, so it's enabled
|
||||
logging.info("SABYenc module (v%s)... found!", sabnzbd.decoder.SABYENC_VERSION)
|
||||
logging.info("SABYenc module is using SIMD set: %s", sabnzbd.decoder.SABYENC_SIMD)
|
||||
else:
|
||||
# Wrong SABCTools version, if it was fully missing it would fail to start due to check at the very top
|
||||
logging.error(
|
||||
T("SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"),
|
||||
sabnzbd.decoder.SABCTOOLS_VERSION,
|
||||
sabnzbd.constants.SABCTOOLS_VERSION_REQUIRED,
|
||||
)
|
||||
|
||||
# Something wrong with SABYenc, so let's determine and print what:
|
||||
if sabnzbd.decoder.SABYENC_VERSION:
|
||||
# We have a VERSION, thus a SABYenc module, but it's not the correct version
|
||||
logging.error(
|
||||
T("SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"),
|
||||
sabnzbd.decoder.SABYENC_VERSION,
|
||||
sabnzbd.constants.SABYENC_VERSION_REQUIRED,
|
||||
)
|
||||
else:
|
||||
# No SABYenc module at all
|
||||
logging.error(
|
||||
T("SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"),
|
||||
sabnzbd.constants.SABYENC_VERSION_REQUIRED,
|
||||
)
|
||||
# Do not allow downloading
|
||||
sabnzbd.NO_DOWNLOADING = True
|
||||
|
||||
@@ -1445,12 +1444,6 @@ def main():
|
||||
logging.error(T("Failed to start web-interface: "), exc_info=True)
|
||||
abort_and_show_error(browserhost, cherryport)
|
||||
|
||||
# Create a record of the active cert/key/chain files, for use with config.create_config_backup()
|
||||
if enable_https:
|
||||
for setting in CONFIG_BACKUP_HTTPS.values():
|
||||
if full_path := getattr(sabnzbd.cfg, setting).get_path():
|
||||
sabnzbd.CONFIG_BACKUP_HTTPS_OK.append(full_path)
|
||||
|
||||
if sabnzbd.WIN32:
|
||||
if enable_https:
|
||||
mode = "s"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# Special requirements for macOS universal2 binary release
|
||||
# This way dependabot can auto-update them
|
||||
cryptography==39.0.1
|
||||
cryptography==38.0.4
|
||||
@@ -1,22 +1,22 @@
|
||||
# Basic build requirements
|
||||
# Note that not all sub-dependencies are listed, but only ones we know could cause trouble
|
||||
pyinstaller==5.8.0
|
||||
pyinstaller-hooks-contrib==2022.15
|
||||
pyinstaller==5.7.0
|
||||
pyinstaller-hooks-contrib==2022.14
|
||||
altgraph==0.17.3
|
||||
wrapt==1.14.1
|
||||
setuptools==67.2.0
|
||||
pkginfo==1.9.6
|
||||
setuptools==65.6.3
|
||||
pkginfo==1.9.2
|
||||
PyGithub==1.57
|
||||
charset-normalizer==3.0.1
|
||||
certifi
|
||||
|
||||
# orjson does not support 32bit Windows, exclude it based on Python-version
|
||||
# This way we also test ujson on Python 3.8 in the CI-tests
|
||||
orjson==3.8.6; python_version > '3.8'
|
||||
# This way we also test ujson on Python 3.7 and 3.8 in the CI-tests
|
||||
orjson==3.8.3; python_version > '3.8'
|
||||
|
||||
# For the macOS build
|
||||
dmgbuild==1.6.0; sys_platform == 'darwin'
|
||||
mac-alias==2.2.2; sys_platform == 'darwin'
|
||||
mac-alias==2.2.1; sys_platform == 'darwin'
|
||||
macholib==1.16.2; sys_platform == 'darwin'
|
||||
ds-store==1.3.1; sys_platform == 'darwin'
|
||||
PyNaCl==1.5.0; sys_platform == 'darwin'
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<!--#if not $windows#-->
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="show_hidden_folders"> <span>$T('hiddenFolders')</span>
|
||||
<input type="checkbox" id="show_hidden_folders"> <span>$T('systemFolders')</span>
|
||||
</label>
|
||||
</div>
|
||||
<!--#end if#-->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Config"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/configure"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/configure"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<!--#from sabnzbd.encoding import CODEPAGE#-->
|
||||
@@ -54,12 +54,12 @@
|
||||
</td>
|
||||
</tr>
|
||||
<!--#end if#-->
|
||||
<!--#if not $have_sabctools#-->
|
||||
<!--#if not $have_sabyenc#-->
|
||||
<tr>
|
||||
<th scope="row">SABCTools:</th>
|
||||
<th scope="row">SABYenc:</th>
|
||||
<td>
|
||||
<span class="label label-danger">$T('notAvailable')</span>
|
||||
<a href="$helpuri$help_uri#no_sabctools" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
|
||||
<a href="$helpuri$help_uri#no_sabyenc" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
|
||||
</td>
|
||||
</tr>
|
||||
<!--#end if#-->
|
||||
@@ -124,7 +124,7 @@
|
||||
|
||||
<div class="colmask">
|
||||
<div class="padding alt">
|
||||
<h5 class="copyright">Copyright © 2007-2023 The SABnzbd Team <<a href="mailto:team@sabnzbd.org">team@sabnzbd.org</a>></h5>
|
||||
<h5 class="copyright">Copyright © 2007-2022 The SABnzbd Team <<a href="mailto:team@sabnzbd.org">team@sabnzbd.org</a>></h5>
|
||||
<p class="copyright"><small>$T('yourRights')</small></p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Categories"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/categories"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/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/4.0/folders"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/folders"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="General"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/general"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/general"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
@@ -375,7 +375,7 @@
|
||||
})
|
||||
|
||||
// Only allow re-generate if default certs
|
||||
if(\$('#https_cert').val() != '$def_https_cert_file') {
|
||||
if(\$('#https_cert').val() != 'server.cert') {
|
||||
\$('.generate_cert').attr('disabled', 'disabled')
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Email"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/notifications"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/notifications"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<!--#def show_notify_checkboxes($section_label)#-->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="RSS"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/rss"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/rss"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
<!--#import html#-->
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Scheduling"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/scheduling"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/scheduling"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<%
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Servers"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/servers"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/servers"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<!--#import json#-->
|
||||
@@ -51,11 +51,11 @@
|
||||
</div>
|
||||
<div class="field-pair advanced-settings">
|
||||
<label class="config" for="port">$T('srv-port')</label>
|
||||
<input type="number" name="port" id="port" size="8" value="563" min="0" />
|
||||
<input type="number" name="port" id="port" size="8" value="119" min="0" />
|
||||
</div>
|
||||
<div class="field-pair">
|
||||
<label class="config" for="ssl">$T('srv-ssl')</label>
|
||||
<input type="checkbox" name="ssl" id="ssl" value="1" checked />
|
||||
<input type="checkbox" name="ssl" id="ssl" value="1" />
|
||||
<span class="desc">$T('explain-ssl')</span>
|
||||
</div>
|
||||
<!-- Tricks to avoid browser auto-fill, fixed on-submit with javascript -->
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Sorting"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/sorting"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/sorting"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Special"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/special"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/special"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<!--#set global $pane="Switches"#-->
|
||||
<!--#set global $help_uri="configuration/4.0/switches"#-->
|
||||
<!--#set global $help_uri="configuration/3.7/switches"#-->
|
||||
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
|
||||
|
||||
<div class="colmask">
|
||||
|
||||
@@ -671,11 +671,6 @@ function ViewModel() {
|
||||
}
|
||||
}
|
||||
|
||||
// default to url input when modal is shown
|
||||
$('#modal-add-nzb').on('shown.bs.modal', function() {
|
||||
$('input[name="nzbURL"]').focus();
|
||||
})
|
||||
|
||||
// From the upload or filedrop
|
||||
self.addNZBFromFile = function(files, fileindex) {
|
||||
// First file
|
||||
@@ -1339,12 +1334,6 @@ function ViewModel() {
|
||||
// And refresh now!
|
||||
self.refresh()
|
||||
|
||||
// Special options for (non) mobile
|
||||
if (isMobile) {
|
||||
// Disable accept parameter on file inputs, as it doesn't work on mobile Safari
|
||||
$("input[accept!=''][accept]").attr("accept","")
|
||||
} else {
|
||||
// Activate tooltips
|
||||
$('[data-tooltip="true"]').tooltip({ trigger: 'hover', container: 'body' })
|
||||
}
|
||||
// Activate tooltips
|
||||
if (!isMobile) $('[data-tooltip="true"]').tooltip({ trigger: 'hover', container: 'body' })
|
||||
}
|
||||
|
||||
@@ -343,61 +343,54 @@ function QueueListModel(parent) {
|
||||
var newStatus = $('.multioperations-selector input[name="multiedit-status"]:checked').val()
|
||||
|
||||
// List all the ID's
|
||||
var strIDs = '';
|
||||
var strIDs = '';
|
||||
$.each(self.multiEditItems(), function(index) {
|
||||
strIDs = strIDs + this.id + ',';
|
||||
})
|
||||
|
||||
// All non-category updates need to only happen after a category update
|
||||
function nonCatUpdates() {
|
||||
if(newScript != '') {
|
||||
callAPI({
|
||||
mode: 'change_script',
|
||||
value: strIDs,
|
||||
value2: newScript
|
||||
})
|
||||
}
|
||||
if(newPrior != '') {
|
||||
callAPI({
|
||||
mode: 'queue',
|
||||
name: 'priority',
|
||||
value: strIDs,
|
||||
value2: newPrior
|
||||
})
|
||||
}
|
||||
if(newProc != '') {
|
||||
callAPI({
|
||||
mode: 'change_opts',
|
||||
value: strIDs,
|
||||
value2: newProc
|
||||
})
|
||||
}
|
||||
if(newStatus) {
|
||||
callAPI({
|
||||
mode: 'queue',
|
||||
name: newStatus,
|
||||
value: strIDs
|
||||
})
|
||||
}
|
||||
|
||||
// Wat a little and do the refresh
|
||||
// Only if anything changed!
|
||||
if(newStatus || newProc != '' || newPrior != '' || newScript != '' || newCat != '') {
|
||||
setTimeout(parent.refresh, 100)
|
||||
}
|
||||
}
|
||||
|
||||
// What is changed?
|
||||
if(newCat != '') {
|
||||
callAPI({
|
||||
mode: 'change_cat',
|
||||
value: strIDs,
|
||||
value2: newCat
|
||||
}).then(nonCatUpdates)
|
||||
} else {
|
||||
nonCatUpdates()
|
||||
})
|
||||
}
|
||||
if(newScript != '') {
|
||||
callAPI({
|
||||
mode: 'change_script',
|
||||
value: strIDs,
|
||||
value2: newScript
|
||||
})
|
||||
}
|
||||
if(newPrior != '') {
|
||||
callAPI({
|
||||
mode: 'queue',
|
||||
name: 'priority',
|
||||
value: strIDs,
|
||||
value2: newPrior
|
||||
})
|
||||
}
|
||||
if(newProc != '') {
|
||||
callAPI({
|
||||
mode: 'change_opts',
|
||||
value: strIDs,
|
||||
value2: newProc
|
||||
})
|
||||
}
|
||||
if(newStatus) {
|
||||
callAPI({
|
||||
mode: 'queue',
|
||||
name: newStatus,
|
||||
value: strIDs
|
||||
})
|
||||
}
|
||||
|
||||
// Wat a little and do the refresh
|
||||
// Only if anything changed!
|
||||
if(newStatus || newProc != '' || newPrior != '' || newScript != '' || newCat != '') {
|
||||
setTimeout(parent.refresh, 100)
|
||||
}
|
||||
}
|
||||
|
||||
// Selete all selected
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div class="form-group">
|
||||
<label for="port" class="col-sm-4 control-label">$T('srv-port')</label>
|
||||
<div class="col-sm-8">
|
||||
<input type="number" class="form-control" name="port" id="port" value="<!--#if $port then $port else '563' #-->" />
|
||||
<input type="number" class="form-control" name="port" id="port" value="<!--#if $port then $port else '119' #-->" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright 2022-2023 The SABnzbd-Team <team@sabnzbd.org> -->
|
||||
<!-- Copyright 2022 The SABnzbd-Team <team@sabnzbd.org> -->
|
||||
<component type="desktop-application">
|
||||
<id>org.sabnzbd.sabnzbd</id>
|
||||
<metadata_license>MIT</metadata_license>
|
||||
@@ -23,26 +23,16 @@
|
||||
</categories>
|
||||
<url type="homepage">https://sabnzbd.org</url>
|
||||
<url type="bugtracker">https://github.com/sabnzbd/sabnzbd/issues</url>
|
||||
<url type="vcs-browser">https://github.com/sabnzbd/sabnzbd</url>
|
||||
<url type="translate">https://sabnzbd.org/wiki/translate</url>
|
||||
<url type="donation">https://sabnzbd.org/donate</url>
|
||||
<url type="help">https://sabnzbd.org/wiki/</url>
|
||||
<url type="faq">https://sabnzbd.org/wiki/faq</url>
|
||||
<url type="contact">https://sabnzbd.org/live-chat.html</url>
|
||||
<url type="contact">https://forums.sabnzbd.org</url>
|
||||
<launchable type="desktop-id">sabnzbd.desktop</launchable>
|
||||
<provides>
|
||||
<mediatype>application/x-nzb</mediatype>
|
||||
<mediatype>application/x-compressed-nzb</mediatype>
|
||||
</provides>
|
||||
<supports>
|
||||
<control>pointing</control>
|
||||
<control>keyboard</control>
|
||||
<control>touch</control>
|
||||
</supports>
|
||||
<recommends>
|
||||
<display_length compare="ge">small</display_length>
|
||||
<internet>always</internet>
|
||||
</recommends>
|
||||
<project_license>GPL-2.0-or-later</project_license>
|
||||
<developer_name>The SABnzbd-team</developer_name>
|
||||
<screenshots>
|
||||
|
||||
Binary file not shown.
BIN
osx/unrar/unrar
BIN
osx/unrar/unrar
Binary file not shown.
@@ -1,11 +1,11 @@
|
||||
#
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-4.0.0Alpha1\n"
|
||||
"Project-Id-Version: SABnzbd-3.8.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"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
msgid ""
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file EMAIL
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-4.0.0Alpha1\n"
|
||||
"Project-Id-Version: SABnzbd-3.8.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"
|
||||
@@ -35,7 +35,12 @@ msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -388,6 +393,7 @@ msgstr ""
|
||||
msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr ""
|
||||
@@ -411,16 +417,19 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Login from too many different IP addresses to server %s [%s] - https://sabnzbd.org/multiple-adresses"
|
||||
msgid "Probable account sharing"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -593,7 +602,7 @@ msgstr ""
|
||||
msgid "API Key incorrect, Use the api key from Config->General in your 3rd party program:"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr ""
|
||||
|
||||
@@ -2819,10 +2828,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Pavel C <quoing_transifex@mess.cz>, 2021
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\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"
|
||||
@@ -40,10 +40,16 @@ msgstr "Šablona pro web nebyla nalezena: %s, zkouším standardní šablonu"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools vypnut: Nenalezena správná verze! (Nalezena v%s, očekávána v%s)"
|
||||
"SABYenc vypnut: Nenalezena správná verze! (Nalezena v%s, očekávána v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"Modul SABYenc... nebyl nalezen! Očekávána v%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
@@ -422,6 +428,7 @@ msgstr ""
|
||||
"Musíte nastavit maximální rychlost linky předtím než začnete nastavovat "
|
||||
"limity pro přenos"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Nelze se připojit k serveru %s [%s]"
|
||||
@@ -445,19 +452,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Příliš mnoho spojení k serveru %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Příliš mnoho spojení k serveru %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Pravděpodobné sdílení účtu"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Přihlášení k serveru %s se nezdařilo [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Přihlášení k serveru %s se nezdařilo"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -639,7 +647,7 @@ msgstr ""
|
||||
"Nesprávný API klíč, použijte api klíč z Nastavení->Obecné ve vašem programu "
|
||||
"třetí strany:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Přihlášené selhalo, zkontrolujte jméno a heslo."
|
||||
|
||||
@@ -2949,10 +2957,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr ""
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\n"
|
||||
"Language-Team: Danish (https://www.transifex.com/sabnzbd/teams/111101/da/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -39,11 +39,17 @@ msgstr "Kan ikke finde webskabeloner: %s, forsøger med standardskabelon"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools deaktiveret: Der blev ikke fundet nogen korrekt version (Fandt "
|
||||
"v%s, forventede v%s)"
|
||||
"SABYenc deaktiveret: Der blev ikke fundet nogen korrekt version (Fandt v%s, "
|
||||
"forventede v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"SABYenc modul... IKKE fundet! Forventede v%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
@@ -420,6 +426,7 @@ msgstr ""
|
||||
"Du skal angive den maksimale båndbredde, før du kan angive en båndbredde "
|
||||
"begrænsning"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Kan ikke tilslutte til server %s [%s]"
|
||||
@@ -443,19 +450,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Det lykkedes ikke at initialisere %s@%s med begrundelse %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Alt for mange forbindelser til serveren %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Alt for mange forbindelser til serveren %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Sandsynligt delt konto"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Det lykkedes ikke at logge på serveren %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Det lykkedes ikke at logge på serveren %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -647,7 +655,7 @@ msgstr ""
|
||||
"Forkert API-nøgle, anvend api-nøglen fra Konfiguration->Generelt i dit "
|
||||
"tredjepartsprogram:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Godkendelse mislykkedes, kontrollere brugernavn/adgangskode."
|
||||
|
||||
@@ -3012,10 +3020,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Systemmapper"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Administrativ mappe"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# C E <githubce@eiselt.ch>, 2020
|
||||
# Nikolai Bohl <n.kay01@gmail.com>, 2020
|
||||
@@ -10,14 +10,14 @@
|
||||
# Andreas Kames, 2021
|
||||
# Simon W., 2021
|
||||
# Nils Briggen, 2022
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
# reloxx13 <reloxx@interia.pl>, 2022
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: reloxx13 <reloxx@interia.pl>, 2022\n"
|
||||
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -49,12 +49,18 @@ msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools deaktiviert: Keine korrekte Version gefunden! (Gefunden v%s, "
|
||||
"SABYenc deaktiviert: Keine korrekte Version gefunden! (Gefunden v%s, "
|
||||
"Erwartet v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"SABYenc Modul... Nicht gefunden! Erwarte v%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "par2 binary... NOT found!"
|
||||
@@ -449,6 +455,7 @@ msgstr ""
|
||||
"Bevor ein Bandbreitenlimit gesetzt werden kann, muss die maximale Bandbreite"
|
||||
" festgelegt werden"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Verbindung zum Server %s kann nicht hergestellt werden. %s"
|
||||
@@ -472,19 +479,20 @@ msgstr "Es gibt keine aktiven Server!"
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Fehler %s@%s zu initialisieren, aus folgendem Grund: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Zu viele Verbindungen zu Server %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Zu viele Verbindungen zu Server %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Möglicherweise wird das Konto geteilt"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Anmelden beim Server fehlgeschlagen. %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Anmelden beim Server fehlgeschlagen. %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -680,7 +688,7 @@ msgstr ""
|
||||
"API-Schlüssel ungültig. Bitte API-Schlüssel aus Einstellungen->Allgemein in "
|
||||
"die externe Anwendung eingeben:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr ""
|
||||
"Authentifizierung fehlgeschlagen. Überprüfen Sie Benutzername und Passwort."
|
||||
@@ -3118,10 +3126,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "System-Ordner"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Administrativer Ordner"
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Ester Molla Aragones <moarages@gmail.com>, 2020
|
||||
# 1024mb <angelb2203@gmail.com>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# 1024mb <angelb2203@gmail.com>, 2020
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\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"
|
||||
@@ -43,12 +43,19 @@ msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools deshabilitado: ¡no se ha encontrado la versión correcta! (Se ha "
|
||||
"SABYenc deshabilitado: ¡no se ha encontrado la versión correcta! (Se ha "
|
||||
"encontrado la v%s, se esperaba la v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"Módulo SABYenc... ¡NO encontrado! Se esperaba la v%s - "
|
||||
"https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "par2 binary... NOT found!"
|
||||
@@ -107,8 +114,6 @@ msgid ""
|
||||
"Current umask (%o) might deny SABnzbd access to the files and folders it "
|
||||
"creates."
|
||||
msgstr ""
|
||||
"La umask actual (%o) podría denegarle acceso a SABnzbd a los archivos y "
|
||||
"carpetas que este crea."
|
||||
|
||||
#. Warning message
|
||||
#: SABnzbd.py
|
||||
@@ -153,22 +158,22 @@ msgstr "Error grave al guardar estado"
|
||||
#. Warning message
|
||||
#: sabnzbd/__init__.py
|
||||
msgid "Restarting because of crashed postprocessor"
|
||||
msgstr "Reiniciando a causa de un posprocesador colgado"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/__init__.py
|
||||
msgid "Restarting because of crashed downloader"
|
||||
msgstr "Reiniciando debido al cuelgue del descargador"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/__init__.py
|
||||
msgid "Restarting because of crashed decoder"
|
||||
msgstr "Reiniciando a causa de un decodificador colgado"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/__init__.py
|
||||
msgid "Restarting because of crashed assembler"
|
||||
msgstr "Reiniciando debido al cuelgue del ensamblador"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/__init__.py
|
||||
@@ -441,6 +446,7 @@ msgstr ""
|
||||
"Debe establecer un ancho de banda máximo antes de poder establecer un límite"
|
||||
" de ancho de banda"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Error en inicio de conexion a servidor %s [%s]"
|
||||
@@ -464,19 +470,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Error al inicializar %s@%s con la razón: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Demasiadas conexiones con el servidor %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Demasiadas conexiones con el servidor %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Compartiendo de cuenta probable"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Registraccion fallo para servidor %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Registraccion fallo para servidor %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -669,7 +676,7 @@ msgstr ""
|
||||
"Clave de API erróneo, favor ingresar la clave correcta desde Config->General"
|
||||
" en tu aplicacion externa:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Autenticación fallida, compruebe el usuario o la contraseña."
|
||||
|
||||
@@ -3091,10 +3098,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Directorios del sistema"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Directorio de administración"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
@@ -37,10 +37,15 @@ msgstr "Web-käyttöliittymän käynnistys epäonnistui"
|
||||
msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr "Web-mallia %s ei löydy, yritetään käyttää oletusmallia"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -417,6 +422,7 @@ msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr ""
|
||||
"Sinun täytyy määrittää enimmäiskaista ennen kaistarajoituksen käyttöönottoa."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Palvelimeen %s ei voida yhdistää [%s]"
|
||||
@@ -440,19 +446,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Alustaminen epäonnistui kohteessa %s@%s syy: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Liikaa yhteyksiä palvelimelle %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Liikaa yhteyksiä palvelimelle %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Mahdollinen tilin jakaminen"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Kirjautuminen palvelimelle %s epäonnistui [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Kirjautuminen palvelimelle %s epäonnistui"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -644,7 +651,7 @@ msgstr ""
|
||||
"API avain virheellinen, käytä Asetukset->Yleiset löytyvää api avainta "
|
||||
"käyttämääsi kolmannen osapuolen ohjelmaan:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Varmennus epäonnistui, tarkista käyttäjänimi/salasana."
|
||||
|
||||
@@ -3015,10 +3022,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Järjestelmäkansio"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Hallinnollinen kansio"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Fred L <88com88@gmail.com>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
# Fred L <88com88@gmail.com>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Fred L <88com88@gmail.com>, 2022\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"
|
||||
@@ -42,11 +42,17 @@ msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools désactivé: aucune version correcte n'a été trouvée ! (v%s trouvée,"
|
||||
" v%s attendue)"
|
||||
"SABYenc désactivé: aucune version correcte n'a été trouvée ! (v%s trouvée, "
|
||||
"v%s attendue)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"Module SABYenc... NON trouvé ! v%s attendue - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
@@ -445,6 +451,7 @@ msgstr ""
|
||||
"Vous devez définir une bande passante maximale avant de pouvoir définir une "
|
||||
"limite de bande passante"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Impossible de se connecter au serveur %s [%s]"
|
||||
@@ -468,21 +475,20 @@ msgstr "Il n'y a aucun serveur actif !"
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Échec d'initialisation de %s@%s pour la raison suivante : %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Trop de connexions au serveur %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Trop de connexions au serveur %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
"Connexion au serveur %s [%s] à partir de trop d'adresses IP différentes - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Partage de compte probable"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Échec de la connexion au serveur %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Échec de la connexion au serveur %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -678,7 +684,7 @@ msgstr ""
|
||||
"Clé API incorrecte, utilisez la clé API de la configuration générale dans "
|
||||
"votre application tierce :"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Echec d'authentification, vérifiez les identifiant/mot de passe."
|
||||
|
||||
@@ -3114,10 +3120,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Dossiers système"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr "Dossiers cachés"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Dossier administrateur"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
# ION, 2022
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: ION, 2022\n"
|
||||
"Language-Team: Hebrew (https://www.transifex.com/sabnzbd/teams/111101/he/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -38,11 +38,16 @@ msgstr "נכשל בהתחלת ממשק רשת"
|
||||
msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr "לא ניתן למצוא תבניות רשת: %s, מנסה תבנית תקנית"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr "SABYenc מושבת: גרסה נכונה לא נמצאה! (%s נמצאה, מצפה אל %s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr "SABCTools מושבת: גרסה נכונה לא נמצאה! (%s נמצאה, מצפה אל %s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr "מודול SABYenc… לא נמצא! מצפה אל %s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
@@ -417,6 +422,7 @@ msgstr "מושהה"
|
||||
msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr "אתה חייב לקבוע רוחב פס מרבי לפני שאתה קובע מגבלת רוחב פס"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "לא ניתן להתחבר אל השרת %s [%s]"
|
||||
@@ -440,19 +446,20 @@ msgstr "אין שרתים פעילים!"
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "נכשל באתחול %s@%s עם סיבה: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "יותר מדי חיבורים לשרת %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "יותר מדי חיבורים לשרת %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "שיתוף סביר של חשבון"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "נכשל בכניסה אל השרת %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "נכשל בכניסה אל השרת %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -642,7 +649,7 @@ msgid ""
|
||||
"program:"
|
||||
msgstr "מפתח API שגוי, השתמש במפתח ה־API מתצורה->כללי בתוכנית הצד השלישי שלך:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "אימות נכשל, בדוק שם משתמש/סיסמה."
|
||||
|
||||
@@ -3021,10 +3028,6 @@ msgstr "קובץ שמכיל את כל הסיסמאות שינוסו על קבצ
|
||||
msgid "System Folders"
|
||||
msgstr "תיקיות מערכת"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "תיקייה מינהלית"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\n"
|
||||
"Language-Team: Norwegian Bokmål (https://www.transifex.com/sabnzbd/teams/111101/nb/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -39,10 +39,16 @@ msgstr "Kan ikke finne webmal: %s, prøver standardmal"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools deaktivert: Fant ikke korrekt versjon! (Fant v%s, forventet v%s)"
|
||||
"SABYenc deaktivert: Fant ikke korrekt versjon! (Fant v%s, forventet v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"SABYenc modul... IKKE funnet! Forventet v%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
@@ -412,6 +418,7 @@ msgstr "Pauset"
|
||||
msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr "Du må sette maks båndbredde før du kan sette en båndbreddebegrensning"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Kan ikke koble til server %s [%s]"
|
||||
@@ -435,19 +442,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Feilet å starte %s@%s grunnet: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "For mange tilkoblinger til server %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "For mange tilkoblinger til server %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Mistenkt kontodeling"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Kunne ikke logge inn på server %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Kunne ikke logge inn på server %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -639,7 +647,7 @@ msgstr ""
|
||||
"API-nøkkel er feil, bruk API-nøkkel fra Konfigurasjon->Generelt i ditt "
|
||||
"tredjepartsprogram:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Godkjenning mislyktes, kontroller brukernavn og passord."
|
||||
|
||||
@@ -2999,10 +3007,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Systemmapper"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Administrativ Mappe"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# Rik Brouwer, 2022
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
#
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\n"
|
||||
"Language-Team: Dutch (https://www.transifex.com/sabnzbd/teams/111101/nl/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -40,12 +40,18 @@ msgstr "Websjabloon %s niet te vinden; het standaardsjabloon wordt gebruikt."
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools uitgeschakeld, geen bruikbare versie gevonden! (V%s gevonden, V%s "
|
||||
"SABYenc uitgeschakeld, geen bruikbare versie gevonden! (V%s gevonden, V%s "
|
||||
"verwacht)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"SABYenc module... NIET gevonden! Verwacht V%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "par2 binary... NOT found!"
|
||||
@@ -439,6 +445,7 @@ msgstr ""
|
||||
"Je moet eerst een maximumbandbreedte instellen voordat je een limiet kunt "
|
||||
"instellen"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Verbinding maken met server %s [%s] niet mogelijk"
|
||||
@@ -462,21 +469,20 @@ msgstr "Er zijn geen actieve servers!"
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Initialisatie van %s@%s mislukt, vanwege: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Te veel verbindingen met server %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Te veel verbindingen met server %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
"Teveel verschillende IP-adressen probeerde in te loggen op server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Mogelijk delen van account"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Aanmelden bij server %s mislukt [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Aanmelden bij server %s mislukt"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -672,7 +678,7 @@ msgstr ""
|
||||
"API-sleutel incorrect; vul de API-sleutel van 'Configuratie' => 'Algemeen' "
|
||||
"in bij het externe programma:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Inloggen mislukt, controleer gebruikersnaam en wachtwoord."
|
||||
|
||||
@@ -3077,10 +3083,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Systeemmappen"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Administratieve map"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
@@ -37,10 +37,15 @@ msgstr "Nie udało się uruchomić interfejsu WWW"
|
||||
msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr "Nie znaleziono szablonu: %s, próbuję użyć standardowego szablonu"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -410,6 +415,7 @@ msgstr ""
|
||||
"Przed ustawieniem limitu przepustowości należy ustawić maksymalną "
|
||||
"przepustowość"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Nie można połączyć się z serwerem %s [%s]"
|
||||
@@ -433,19 +439,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Błąd podczas inicjalizacji %s@%s: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Zbyt wiele połączeń do serwera %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Zbyt wiele połączeń do serwera %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Prawdopodobne współdzielenie konta"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Błąd logowania do serwera %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Błąd logowania do serwera %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -639,7 +646,7 @@ msgstr ""
|
||||
"Klucz API jest nieprawidłowy, użyj klucza API z sekcji Konfiguracja->Ogólne "
|
||||
"w zewnętrznym programie:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Błąd połączenia, sprawdź nazwę użytkownika i hasło."
|
||||
|
||||
@@ -3009,10 +3016,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Katalogi systemowe"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Katalog administracyjny"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
@@ -38,10 +38,15 @@ msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr ""
|
||||
"Não foi possível encontrar o template web: %s. Tentando o template padrão"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -416,6 +421,7 @@ msgstr ""
|
||||
"Você deve definir a largura de banda máxima antes de definir um limite de "
|
||||
"banda"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Não é possível conectar ao servidor %s [%s]"
|
||||
@@ -439,19 +445,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Falha ao iniciar %s@%s devido as seguintes razões: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Excesso de conexões ao servidor %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Excesso de conexões ao servidor %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Provável compartilhamento de conta"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Falha de logon ao servidor %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Falha de logon ao servidor %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -643,7 +650,7 @@ msgstr ""
|
||||
"Chave de API incorreta. Use a chave de API de Configuração->Geral em seu "
|
||||
"programa de terceiros:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Falha de autenticação, verifique usuário / senha."
|
||||
|
||||
@@ -3009,10 +3016,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Pastas de Sistema"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Pasta Administrativa"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Eduard Baniceru <war4peace@gmail.com>, 2021
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\n"
|
||||
"Language-Team: Romanian (https://www.transifex.com/sabnzbd/teams/111101/ro/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -40,12 +40,18 @@ msgstr "Nu se poate găsi şablon web:%s, se încearcă şablon standard"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
"SABCTools dezactivat: nu s-a găsit o versiune corectă! (Găsită v%s, se "
|
||||
"SABYenc dezactivat: nu s-a găsit o versiune corectă! (Găsită v%s, se "
|
||||
"așteaptă v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
"Modul SABYenc... NEgăsit! Se așteaptă v%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "par2 binary... NOT found!"
|
||||
@@ -429,6 +435,7 @@ msgstr ""
|
||||
"Trebuie să seta-ţi lățimea de bandă maximă înainte de a seta o limită de "
|
||||
"viteză."
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Nu mă pot conecta la serverul %s [%s]"
|
||||
@@ -452,19 +459,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Nu am putu inițializa %s@%s din cauza următorului motiv: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Prea multe conexiuni la serverul %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Prea multe conexiuni la serverul %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Partajare cont probabilă"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Autentificare nereuşită la serverul %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Autentificare nereuşită la serverul %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -656,7 +664,7 @@ msgstr ""
|
||||
"Cheie API incorectă, Folosiţi cheia api din Configurare->General în "
|
||||
"programul dumneavoastră terţ:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Autentificare nereuşită, verifică nume utilizator/parolă."
|
||||
|
||||
@@ -3034,10 +3042,6 @@ msgstr "Fişier ce conţine parole pentru fişiere RAR encriptate."
|
||||
msgid "System Folders"
|
||||
msgstr "Dosare Sistem"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Dosar Administrativ"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
@@ -39,10 +39,15 @@ msgstr ""
|
||||
"Не удаётся найти шаблон веб-интерфейса: %s. Выполняется попытка использовать"
|
||||
" стандартный шаблон"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -412,6 +417,7 @@ msgstr "Приостановлено"
|
||||
msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Не удаётся подключиться к серверу %s [%s]"
|
||||
@@ -435,19 +441,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr ""
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Возможно, учётная запись используется где-то ещё"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Ошибка входа на сервер %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Ошибка входа на сервер %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -639,7 +646,7 @@ msgstr ""
|
||||
"Неправильный ключ API. Используйте в сторонней программе ключ API из раздела"
|
||||
" «Настройка -> Общие»:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Ошибка проверки подлинности. Проверьте имя и пароль."
|
||||
|
||||
@@ -3005,10 +3012,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Системные папки"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Административная папка"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
@@ -37,10 +37,15 @@ msgstr "Neuspešno pokretanje web interfejsa"
|
||||
msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr "Немогуће наћи веб модел: %s, програм покушава са стандардним моделом"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -411,6 +416,7 @@ msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr ""
|
||||
"Требате да поставите максимални проток пре него што поставите ограничење"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Neuspešno povezivanje na server %s[%s]"
|
||||
@@ -434,19 +440,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Neuspešna inicijalizacija %s@%s iz razloga: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "Previše konekcija ka serveru %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "Previše konekcija ka serveru %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Moguće deljenje naloga"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Неуспешно пријављивање на сервер %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Неуспешно пријављивање на сервер %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -636,7 +643,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"API кључ је погрешан, унети у спољни програм API кључ из Подешавања->Опште:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Аутентификација погрешна, проверити име/лозинку."
|
||||
|
||||
@@ -2990,10 +2997,6 @@ msgstr "Датотека са свим лозинкама за шифрован
|
||||
msgid "System Folders"
|
||||
msgstr "Системске фасцикле"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Фасцикла Администратора"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
@@ -37,10 +37,15 @@ msgstr "Det gick inte att starta webbgränssnittet"
|
||||
msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr "Hittar inte webbmall: %s, försöker med standardmall"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr ""
|
||||
|
||||
#. Error message
|
||||
@@ -411,6 +416,7 @@ msgstr "Pausad"
|
||||
msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr "Du måste ange maximal bandbredd innan du kan ange bandbreddsgräns"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "Kan ej ansluta till server %s [%s]"
|
||||
@@ -434,19 +440,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "Misslyckades att initiera %s@%s med orsak %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "För många anslutningar till servern %s [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "För många anslutningar till servern %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "Misstänkt kontodelning"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "Det gick inte att logga in på server %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "Det gick inte att logga in på server %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -638,7 +645,7 @@ msgstr ""
|
||||
"API-nyckel felaktig, använd api-nyckeln från Konfiguration-> Allmänt i ditt "
|
||||
"tredjepartsprogram:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "Autentisering misslyckades, kontrollera användarnamn och lösenord."
|
||||
|
||||
@@ -3001,10 +3008,6 @@ msgstr ""
|
||||
msgid "System Folders"
|
||||
msgstr "Systemmappar"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "Administrativ mapp"
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
# SABnzbd Translation Template file MAIN
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
# Safihre <safihre@sabnzbd.org>, 2023
|
||||
# Safihre <safihre@sabnzbd.org>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
|
||||
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2022\n"
|
||||
"Language-Team: Chinese (China) (https://www.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -37,11 +37,16 @@ msgstr "web 界面启动失败"
|
||||
msgid "Cannot find web template: %s, trying standard template"
|
||||
msgstr "无法找到 web 模板: %s,正在尝试标准模板"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid "SABYenc disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr "SABYenc 已禁用:未找到正确的版本!(找到 v%s,要求 v%s)"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
msgid ""
|
||||
"SABCTools disabled: no correct version found! (Found v%s, expecting v%s)"
|
||||
msgstr "SABCTools 已禁用:未找到正确的版本!(找到 v%s,要求 v%s)"
|
||||
"SABYenc module... NOT found! Expecting v%s - https://sabnzbd.org/sabyenc"
|
||||
msgstr "SABYenc 模块... 未找到!要求 v%s - https://sabnzbd.org/sabyenc"
|
||||
|
||||
#. Error message
|
||||
#: SABnzbd.py
|
||||
@@ -408,6 +413,7 @@ msgstr "已暂停"
|
||||
msgid "You must set a maximum bandwidth before you can set a bandwidth limit"
|
||||
msgstr "设置带宽限制前,您必须设置最大带宽值"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Cannot connect to server %s [%s]"
|
||||
msgstr "无法连接到服务器 %s [%s]"
|
||||
@@ -431,19 +437,20 @@ msgstr ""
|
||||
msgid "Failed to initialize %s@%s with reason: %s"
|
||||
msgstr "无法初始化 %s@%s,原因为: %s"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Too many connections to server %s [%s]"
|
||||
msgstr "服务器 %s 连接数过多 [%s]"
|
||||
msgid "Too many connections to server %s"
|
||||
msgstr "服务器 %s 连接数过多"
|
||||
|
||||
#. Warning message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid ""
|
||||
"Login from too many different IP addresses to server %s [%s] - "
|
||||
"https://sabnzbd.org/multiple-adresses"
|
||||
msgstr ""
|
||||
msgid "Probable account sharing"
|
||||
msgstr "可能存在账号共享"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
msgid "Failed login for server %s [%s]"
|
||||
msgstr "无法登录服务器 %s [%s]"
|
||||
msgid "Failed login for server %s"
|
||||
msgstr "无法登录服务器 %s"
|
||||
|
||||
#. Error message
|
||||
#: sabnzbd/downloader.py
|
||||
@@ -631,7 +638,7 @@ msgid ""
|
||||
"program:"
|
||||
msgstr "API Key 不正确,请在第三方程序中使用“配置”->“常规”中的 api key:"
|
||||
|
||||
#: sabnzbd/interface.py, sabnzbd/utils/servertests.py
|
||||
#: sabnzbd/interface.py, sabnzbd/newswrapper.py, sabnzbd/utils/servertests.py
|
||||
msgid "Authentication failed, check username/password."
|
||||
msgstr "身份认证失败,请检查用户名/密码。"
|
||||
|
||||
@@ -2959,10 +2966,6 @@ msgstr "包含要对加密 RAR 文件进行尝试的所有密码的文件。"
|
||||
msgid "System Folders"
|
||||
msgstr "系统文件夹"
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Hidden Folders"
|
||||
msgstr ""
|
||||
|
||||
#: sabnzbd/skintext.py
|
||||
msgid "Administrative Folder"
|
||||
msgstr "管理文件夹"
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
#
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-4.0.0Alpha1\n"
|
||||
"Project-Id-Version: SABnzbd-3.8.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"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
#
|
||||
# Translators:
|
||||
# Safihre <safihre@sabnzbd.org>, 2020
|
||||
# reloxx13 <reloxx@interia.pl>, 2022
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: SABnzbd-4.0.0-develop\n"
|
||||
"Project-Id-Version: SABnzbd-3.8.0-develop\n"
|
||||
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
|
||||
"Last-Translator: reloxx13 <reloxx@interia.pl>, 2022\n"
|
||||
"Language-Team: German (https://www.transifex.com/sabnzbd/teams/111101/de/)\n"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SABnzbd Translation Template file NSIS
|
||||
# Copyright 2007-2023 The SABnzbd-Team
|
||||
# Copyright 2007-2022 The SABnzbd-Team
|
||||
# team@sabnzbd.org
|
||||
#
|
||||
# Translators:
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Main requirements
|
||||
# Note that not all sub-dependencies are listed, but only ones we know could cause trouble
|
||||
sabctools==6.1.0
|
||||
sabyenc3==5.4.4
|
||||
cheetah3==3.2.6.post1
|
||||
cffi==1.15.1
|
||||
pycparser==2.21
|
||||
feedparser==6.0.10
|
||||
configobj==5.0.8
|
||||
configobj==5.0.6
|
||||
cheroot==9.0.0
|
||||
six==1.16.0
|
||||
cherrypy==18.8.0
|
||||
@@ -13,12 +13,12 @@ jaraco.functools==3.5.2
|
||||
jaraco.collections==3.8.0
|
||||
jaraco.text==3.8.1 # Newer version introduces irrelevant extra dependencies
|
||||
jaraco.classes==3.2.3
|
||||
jaraco.context==4.3.0
|
||||
jaraco.context==4.2.0
|
||||
more-itertools==9.0.0
|
||||
zc.lockfile==2.0
|
||||
python-dateutil==2.8.2
|
||||
tempora==5.2.1
|
||||
pytz==2022.7.1
|
||||
tempora==5.1.0
|
||||
pytz==2022.6
|
||||
sgmllib3k==1.0.0
|
||||
portend==3.1.0
|
||||
chardet==5.1.0
|
||||
@@ -30,17 +30,17 @@ rebulk==3.1.0
|
||||
|
||||
# Recent cryptography versions require Rust. If you run into issues compiling this
|
||||
# SABnzbd will also work with older pre-Rust versions such as cryptography==3.3.2
|
||||
cryptography==39.0.1
|
||||
cryptography==38.0.4
|
||||
|
||||
# We recommend using "orjson" as it is 2x as fast as "ujson". However, it requires
|
||||
# Rust so SABnzbd works just as well with "ujson" or the Python built in "json" module
|
||||
ujson==5.7.0
|
||||
ujson==5.6.0
|
||||
|
||||
# Windows system integration
|
||||
pywin32==305; sys_platform == 'win32'
|
||||
|
||||
# macOS system calls
|
||||
pyobjc==9.0.1; sys_platform == 'darwin'
|
||||
pyobjc==9.0; sys_platform == 'darwin'
|
||||
|
||||
# Linux notifications
|
||||
notify2==0.3.1; sys_platform != 'win32' and sys_platform != 'darwin'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -162,7 +162,7 @@ WIN_SERVICE = None # Instance of our Win32 Service Class
|
||||
BROWSER_URL = None
|
||||
|
||||
CERTIFICATE_VALIDATION = True
|
||||
NO_DOWNLOADING = False # When essentials are missing (SABCTools/par2/unrar)
|
||||
NO_DOWNLOADING = False # When essentials are missing (SABYenc/par2/unrar)
|
||||
|
||||
WEB_DIR = None
|
||||
WEB_DIR_CONFIG = None
|
||||
@@ -190,16 +190,12 @@ DOWNLOAD_DIR_SPEED = 0
|
||||
COMPLETE_DIR_SPEED = 0
|
||||
INTERNET_BANDWIDTH = 0
|
||||
|
||||
# Record of HTTPS config files at startup
|
||||
CONFIG_BACKUP_HTTPS_OK = []
|
||||
|
||||
# Rendering of original command line arguments in Config
|
||||
CMDLINE = " ".join(['"%s"' % arg for arg in sys.argv])
|
||||
|
||||
__INITIALIZED__ = False
|
||||
__SHUTTING_DOWN__ = False
|
||||
|
||||
|
||||
##############################################################################
|
||||
# Signal Handler
|
||||
##############################################################################
|
||||
@@ -232,8 +228,6 @@ def initialize(pause_downloader=False, clean_up=False, repair=0):
|
||||
|
||||
sabnzbd.__SHUTTING_DOWN__ = False
|
||||
|
||||
sys.setswitchinterval(cfg.switchinterval())
|
||||
|
||||
# Set global database connection for Web-UI threads
|
||||
cherrypy.engine.subscribe("start_thread", get_db_connection)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -26,7 +26,7 @@ from typing import Dict, List
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.decorators import synchronized
|
||||
from sabnzbd.constants import GIGI, ANFO, MEBI, LIMIT_DECODE_QUEUE, MIN_DECODE_QUEUE, ASSEMBLER_WRITE_THRESHOLD
|
||||
from sabnzbd.constants import GIGI, ANFO, MEBI, LIMIT_DECODE_QUEUE, MIN_DECODE_QUEUE
|
||||
from sabnzbd.nzbstuff import Article
|
||||
|
||||
# Operations on the article table are handled via try/except.
|
||||
@@ -45,8 +45,6 @@ class ArticleCache:
|
||||
# so it can be larger on memory-rich systems
|
||||
self.decoder_cache_article_limit = 0
|
||||
|
||||
self.assembler_write_trigger: int = 1
|
||||
|
||||
# On 32 bit we only allow the user to set 1GB
|
||||
# For 64 bit we allow up to 4GB, in case somebody wants that
|
||||
self.__cache_upper_limit = GIGI
|
||||
@@ -70,16 +68,6 @@ class ArticleCache:
|
||||
# The cache should also not be too small
|
||||
self.decoder_cache_article_limit = max(decoder_cache_limit, MIN_DECODE_QUEUE)
|
||||
|
||||
# Set assembler_write_trigger to be the equivalent of ASSEMBLER_WRITE_THRESHOLD %
|
||||
# of the total cache, assuming an article size of 750 000 bytes
|
||||
self.assembler_write_trigger = int(self.__cache_limit * ASSEMBLER_WRITE_THRESHOLD / 100 / 750_000) + 1
|
||||
|
||||
logging.debug(
|
||||
"Decoder cache limit = %d - Assembler trigger = %d",
|
||||
self.decoder_cache_article_limit,
|
||||
self.assembler_write_trigger,
|
||||
)
|
||||
|
||||
@synchronized(ARTICLE_COUNTER_LOCK)
|
||||
def reserve_space(self, data_size: int):
|
||||
"""Reserve space in the cache"""
|
||||
@@ -104,10 +92,9 @@ class ArticleCache:
|
||||
# Register article for bookkeeping in case the job is deleted
|
||||
nzo.add_saved_article(article)
|
||||
|
||||
if article.lowest_partnum and not (article.nzf.import_finished or article.nzf.filename_checked):
|
||||
# Write the first-fetched articles to temporary file unless downloading
|
||||
# of the rest of the parts has started or filename is verified.
|
||||
# Otherwise the cache could overflow.
|
||||
if article.lowest_partnum and not article.nzf.import_finished:
|
||||
# Write the first-fetched articles to disk
|
||||
# Otherwise the cache could overflow
|
||||
self.__flush_article_to_disk(article, data)
|
||||
return
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -24,6 +24,7 @@ import queue
|
||||
import logging
|
||||
import re
|
||||
from threading import Thread
|
||||
import hashlib
|
||||
import ctypes
|
||||
from typing import Tuple, Optional, List
|
||||
|
||||
@@ -55,8 +56,11 @@ class Assembler(Thread):
|
||||
def process(self, nzo: NzbObject, nzf: Optional[NzbFile] = None, file_done: Optional[bool] = None):
|
||||
self.queue.put((nzo, nzf, file_done))
|
||||
|
||||
def queue_level(self) -> float:
|
||||
return self.queue.qsize() / MAX_ASSEMBLER_QUEUE
|
||||
def queue_full(self):
|
||||
return self.queue.qsize() >= MAX_ASSEMBLER_QUEUE
|
||||
|
||||
def partial_nzf_in_queue(self, nzf: NzbFile):
|
||||
return (nzf.nzo, nzf, False) in self.queue.queue
|
||||
|
||||
def run(self):
|
||||
while 1:
|
||||
@@ -74,7 +78,9 @@ class Assembler(Thread):
|
||||
self.diskspace_check(nzo, nzf)
|
||||
|
||||
# Prepare filepath
|
||||
if filepath := nzf.prepare_filepath():
|
||||
filepath = nzf.prepare_filepath()
|
||||
|
||||
if filepath:
|
||||
try:
|
||||
logging.debug("Decoding part of %s", filepath)
|
||||
self.assemble(nzo, nzf, file_done)
|
||||
@@ -164,6 +170,9 @@ class Assembler(Thread):
|
||||
1) Partial write: write what we have
|
||||
2) Nothing written before: write all
|
||||
"""
|
||||
# New hash-object needed?
|
||||
if not nzf.md5:
|
||||
nzf.md5 = hashlib.md5()
|
||||
|
||||
# We write large article-sized chunks, so we can safely skip the buffering of Python
|
||||
with open(nzf.filepath, "ab", buffering=0) as fout:
|
||||
@@ -182,7 +191,7 @@ class Assembler(Thread):
|
||||
# Could be empty in case nzo was deleted
|
||||
if data:
|
||||
fout.write(data)
|
||||
nzf.update_crc32(article.crc32, len(data))
|
||||
nzf.md5.update(data)
|
||||
article.on_disk = True
|
||||
else:
|
||||
logging.info("No data found when trying to write %s", article)
|
||||
@@ -198,7 +207,7 @@ class Assembler(Thread):
|
||||
# Final steps
|
||||
if file_done:
|
||||
set_permissions(nzf.filepath)
|
||||
nzf.assembled = True
|
||||
nzf.md5sum = nzf.md5.digest()
|
||||
|
||||
@staticmethod
|
||||
def check_encrypted_and_unwanted(nzo: NzbObject, nzf: NzbFile):
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -434,6 +434,40 @@ class BPSMeter:
|
||||
# We record every second, but display at the user's refresh-rate
|
||||
return self.bps_list[::refresh_rate]
|
||||
|
||||
def get_stable_speed(self, timespan: int = 10) -> Optional[int]:
|
||||
"""See if there is a stable speed the last <timespan> seconds
|
||||
None: indicates it can't determine yet
|
||||
0: the speed was not stable during <timespan>
|
||||
Positive float: the speed was stable
|
||||
"""
|
||||
if len(self.bps_list) < timespan:
|
||||
return None
|
||||
|
||||
# Check if speed fell by more than 15%
|
||||
try:
|
||||
if self.bps_list[-1] / self.bps_list[-timespan] < 0.85:
|
||||
return 0
|
||||
except:
|
||||
pass
|
||||
|
||||
# Calculate the variance in the speed
|
||||
avg = sum(self.bps_list[-timespan:]) / timespan
|
||||
vari = 0
|
||||
for bps in self.bps_list[-timespan:]:
|
||||
vari += abs(bps - avg)
|
||||
vari = vari / timespan
|
||||
|
||||
try:
|
||||
# See if the variance is less than 5%
|
||||
if (vari / (self.bps / KIBI)) < 0.05:
|
||||
return avg
|
||||
else:
|
||||
return 0
|
||||
except:
|
||||
# Probably one of the values was 0
|
||||
pass
|
||||
return None
|
||||
|
||||
def reset_quota(self, force: bool = False):
|
||||
"""Check if it's time to reset the quota, optionally resuming
|
||||
Return True, when still paused or should be paused
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -47,8 +47,6 @@ from sabnzbd.constants import (
|
||||
DEF_COMPLETE_DIR,
|
||||
DEF_FOLDER_MAX,
|
||||
DEF_STD_WEB_COLOR,
|
||||
DEF_HTTPS_CERT_FILE,
|
||||
DEF_HTTPS_KEY_FILE,
|
||||
)
|
||||
|
||||
|
||||
@@ -260,6 +258,7 @@ configlock = OptionBool("misc", "config_lock", False)
|
||||
# One time trackers
|
||||
##############################################################################
|
||||
fixed_ports = OptionBool("misc", "fixed_ports", False)
|
||||
sched_converted = OptionBool("misc", "sched_converted", False)
|
||||
notified_new_skin = OptionNumber("misc", "notified_new_skin", 0)
|
||||
direct_unpack_tested = OptionBool("misc", "direct_unpack_tested", False)
|
||||
|
||||
@@ -280,8 +279,8 @@ bandwidth_max = OptionStr("misc", "bandwidth_max")
|
||||
cache_limit = OptionStr("misc", "cache_limit")
|
||||
web_dir = OptionStr("misc", "web_dir", DEF_STD_WEB_DIR)
|
||||
web_color = OptionStr("misc", "web_color", DEF_STD_WEB_COLOR)
|
||||
https_cert = OptionDir("misc", "https_cert", DEF_HTTPS_CERT_FILE, create=False)
|
||||
https_key = OptionDir("misc", "https_key", DEF_HTTPS_KEY_FILE, create=False)
|
||||
https_cert = OptionDir("misc", "https_cert", "server.cert", create=False)
|
||||
https_key = OptionDir("misc", "https_key", "server.key", create=False)
|
||||
https_chain = OptionDir("misc", "https_chain", create=False)
|
||||
enable_https = OptionBool("misc", "enable_https", False)
|
||||
# 0=local-only, 1=nzb, 2=api, 3=full_api, 4=webui, 5=webui with login for external
|
||||
@@ -435,9 +434,7 @@ host_whitelist = OptionList("misc", "host_whitelist", validation=all_lowercase)
|
||||
local_ranges = OptionList("misc", "local_ranges", protect=True)
|
||||
max_url_retries = OptionNumber("misc", "max_url_retries", 10, minval=1)
|
||||
downloader_sleep_time = OptionNumber("misc", "downloader_sleep_time", 10, minval=0)
|
||||
receive_threads = OptionNumber("misc", "receive_threads", 2, minval=1)
|
||||
num_simd_decoders = OptionNumber("misc", "num_simd_decoders", 2, minval=1)
|
||||
switchinterval = OptionNumber("misc", "switchinterval", 0.005)
|
||||
ssdp_broadcast_interval = OptionNumber("misc", "ssdp_broadcast_interval", 15, minval=1, maxval=600)
|
||||
ext_rename_ignore = OptionList("misc", "ext_rename_ignore", validation=lower_case_ext)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -34,14 +34,7 @@ from urllib.parse import urlparse
|
||||
import configobj
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import (
|
||||
CONFIG_VERSION,
|
||||
NORMAL_PRIORITY,
|
||||
DEFAULT_PRIORITY,
|
||||
CONFIG_BACKUP_FILES,
|
||||
CONFIG_BACKUP_HTTPS,
|
||||
DEF_INI_FILE,
|
||||
)
|
||||
from sabnzbd.constants import CONFIG_VERSION, NORMAL_PRIORITY, DEFAULT_PRIORITY, CONFIG_BACKUP_FILES, DEF_INI_FILE
|
||||
from sabnzbd.decorators import synchronized
|
||||
from sabnzbd.filesystem import clip_path, real_path, create_real_path, renamer, remove_file, is_writable
|
||||
|
||||
@@ -401,6 +394,7 @@ class ConfigServer:
|
||||
"""Class defining a single server"""
|
||||
|
||||
def __init__(self, name, values):
|
||||
|
||||
self.__name = clean_section_name(name)
|
||||
name = "servers," + self.__name
|
||||
|
||||
@@ -719,9 +713,7 @@ def get_dconfig(section, keyword, nested=False):
|
||||
sect = CFG_DATABASE[section]
|
||||
except KeyError:
|
||||
return False, {}
|
||||
if section == "categories":
|
||||
data[section] = get_ordered_categories()
|
||||
elif section in ("servers", "rss"):
|
||||
if section in ("servers", "categories", "rss"):
|
||||
data[section] = []
|
||||
for keyword in sect.keys():
|
||||
res, conf = get_dconfig(section, keyword, True)
|
||||
@@ -950,17 +942,6 @@ def create_config_backup() -> Union[str, bool]:
|
||||
if os.path.isfile(full_path):
|
||||
with open(full_path, "rb") as data:
|
||||
zip_ref.writestr(filename, data.read())
|
||||
for filename, setting in CONFIG_BACKUP_HTTPS.items():
|
||||
full_path = getattr(sabnzbd.cfg, setting).get_path()
|
||||
# Only accept HTTPS config files that were successfully loaded by cherrypy on
|
||||
# startup to protect against last-minute breaking config changes as well as
|
||||
# inclusion of unrelated files in the backup through manipulated settings.
|
||||
if full_path and os.path.isfile(full_path) and full_path in sabnzbd.CONFIG_BACKUP_HTTPS_OK:
|
||||
logging.debug("Adding %s file %s to backup", setting, full_path)
|
||||
with open(full_path, "rb") as data:
|
||||
# Add the https cert/key/chain files with a fixed relative filename,
|
||||
# regardless of where they are actually stored on the filesystem
|
||||
zip_ref.writestr(filename, data.read())
|
||||
with open(CFG_OBJ.filename, "rb") as data:
|
||||
zip_ref.writestr(DEF_INI_FILE, data.read())
|
||||
return clip_path(complete_path)
|
||||
@@ -983,7 +964,6 @@ def validate_config_backup(config_backup_data: bytes) -> bool:
|
||||
|
||||
def restore_config_backup(config_backup_data: bytes):
|
||||
"""Restore configuration files from zip file"""
|
||||
global CFG_MODIFIED
|
||||
try:
|
||||
with io.BytesIO(config_backup_data) as backup_ref:
|
||||
with zipfile.ZipFile(backup_ref, "r") as zip_ref:
|
||||
@@ -996,22 +976,16 @@ def restore_config_backup(config_backup_data: bytes):
|
||||
|
||||
# Write the rest of the admin files that we want to recover
|
||||
adminpath = sabnzbd.cfg.admin_dir.get_path()
|
||||
for filename in CONFIG_BACKUP_FILES + list(CONFIG_BACKUP_HTTPS.keys()):
|
||||
for filename in CONFIG_BACKUP_FILES:
|
||||
try:
|
||||
zip_ref.getinfo(filename)
|
||||
destination_file = os.path.join(adminpath, filename)
|
||||
logging.debug("Writing backup of %s to %s", filename, destination_file)
|
||||
with open(destination_file, "wb") as destination_ref:
|
||||
destination_ref.write(zip_ref.read(filename))
|
||||
# For HTTPS config files, point the associated setting to the restored file
|
||||
if setting := CONFIG_BACKUP_HTTPS.get(filename):
|
||||
logging.debug("Setting value of %s to restored file %s", setting, filename)
|
||||
getattr(sabnzbd.cfg, setting).set(filename)
|
||||
CFG_MODIFIED = True
|
||||
except KeyError:
|
||||
# File not in archive
|
||||
pass
|
||||
save_config()
|
||||
except:
|
||||
logging.warning(T("Could not restore backup"))
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -49,11 +49,17 @@ RENAMES_FILE = "__renames__"
|
||||
ATTRIB_FILE = "SABnzbd_attrib"
|
||||
REPAIR_REQUEST = "repair-all.sab"
|
||||
|
||||
SABCTOOLS_VERSION_REQUIRED = "6.1.0"
|
||||
SABYENC_VERSION_REQUIRED = "5.4.4"
|
||||
|
||||
DB_HISTORY_VERSION = 1
|
||||
DB_HISTORY_NAME = "history%s.db" % DB_HISTORY_VERSION
|
||||
|
||||
CONFIG_BACKUP_FILES = [
|
||||
BYTES_FILE_NAME,
|
||||
RSS_FILE_NAME,
|
||||
DB_HISTORY_NAME,
|
||||
]
|
||||
|
||||
DEF_DOWNLOAD_DIR = os.path.normpath("Downloads/incomplete")
|
||||
DEF_COMPLETE_DIR = os.path.normpath("Downloads/complete")
|
||||
DEF_ADMIN_DIR = "admin"
|
||||
@@ -76,30 +82,14 @@ DEF_ARTICLE_CACHE_DEFAULT = "500M"
|
||||
DEF_ARTICLE_CACHE_MAX = "1G"
|
||||
DEF_TIMEOUT = 60
|
||||
DEF_SCANRATE = 5
|
||||
DEF_HTTPS_CERT_FILE = "server.cert"
|
||||
DEF_HTTPS_KEY_FILE = "server.key"
|
||||
MAX_WARNINGS = 20
|
||||
MAX_BAD_ARTICLES = 5
|
||||
|
||||
CONFIG_BACKUP_FILES = [
|
||||
BYTES_FILE_NAME,
|
||||
RSS_FILE_NAME,
|
||||
DB_HISTORY_NAME,
|
||||
]
|
||||
CONFIG_BACKUP_HTTPS = { # "basename": "associated setting"
|
||||
DEF_HTTPS_CERT_FILE: "https_cert",
|
||||
DEF_HTTPS_KEY_FILE: "https_key",
|
||||
"server.chain": "https_chain",
|
||||
}
|
||||
|
||||
# Constants affecting download performance
|
||||
MIN_DECODE_QUEUE = 10
|
||||
LIMIT_DECODE_QUEUE = 100
|
||||
MAX_ASSEMBLER_QUEUE = 10
|
||||
SOFT_QUEUE_LIMIT = 0.6
|
||||
# Percentage of cache to use before adding file to assembler
|
||||
ASSEMBLER_WRITE_THRESHOLD = 5
|
||||
NNTP_BUFFER_SIZE = int(800 * KIBI)
|
||||
DIRECT_WRITE_TRIGGER = 35
|
||||
MAX_ASSEMBLER_QUEUE = 5
|
||||
|
||||
REPAIR_PRIORITY = 3
|
||||
FORCE_PRIORITY = 2
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -554,7 +554,7 @@ def unpack_history_info(item: Union[Dict, sqlite3.Row]):
|
||||
return item
|
||||
|
||||
|
||||
def scheduled_history_purge():
|
||||
def midnight_history_purge():
|
||||
logging.info("Scheduled history purge")
|
||||
with HistoryDB() as history_db:
|
||||
history_db.auto_history_purge()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -26,31 +26,28 @@ import binascii
|
||||
from io import BytesIO
|
||||
from threading import Thread
|
||||
from typing import Tuple, List, Optional
|
||||
from zlib import crc32
|
||||
|
||||
import sabnzbd
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.constants import SABCTOOLS_VERSION_REQUIRED
|
||||
from sabnzbd.constants import SABYENC_VERSION_REQUIRED
|
||||
from sabnzbd.encoding import ubtou
|
||||
from sabnzbd.nzbstuff import Article
|
||||
from sabnzbd.misc import match_str
|
||||
|
||||
# Check for correct SABCTools version
|
||||
SABCTOOLS_VERSION = None
|
||||
SABCTOOLS_SIMD = None
|
||||
SABCTOOLS_OPENSSL_LINKED = None
|
||||
# Check for correct SABYenc version
|
||||
SABYENC_VERSION = None
|
||||
SABYENC_SIMD = None
|
||||
try:
|
||||
import sabctools
|
||||
import sabyenc3
|
||||
|
||||
SABCTOOLS_ENABLED = True
|
||||
SABCTOOLS_VERSION = sabctools.__version__
|
||||
SABCTOOLS_SIMD = sabctools.simd
|
||||
SABCTOOLS_OPENSSL_LINKED = sabctools.openssl_linked
|
||||
SABYENC_ENABLED = True
|
||||
SABYENC_VERSION = sabyenc3.__version__
|
||||
SABYENC_SIMD = sabyenc3.simd
|
||||
# Verify version to at least match minor version
|
||||
if SABCTOOLS_VERSION[:3] != SABCTOOLS_VERSION_REQUIRED[:3]:
|
||||
if SABYENC_VERSION[:3] != SABYENC_VERSION_REQUIRED[:3]:
|
||||
raise ImportError
|
||||
except:
|
||||
SABCTOOLS_ENABLED = False
|
||||
SABYENC_ENABLED = False
|
||||
|
||||
|
||||
class BadData(Exception):
|
||||
@@ -71,6 +68,7 @@ class Decoder:
|
||||
"""Implement thread-like coordinator for the decoders"""
|
||||
|
||||
def __init__(self):
|
||||
|
||||
# Initialize queue and servers
|
||||
self.decoder_queue = queue.Queue()
|
||||
|
||||
@@ -105,13 +103,13 @@ class Decoder:
|
||||
except:
|
||||
pass
|
||||
|
||||
def process(self, article: Article, raw_data: bytearray, raw_data_size: int):
|
||||
sabnzbd.ArticleCache.reserve_space(raw_data_size)
|
||||
self.decoder_queue.put((article, raw_data, raw_data_size))
|
||||
def process(self, article: Article, raw_data: List[bytes], data_size: int):
|
||||
sabnzbd.ArticleCache.reserve_space(data_size)
|
||||
self.decoder_queue.put((article, raw_data, data_size))
|
||||
|
||||
def queue_level(self) -> float:
|
||||
# Return level of decoder queue. 0 = empty, >=1 = full.
|
||||
return self.decoder_queue.qsize() / sabnzbd.ArticleCache.decoder_cache_article_limit
|
||||
def queue_full(self) -> bool:
|
||||
# Check if the queue size exceeds the limits
|
||||
return self.decoder_queue.qsize() >= sabnzbd.ArticleCache.decoder_cache_article_limit
|
||||
|
||||
|
||||
class DecoderWorker(Thread):
|
||||
@@ -120,14 +118,14 @@ class DecoderWorker(Thread):
|
||||
def __init__(self, decoder_queue):
|
||||
super().__init__()
|
||||
logging.debug("Initializing decoder %s", self.name)
|
||||
self.decoder_queue: queue.Queue[Tuple[Optional[Article], Optional[bytearray], Optional[int]]] = decoder_queue
|
||||
self.decoder_queue: queue.Queue[Tuple[Optional[Article], Optional[List[bytes]], Optional[int]]] = decoder_queue
|
||||
|
||||
def run(self):
|
||||
while 1:
|
||||
# Set Article and NzbObject objects to None so references from this
|
||||
# thread do not keep the parent objects alive (see #1628)
|
||||
decoded_data = raw_data = article = nzo = None
|
||||
article, raw_data, raw_data_size = self.decoder_queue.get()
|
||||
article, raw_data, data_size = self.decoder_queue.get()
|
||||
if not article:
|
||||
logging.debug("Shutting down decoder %s", self.name)
|
||||
break
|
||||
@@ -136,7 +134,7 @@ class DecoderWorker(Thread):
|
||||
art_id = article.article
|
||||
|
||||
# Free space in the decoder-queue
|
||||
sabnzbd.ArticleCache.free_reserved_space(raw_data_size)
|
||||
sabnzbd.ArticleCache.free_reserved_space(data_size)
|
||||
|
||||
# Keeping track
|
||||
article_success = False
|
||||
@@ -151,7 +149,7 @@ class DecoderWorker(Thread):
|
||||
if article.nzf.type == "uu":
|
||||
decoded_data = decode_uu(article, raw_data)
|
||||
else:
|
||||
decoded_data = decode_yenc(article, raw_data, raw_data_size)
|
||||
decoded_data = decode_yenc(article, raw_data)
|
||||
|
||||
article_success = True
|
||||
|
||||
@@ -183,7 +181,7 @@ class DecoderWorker(Thread):
|
||||
|
||||
except (BadYenc, ValueError):
|
||||
# Handles precheck and badly formed articles
|
||||
if nzo.precheck and raw_data and raw_data.startswith(b"223 "):
|
||||
if nzo.precheck and raw_data and raw_data[0].startswith(b"223 "):
|
||||
# STAT was used, so we only get a status code
|
||||
article_success = True
|
||||
else:
|
||||
@@ -197,9 +195,9 @@ class DecoderWorker(Thread):
|
||||
pass
|
||||
# Only bother with further checks if uu-decoding didn't work out
|
||||
if not article_success:
|
||||
# Convert the first 2000 bytes of raw socket data to article lines,
|
||||
# Convert the initial chunks of raw socket data to article lines,
|
||||
# and examine the headers (for precheck) or body (for download).
|
||||
for line in raw_data[:2000].split(b"\r\n"):
|
||||
for line in b"".join(raw_data[:2]).split(b"\r\n"):
|
||||
lline = line.lower()
|
||||
if lline.startswith(b"message-id:"):
|
||||
article_success = True
|
||||
@@ -235,43 +233,39 @@ class DecoderWorker(Thread):
|
||||
# If the data needs to be written to disk due to full cache, this will be slow
|
||||
# Causing the decoder-queue to fill up and delay the downloader
|
||||
sabnzbd.ArticleCache.save_article(article, decoded_data)
|
||||
article.decoded = True
|
||||
elif not nzo.precheck:
|
||||
# Nothing to save
|
||||
article.on_disk = True
|
||||
|
||||
sabnzbd.NzbQueue.register_article(article, article_success)
|
||||
|
||||
|
||||
def decode_yenc(article: Article, data: bytearray, raw_data_size: int) -> bytearray:
|
||||
# Let SABCTools do all the heavy lifting
|
||||
yenc_filename, crc_correct = sabctools.yenc_decode(data)
|
||||
def decode_yenc(article: Article, raw_data: List[bytes]) -> bytes:
|
||||
# Let SABYenc do all the heavy lifting
|
||||
decoded_data, yenc_filename, crc_correct = sabyenc3.decode_usenet_chunks(raw_data)
|
||||
|
||||
# Mark as decoded
|
||||
article.decoded = True
|
||||
|
||||
nzf = article.nzf
|
||||
# Assume it is yenc
|
||||
nzf.type = "yenc"
|
||||
article.nzf.type = "yenc"
|
||||
|
||||
# Only set the name if it was found and not obfuscated
|
||||
if not nzf.filename_checked and yenc_filename:
|
||||
if not article.nzf.filename_checked and yenc_filename:
|
||||
# Set the md5-of-16k if this is the first article
|
||||
if article.lowest_partnum:
|
||||
nzf.md5of16k = hashlib.md5(data[:16384]).digest()
|
||||
article.nzf.md5of16k = hashlib.md5(decoded_data[:16384]).digest()
|
||||
|
||||
# Try the rename, even if it's not the first article
|
||||
# For example when the first article was missing
|
||||
nzf.nzo.verify_nzf_filename(nzf, yenc_filename)
|
||||
article.nzf.nzo.verify_nzf_filename(article.nzf, yenc_filename)
|
||||
|
||||
# CRC check
|
||||
if crc_correct is None:
|
||||
if not crc_correct:
|
||||
logging.info("CRC Error in %s", article.article)
|
||||
raise BadData(data)
|
||||
raise BadData(decoded_data)
|
||||
|
||||
article.crc32 = crc_correct
|
||||
|
||||
return data
|
||||
return decoded_data
|
||||
|
||||
|
||||
def decode_uu(article: Article, raw_data: bytearray) -> bytes:
|
||||
def decode_uu(article: Article, raw_data: List[bytes]) -> bytes:
|
||||
"""Try to uu-decode an article. The raw_data may or may not contain headers.
|
||||
If there are headers, they will be separated from the body by at least one
|
||||
empty line. In case of no headers, the first line seems to always be the nntp
|
||||
@@ -281,7 +275,10 @@ def decode_uu(article: Article, raw_data: bytearray) -> bytes:
|
||||
raise BadUu
|
||||
|
||||
# Line up the raw_data
|
||||
raw_data = raw_data.split(b"\r\n")
|
||||
with BytesIO() as encoded_data:
|
||||
for data in raw_data:
|
||||
encoded_data.write(data)
|
||||
raw_data = encoded_data.getvalue().split(b"\r\n")
|
||||
|
||||
# Index of the uu payload start in raw_data
|
||||
uu_start = 0
|
||||
@@ -295,7 +292,7 @@ def decode_uu(article: Article, raw_data: bytearray) -> bytes:
|
||||
# Try to find an empty line separating the body from headers or response
|
||||
# code and set the expected payload start to the next line.
|
||||
try:
|
||||
uu_start = raw_data[:limit].index(bytearray(b"")) + 1
|
||||
uu_start = raw_data[:limit].index(b"") + 1
|
||||
except ValueError:
|
||||
# No empty line, look for a response code instead
|
||||
if raw_data[0].startswith(b"222 "):
|
||||
@@ -376,8 +373,9 @@ def decode_uu(article: Article, raw_data: bytearray) -> bytes:
|
||||
# Store the decoded data
|
||||
decoded_data.write(decoded_line)
|
||||
|
||||
# Set the type to uu; the latter is still needed in
|
||||
# Mark as decoded and set the type to uu; the latter is still needed in
|
||||
# case the lowest_partnum article was damaged or slow to download.
|
||||
article.decoded = True
|
||||
article.nzf.type = "uu"
|
||||
|
||||
if article.lowest_partnum:
|
||||
@@ -387,9 +385,7 @@ def decode_uu(article: Article, raw_data: bytearray) -> bytes:
|
||||
if not article.nzf.filename_checked and uu_filename:
|
||||
article.nzf.nzo.verify_nzf_filename(article.nzf, uu_filename)
|
||||
|
||||
data = decoded_data.getvalue()
|
||||
article.crc32 = crc32(data)
|
||||
return data
|
||||
return decoded_data.getvalue()
|
||||
|
||||
|
||||
def search_new_server(article: Article) -> bool:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
|
||||
2
sabnzbd/deobfuscate_filenames.py
Normal file → Executable file
2
sabnzbd/deobfuscate_filenames.py
Normal file → Executable file
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -344,14 +344,10 @@ class DirectUnpacker(threading.Thread):
|
||||
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 nzf.assembled
|
||||
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.assembled
|
||||
):
|
||||
if nzf_search.setname == self.cur_setname and nzf_search.vol == (self.cur_volume + 1) and nzf_search.md5sum:
|
||||
return nzf_search
|
||||
return False
|
||||
|
||||
@@ -418,6 +414,7 @@ class DirectUnpacker(threading.Thread):
|
||||
"%s\\" % long_path(extraction_path),
|
||||
]
|
||||
else:
|
||||
# Don't use "-ai" (not needed for non-Windows)
|
||||
# The -scf forces the output to be UTF8
|
||||
command = [
|
||||
sabnzbd.newsunpack.RAR_COMMAND,
|
||||
@@ -426,7 +423,6 @@ class DirectUnpacker(threading.Thread):
|
||||
"-idp",
|
||||
"-scf",
|
||||
"-o+",
|
||||
"-ai",
|
||||
password_command,
|
||||
rarfile_path,
|
||||
"%s/" % extraction_path,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -19,11 +19,10 @@
|
||||
sabnzbd.dirscanner - Scanner for Watched Folder
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
import threading
|
||||
from typing import Generator, Set, Optional, Tuple
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.constants import SCAN_FILE_NAME, VALID_ARCHIVES, VALID_NZB_FILES
|
||||
@@ -31,9 +30,6 @@ import sabnzbd.filesystem as filesystem
|
||||
import sabnzbd.config as config
|
||||
import sabnzbd.cfg as cfg
|
||||
|
||||
DIR_SCANNER_LOCK = threading.RLock()
|
||||
VALID_EXTENSIONS = set(VALID_NZB_FILES + VALID_ARCHIVES)
|
||||
|
||||
|
||||
def compare_stat_tuple(tup1, tup2):
|
||||
"""Test equality of two stat-tuples, content-related parts only"""
|
||||
@@ -48,10 +44,18 @@ def compare_stat_tuple(tup1, tup2):
|
||||
return True
|
||||
|
||||
|
||||
async def clean_file_list(inp_list, files):
|
||||
def clean_file_list(inp_list, folder, files):
|
||||
"""Remove elements of "inp_list" not found in "files" """
|
||||
for path in set(inp_list.keys()).difference(files):
|
||||
del inp_list[path]
|
||||
for path in sorted(inp_list):
|
||||
fld, name = os.path.split(path)
|
||||
if fld == folder:
|
||||
present = False
|
||||
for name in files:
|
||||
if os.path.join(folder, name) == path:
|
||||
present = True
|
||||
break
|
||||
if not present:
|
||||
del inp_list[path]
|
||||
|
||||
|
||||
class DirScanner(threading.Thread):
|
||||
@@ -64,15 +68,7 @@ class DirScanner(threading.Thread):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
self.loop: Optional[asyncio.AbstractEventLoop] = None
|
||||
self.scanner_task: Optional[asyncio.Task] = None
|
||||
self.lock = asyncio.Lock() # Prevents concurrent scans
|
||||
self.error_reported = False # Prevents multiple reporting of missing watched folder
|
||||
self.dirscan_dir = cfg.dirscan_dir.get_path()
|
||||
self.dirscan_speed = cfg.dirscan_speed()
|
||||
cfg.dirscan_dir.callback(self.newdir)
|
||||
cfg.dirscan_speed.callback(self.newspeed)
|
||||
|
||||
self.newdir()
|
||||
try:
|
||||
dirscan_dir, self.ignored, self.suspected = sabnzbd.filesystem.load_admin(SCAN_FILE_NAME)
|
||||
if dirscan_dir != self.dirscan_dir:
|
||||
@@ -83,24 +79,34 @@ class DirScanner(threading.Thread):
|
||||
# successfully processed ones that cannot be deleted
|
||||
self.suspected = {} # Will hold name/attributes of suspected candidates
|
||||
|
||||
self.loop_condition = threading.Condition(threading.Lock())
|
||||
self.shutdown = False
|
||||
self.error_reported = False # Prevents multiple reporting of missing watched folder
|
||||
self.dirscan_dir = cfg.dirscan_dir.get_path()
|
||||
self.dirscan_speed = cfg.dirscan_speed() or None # If set to 0, use None so the wait() is forever
|
||||
self.busy = False
|
||||
cfg.dirscan_dir.callback(self.newdir)
|
||||
cfg.dirscan_speed.callback(self.newspeed)
|
||||
|
||||
def newdir(self):
|
||||
"""We're notified of a dir change"""
|
||||
self.ignored = {}
|
||||
self.suspected = {}
|
||||
self.dirscan_dir = cfg.dirscan_dir.get_path()
|
||||
|
||||
self.start_scanner()
|
||||
self.dirscan_speed = cfg.dirscan_speed()
|
||||
|
||||
def newspeed(self):
|
||||
"""We're notified of a scan speed change"""
|
||||
self.dirscan_speed = cfg.dirscan_speed()
|
||||
|
||||
self.start_scanner()
|
||||
# If set to 0, use None so the wait() is forever
|
||||
self.dirscan_speed = cfg.dirscan_speed() or None
|
||||
with self.loop_condition:
|
||||
self.loop_condition.notify()
|
||||
|
||||
def stop(self):
|
||||
"""Stop the dir scanner"""
|
||||
if self.loop:
|
||||
asyncio.run_coroutine_threadsafe(self.shutdown(), self.loop)
|
||||
self.shutdown = True
|
||||
with self.loop_condition:
|
||||
self.loop_condition.notify()
|
||||
|
||||
def save(self):
|
||||
"""Save dir scanner bookkeeping"""
|
||||
@@ -109,168 +115,99 @@ class DirScanner(threading.Thread):
|
||||
def run(self):
|
||||
"""Start the scanner"""
|
||||
logging.info("Dirscanner starting up")
|
||||
self.shutdown = False
|
||||
|
||||
self.loop = asyncio.new_event_loop()
|
||||
|
||||
try:
|
||||
self.start_scanner()
|
||||
self.loop.run_forever()
|
||||
finally:
|
||||
self.loop.close()
|
||||
|
||||
def start_scanner(self):
|
||||
"""Start the scanner if it is not already running"""
|
||||
with DIR_SCANNER_LOCK:
|
||||
if not self.loop:
|
||||
logging.debug("Can not start scanner because loop not found")
|
||||
return
|
||||
|
||||
if not self.scanner_task or self.scanner_task.done():
|
||||
self.scanner_task = asyncio.run_coroutine_threadsafe(self.scanner(), self.loop)
|
||||
|
||||
def get_suspected_files(
|
||||
self, folder: str, catdir: Optional[str] = None
|
||||
) -> Generator[Tuple[str, Optional[str], Optional[os.stat_result]], None, None]:
|
||||
"""Generator listing possible paths to NZB files"""
|
||||
|
||||
if catdir is None:
|
||||
cats = config.get_categories()
|
||||
else:
|
||||
cats = {}
|
||||
|
||||
try:
|
||||
with os.scandir(os.path.join(folder, catdir or "")) as it:
|
||||
for entry in it:
|
||||
path = entry.path
|
||||
|
||||
if path in self.ignored:
|
||||
# We still need to know that an ignored file is still present when we clean up
|
||||
yield path, catdir, None
|
||||
continue
|
||||
|
||||
# If the entry is a catdir then recursion
|
||||
if entry.is_dir():
|
||||
if not catdir and entry.name.lower() in cats:
|
||||
yield from self.get_suspected_files(folder, entry.name)
|
||||
continue
|
||||
|
||||
if filesystem.get_ext(path) in VALID_EXTENSIONS:
|
||||
try:
|
||||
# https://docs.python.org/3/library/os.html#os.DirEntry.stat
|
||||
# On Windows, the st_ino, st_dev and st_nlink attributes of the stat_result are always set
|
||||
# to zero. Call os.stat() to get these attributes.
|
||||
if sabnzbd.WIN32:
|
||||
stat_tuple = os.stat(path)
|
||||
else:
|
||||
stat_tuple = entry.stat()
|
||||
except OSError:
|
||||
continue
|
||||
else:
|
||||
self.ignored[path] = 1
|
||||
yield path, catdir, None
|
||||
continue
|
||||
|
||||
if path in self.suspected:
|
||||
if not compare_stat_tuple(self.suspected[path], stat_tuple):
|
||||
# Suspected file attributes have changed
|
||||
del self.suspected[path]
|
||||
|
||||
yield path, catdir, stat_tuple
|
||||
except:
|
||||
if not self.error_reported and not catdir:
|
||||
logging.error(T("Cannot read Watched Folder %s"), filesystem.clip_path(folder))
|
||||
logging.info("Traceback: ", exc_info=True)
|
||||
self.error_reported = True
|
||||
|
||||
async def when_stable_add_nzbfile(self, path: str, catdir: Optional[str], stat_tuple: os.stat_result):
|
||||
"""Try and import the NZB but wait until the attributes are stable for 1 second, but give up after 3 sec"""
|
||||
|
||||
logging.info("Trying to import %s", path)
|
||||
|
||||
# Wait until the attributes are stable for 1 second, but give up after 3 sec
|
||||
# This indicates that the file is fully written to disk
|
||||
for n in range(3):
|
||||
await asyncio.sleep(1.0)
|
||||
|
||||
try:
|
||||
stat_tuple_tmp = os.stat(path)
|
||||
except OSError:
|
||||
continue
|
||||
if compare_stat_tuple(stat_tuple, stat_tuple_tmp):
|
||||
break
|
||||
stat_tuple = stat_tuple_tmp
|
||||
else:
|
||||
# Not stable
|
||||
return
|
||||
|
||||
# Add the NZB's
|
||||
res, _ = sabnzbd.nzbparser.add_nzbfile(path, catdir=catdir, keep=False)
|
||||
if res < 0:
|
||||
# Retry later, for example when we can't read the file
|
||||
self.suspected[path] = stat_tuple
|
||||
elif res == 0:
|
||||
self.error_reported = False
|
||||
else:
|
||||
self.ignored[path] = 1
|
||||
while not self.shutdown:
|
||||
# Wait to be woken up or triggered
|
||||
with self.loop_condition:
|
||||
self.loop_condition.wait(self.dirscan_speed)
|
||||
if self.dirscan_speed and not self.shutdown:
|
||||
self.scan()
|
||||
|
||||
def scan(self):
|
||||
"""Schedule a scan of the watched folder"""
|
||||
if not self.loop:
|
||||
return
|
||||
|
||||
if not (dirscan_dir := self.dirscan_dir):
|
||||
return
|
||||
|
||||
asyncio.run_coroutine_threadsafe(self.scan_async(dirscan_dir), self.loop)
|
||||
|
||||
async def scan_async(self, dirscan_dir: str):
|
||||
"""Do one scan of the watched folder"""
|
||||
async with self.lock:
|
||||
if sabnzbd.PAUSED_ALL:
|
||||
return
|
||||
|
||||
files: Set[str] = set()
|
||||
futures: Set[asyncio.Task] = set()
|
||||
def run_dir(folder, catdir):
|
||||
try:
|
||||
files = os.listdir(folder)
|
||||
except OSError:
|
||||
if not self.error_reported and not catdir:
|
||||
logging.error(T("Cannot read Watched Folder %s"), filesystem.clip_path(folder))
|
||||
self.error_reported = True
|
||||
files = []
|
||||
|
||||
for path, catdir, stat_tuple in self.get_suspected_files(dirscan_dir):
|
||||
files.add(path)
|
||||
|
||||
if path in self.ignored or path in self.suspected:
|
||||
for filename in files:
|
||||
if self.shutdown:
|
||||
break
|
||||
path = os.path.join(folder, filename)
|
||||
if os.path.isdir(path) or path in self.ignored or filename[0] == ".":
|
||||
continue
|
||||
|
||||
if filesystem.get_ext(path) in VALID_NZB_FILES + VALID_ARCHIVES:
|
||||
try:
|
||||
stat_tuple = os.stat(path)
|
||||
except OSError:
|
||||
continue
|
||||
else:
|
||||
self.ignored[path] = 1
|
||||
continue
|
||||
|
||||
if path in self.suspected:
|
||||
if compare_stat_tuple(self.suspected[path], stat_tuple):
|
||||
# Suspected file still has the same attributes
|
||||
continue
|
||||
else:
|
||||
del self.suspected[path]
|
||||
|
||||
if stat_tuple.st_size > 0:
|
||||
futures.add(asyncio.create_task(self.when_stable_add_nzbfile(path, catdir, stat_tuple)))
|
||||
await asyncio.sleep(0)
|
||||
logging.info("Trying to import %s", path)
|
||||
|
||||
# Wait until the attributes are stable for 1 second, but give up after 3 sec
|
||||
# This indicates that the file is fully written to disk
|
||||
for n in range(3):
|
||||
time.sleep(1.0)
|
||||
try:
|
||||
stat_tuple_tmp = os.stat(path)
|
||||
except OSError:
|
||||
continue
|
||||
if compare_stat_tuple(stat_tuple, stat_tuple_tmp):
|
||||
break
|
||||
stat_tuple = stat_tuple_tmp
|
||||
else:
|
||||
# Not stable
|
||||
continue
|
||||
|
||||
# Add the NZB's
|
||||
res, _ = sabnzbd.nzbparser.add_nzbfile(path, catdir=catdir, keep=False)
|
||||
if res < 0:
|
||||
# Retry later, for example when we can't read the file
|
||||
self.suspected[path] = stat_tuple
|
||||
elif res == 0:
|
||||
self.error_reported = False
|
||||
else:
|
||||
self.ignored[path] = 1
|
||||
|
||||
# Remove files from the bookkeeping that are no longer on the disk
|
||||
# Wait for the paths found in this scan to finish
|
||||
await asyncio.gather(clean_file_list(self.ignored, files), clean_file_list(self.suspected, files), *futures)
|
||||
clean_file_list(self.ignored, folder, files)
|
||||
clean_file_list(self.suspected, folder, files)
|
||||
|
||||
async def scanner(self):
|
||||
"""Periodically scan the directory and add NZB files to the queue"""
|
||||
while True:
|
||||
if not (dirscan_speed := self.dirscan_speed):
|
||||
break
|
||||
if not self.busy:
|
||||
self.busy = True
|
||||
dirscan_dir = self.dirscan_dir
|
||||
if dirscan_dir and not sabnzbd.PAUSED_ALL:
|
||||
run_dir(dirscan_dir, None)
|
||||
|
||||
if not (dirscan_dir := self.dirscan_dir):
|
||||
break
|
||||
try:
|
||||
dirscan_list = os.listdir(dirscan_dir)
|
||||
except OSError:
|
||||
if not self.error_reported:
|
||||
logging.error(T("Cannot read Watched Folder %s"), filesystem.clip_path(dirscan_dir))
|
||||
self.error_reported = True
|
||||
dirscan_list = []
|
||||
|
||||
await self.scan_async(dirscan_dir)
|
||||
|
||||
await asyncio.sleep(dirscan_speed)
|
||||
|
||||
async def shutdown(self):
|
||||
"""Cancel all tasks and stop the loop"""
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
# Get all tasks except for this one
|
||||
tasks = filter(lambda task: task is not asyncio.current_task(), asyncio.all_tasks())
|
||||
|
||||
# Cancel them all
|
||||
for task in tasks:
|
||||
task.cancel()
|
||||
|
||||
# Wait for the tasks to be done
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
loop.stop()
|
||||
cats = config.get_categories()
|
||||
for dd in dirscan_list:
|
||||
dpath = os.path.join(dirscan_dir, dd)
|
||||
if os.path.isdir(dpath) and dd.lower() in cats:
|
||||
run_dir(dpath, dd.lower())
|
||||
self.busy = False
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -29,16 +29,14 @@ import random
|
||||
import sys
|
||||
import ssl
|
||||
from typing import List, Dict, Optional, Union
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
import sabnzbd
|
||||
from sabnzbd.decorators import synchronized, NzbQueueLocker, DOWNLOADER_CV
|
||||
from sabnzbd.newswrapper import NewsWrapper, NNTPPermanentError
|
||||
import sabnzbd.config as config
|
||||
import sabnzbd.cfg as cfg
|
||||
from sabnzbd.misc import from_units, get_server_addrinfo, helpful_warning, int_conv
|
||||
from sabnzbd.misc import from_units, nntp_to_msg, get_server_addrinfo, helpful_warning, int_conv
|
||||
from sabnzbd.utils.happyeyeballs import happyeyeballs
|
||||
from sabnzbd.constants import SOFT_QUEUE_LIMIT
|
||||
|
||||
|
||||
# Timeout penalty in minutes for each cause
|
||||
@@ -57,8 +55,6 @@ _SERVER_CHECK_DELAY = 0.5
|
||||
_BPSMETER_UPDATE_DELAY = 0.05
|
||||
# How many articles should be prefetched when checking the next articles?
|
||||
_ARTICLE_PREFETCH = 20
|
||||
# Minimum expected size of TCP receive buffer
|
||||
_DEFAULT_CHUNK_SIZE = 32768
|
||||
|
||||
TIMER_LOCK = RLock()
|
||||
|
||||
@@ -120,6 +116,7 @@ class Server:
|
||||
optional=False,
|
||||
retention=0,
|
||||
):
|
||||
|
||||
self.id: str = server_id
|
||||
self.newid: Optional[str] = None
|
||||
self.restart: bool = False
|
||||
@@ -221,28 +218,6 @@ class Server:
|
||||
self.request = True
|
||||
Thread(target=self._request_info_internal).start()
|
||||
|
||||
def get_article(self):
|
||||
"""Get article from pre-fetched and pre-fetch new ones if necessary.
|
||||
Articles that are too old for this server are immediately marked as tried"""
|
||||
if self.article_queue:
|
||||
return self.article_queue.pop(0)
|
||||
elif self.next_article_search < time.time():
|
||||
# Pre-fetch new articles
|
||||
self.article_queue = sabnzbd.NzbQueue.get_articles(self, sabnzbd.Downloader.servers, _ARTICLE_PREFETCH)
|
||||
if self.article_queue:
|
||||
article = self.article_queue.pop(0)
|
||||
# Mark expired articles as tried on this server
|
||||
if self.retention and article.nzf.nzo.avg_stamp < time.time() - self.retention:
|
||||
sabnzbd.Downloader.decode(article)
|
||||
while self.article_queue:
|
||||
sabnzbd.Downloader.decode(self.article_queue.pop())
|
||||
else:
|
||||
return article
|
||||
else:
|
||||
# No available articles, skip this server for a short time
|
||||
self.next_article_search = time.time() + _SERVER_CHECK_DELAY
|
||||
return None
|
||||
|
||||
def reset_article_queue(self):
|
||||
logging.debug("Resetting article queue for %s", self)
|
||||
for article in self.article_queue:
|
||||
@@ -275,8 +250,6 @@ class Downloader(Thread):
|
||||
"bandwidth_limit",
|
||||
"bandwidth_perc",
|
||||
"sleep_time",
|
||||
"recv_pool",
|
||||
"recv_threads",
|
||||
"paused_for_postproc",
|
||||
"shutdown",
|
||||
"server_restarts",
|
||||
@@ -306,10 +279,6 @@ class Downloader(Thread):
|
||||
self.sleep_time_set()
|
||||
cfg.downloader_sleep_time.callback(self.sleep_time_set)
|
||||
|
||||
self.recv_threads: int = cfg.receive_threads()
|
||||
self.recv_pool: Optional[ThreadPoolExecutor] = ThreadPoolExecutor(self.recv_threads)
|
||||
logging.debug("Receive threads: %s", self.recv_threads)
|
||||
|
||||
self.paused_for_postproc: bool = False
|
||||
self.shutdown: bool = False
|
||||
|
||||
@@ -534,7 +503,7 @@ class Downloader(Thread):
|
||||
# Make sure server address resolution is refreshed
|
||||
server.info = None
|
||||
|
||||
def decode(self, article, raw_data: Optional[bytearray] = None, raw_data_size: Optional[int] = None):
|
||||
def decode(self, article, raw_data: Optional[List[bytes]] = None, data_size: Optional[int] = None):
|
||||
"""Decode article and check the status of
|
||||
the decoder and the assembler
|
||||
"""
|
||||
@@ -549,45 +518,39 @@ class Downloader(Thread):
|
||||
return
|
||||
|
||||
# Send to decoder-queue
|
||||
sabnzbd.Decoder.process(article, raw_data, raw_data_size)
|
||||
sabnzbd.Decoder.process(article, raw_data, data_size)
|
||||
|
||||
# See if we need to delay because the queues are full
|
||||
logged_counter = 0
|
||||
decoder_full = sabnzbd.Decoder.queue_full()
|
||||
assembler_full = sabnzbd.Assembler.queue_full()
|
||||
while not self.shutdown and (decoder_full or assembler_full):
|
||||
# Only log/update once every second, to not waste any CPU-cycles
|
||||
if not logged_counter % 10:
|
||||
# Make sure the BPS-meter is updated
|
||||
sabnzbd.BPSMeter.update()
|
||||
|
||||
decoder_level = sabnzbd.Decoder.queue_level()
|
||||
assembler_level = sabnzbd.Assembler.queue_level()
|
||||
# Update who is delaying us
|
||||
sabnzbd.BPSMeter.delayed_decoder += int(decoder_full)
|
||||
sabnzbd.BPSMeter.delayed_assembler += int(assembler_full)
|
||||
logging.debug(
|
||||
"Delayed - %d seconds - Decoder queue: %d - Assembler queue: %d",
|
||||
logged_counter / 10,
|
||||
sabnzbd.Decoder.decoder_queue.qsize(),
|
||||
sabnzbd.Assembler.queue.qsize(),
|
||||
)
|
||||
|
||||
# Sleep for an increasing amount of time, depending on queue sizes.
|
||||
if decoder_level > SOFT_QUEUE_LIMIT or assembler_level > SOFT_QUEUE_LIMIT:
|
||||
time.sleep((decoder_level + assembler_level - SOFT_QUEUE_LIMIT) / 2)
|
||||
sabnzbd.BPSMeter.delayed_decoder += int(decoder_level > SOFT_QUEUE_LIMIT)
|
||||
sabnzbd.BPSMeter.delayed_assembler += int(assembler_level > SOFT_QUEUE_LIMIT)
|
||||
|
||||
while not self.shutdown and (sabnzbd.Decoder.queue_level() >= 1 or sabnzbd.Assembler.queue_level() >= 1):
|
||||
# Only log/update once every second, to not waste any CPU-cycles
|
||||
if not logged_counter % 10:
|
||||
# Make sure the BPS-meter is updated
|
||||
sabnzbd.BPSMeter.update()
|
||||
|
||||
# Update who is delaying us
|
||||
logging.debug(
|
||||
"Delayed - %d seconds - Decoder queue: %d - Assembler queue: %d",
|
||||
logged_counter / 10,
|
||||
sabnzbd.Decoder.decoder_queue.qsize(),
|
||||
sabnzbd.Assembler.queue.qsize(),
|
||||
)
|
||||
|
||||
# Wait and update the queue sizes
|
||||
time.sleep(0.1)
|
||||
logged_counter += 1
|
||||
# Wait and update the queue sizes
|
||||
time.sleep(0.1)
|
||||
logged_counter += 1
|
||||
decoder_full = sabnzbd.Decoder.queue_full()
|
||||
assembler_full = sabnzbd.Assembler.queue_full()
|
||||
|
||||
def run(self):
|
||||
# First check IPv6 connectivity
|
||||
sabnzbd.EXTERNAL_IPV6 = sabnzbd.misc.test_ipv6()
|
||||
logging.debug("External IPv6 test result: %s", sabnzbd.EXTERNAL_IPV6)
|
||||
|
||||
logging.debug("switchinterval = %s", sys.getswitchinterval())
|
||||
|
||||
# Then we check SSL certificate checking
|
||||
sabnzbd.CERTIFICATE_VALIDATION = sabnzbd.misc.test_cert_checking()
|
||||
logging.debug("SSL verification test: %s", sabnzbd.CERTIFICATE_VALIDATION)
|
||||
@@ -601,13 +564,10 @@ class Downloader(Thread):
|
||||
BPSMeter.update()
|
||||
next_bpsmeter_update = 0
|
||||
|
||||
# Sleep check variables
|
||||
last_max_chunk_size: int = 0
|
||||
max_chunk_size: int = _DEFAULT_CHUNK_SIZE
|
||||
# Debugging code for v4 test release
|
||||
sleep_count_start: float = time.time()
|
||||
sleep_count: int = 0
|
||||
time_slept: float = 0
|
||||
# can_be_slowed variables
|
||||
can_be_slowed: Optional[float] = None
|
||||
can_be_slowed_timer: float = 0.0
|
||||
next_stable_speed_check: float = 0.0
|
||||
|
||||
# Check server expiration dates
|
||||
check_server_expiration()
|
||||
@@ -673,13 +633,32 @@ class Downloader(Thread):
|
||||
server.request_info()
|
||||
break
|
||||
|
||||
nw.article = server.get_article()
|
||||
if not nw.article:
|
||||
break
|
||||
# Get article from pre-fetched ones or fetch new ones
|
||||
if server.article_queue:
|
||||
article = server.article_queue.pop(0)
|
||||
else:
|
||||
# Pre-fetch new articles
|
||||
server.article_queue = sabnzbd.NzbQueue.get_articles(server, self.servers, _ARTICLE_PREFETCH)
|
||||
if server.article_queue:
|
||||
article = server.article_queue.pop(0)
|
||||
# Mark expired articles as tried on this server
|
||||
if server.retention and article.nzf.nzo.avg_stamp < now - server.retention:
|
||||
self.decode(article)
|
||||
while server.article_queue:
|
||||
self.decode(server.article_queue.pop())
|
||||
# Move to the next server, allowing the next server to already start
|
||||
# fetching the articles that were too old for this server
|
||||
break
|
||||
else:
|
||||
# Skip this server for a short time
|
||||
server.next_article_search = now + _SERVER_CHECK_DELAY
|
||||
break
|
||||
|
||||
server.idle_threads.remove(nw)
|
||||
server.busy_threads.append(nw)
|
||||
|
||||
nw.article = article
|
||||
|
||||
if nw.connected:
|
||||
self.__request_article(nw)
|
||||
else:
|
||||
@@ -716,44 +695,43 @@ class Downloader(Thread):
|
||||
logging.info("Shutting down")
|
||||
break
|
||||
|
||||
# If less data than possible was received then it should be ok to sleep a bit
|
||||
if self.sleep_time:
|
||||
if last_max_chunk_size > max_chunk_size:
|
||||
logging.debug("New max_chunk_size %d -> %d", max_chunk_size, last_max_chunk_size)
|
||||
max_chunk_size = last_max_chunk_size
|
||||
elif last_max_chunk_size < max_chunk_size / 3:
|
||||
time_before = time.time()
|
||||
time.sleep(self.sleep_time)
|
||||
now = time.time()
|
||||
# Debugging code for v4 test release
|
||||
if now - time_before > self.sleep_time + 0.02:
|
||||
logging.debug("Slept %.5f seconds, sleep_time = %s", now - time_before, self.sleep_time)
|
||||
time_slept += now - time_before
|
||||
sleep_count += 1
|
||||
if sleep_count_start + 20 < now:
|
||||
if sleep_count > 21:
|
||||
logging.debug(
|
||||
"Slept %d times for an average of %.5f seconds the last %.2f seconds. sleep_time = %s",
|
||||
sleep_count,
|
||||
time_slept / sleep_count,
|
||||
now - sleep_count_start,
|
||||
self.sleep_time,
|
||||
)
|
||||
sleep_count_start = now
|
||||
sleep_count = 0
|
||||
time_slept = 0
|
||||
|
||||
last_max_chunk_size = 0
|
||||
|
||||
# Use select to find sockets ready for reading/writing
|
||||
readkeys = self.read_fds.keys()
|
||||
if readkeys:
|
||||
read, _, _ = select.select(readkeys, (), (), 1.0)
|
||||
|
||||
# Add a sleep if there are too few results compared to the number of active connections
|
||||
if self.sleep_time:
|
||||
if can_be_slowed and len(read) < 1 + len(readkeys) / 10:
|
||||
time.sleep(self.sleep_time)
|
||||
|
||||
# Initialize by waiting for stable speed and then enable sleep
|
||||
if can_be_slowed is None or can_be_slowed_timer:
|
||||
# Wait for stable speed to start testing
|
||||
|
||||
if not can_be_slowed_timer and now > next_stable_speed_check:
|
||||
if BPSMeter.get_stable_speed(timespan=10):
|
||||
can_be_slowed_timer = now + 8
|
||||
can_be_slowed = 1
|
||||
else:
|
||||
next_stable_speed_check = now + _BPSMETER_UPDATE_DELAY
|
||||
|
||||
# Check 10 seconds after enabling slowdown
|
||||
if can_be_slowed_timer and now > can_be_slowed_timer:
|
||||
# Now let's check if it was stable in the last 10 seconds
|
||||
can_be_slowed = BPSMeter.get_stable_speed(timespan=10)
|
||||
can_be_slowed_timer = 0
|
||||
if not can_be_slowed:
|
||||
self.sleep_time = 0
|
||||
logging.debug("Downloader-slowdown: %r", can_be_slowed)
|
||||
|
||||
else:
|
||||
read = []
|
||||
|
||||
BPSMeter.reset()
|
||||
|
||||
time.sleep(1.0)
|
||||
max_chunk_size = _DEFAULT_CHUNK_SIZE
|
||||
|
||||
with DOWNLOADER_CV:
|
||||
while (
|
||||
(sabnzbd.NzbQueue.is_empty() or self.no_active_jobs() or self.paused_for_postproc)
|
||||
@@ -770,196 +748,184 @@ class Downloader(Thread):
|
||||
if not read:
|
||||
continue
|
||||
|
||||
if self.recv_threads > 1:
|
||||
for nw, bytes_received, done in self.recv_pool.map(self.__recv, read):
|
||||
if bytes_received > last_max_chunk_size:
|
||||
last_max_chunk_size = bytes_received
|
||||
self.__handle_recv_result(nw, bytes_received, done)
|
||||
if self.bandwidth_limit:
|
||||
self.__check_speed()
|
||||
else:
|
||||
for selected in read:
|
||||
nw, bytes_received, done = self.__recv(selected)
|
||||
if bytes_received > last_max_chunk_size:
|
||||
last_max_chunk_size = bytes_received
|
||||
self.__handle_recv_result(nw, bytes_received, done)
|
||||
if self.bandwidth_limit and bytes_received:
|
||||
self.__check_speed()
|
||||
for selected in read:
|
||||
nw = self.read_fds[selected]
|
||||
article = nw.article
|
||||
server = nw.server
|
||||
|
||||
def __recv(self, selected):
|
||||
nw = None
|
||||
try:
|
||||
nw = self.read_fds[selected]
|
||||
bytes_received, done = nw.recv_chunk()
|
||||
return nw, bytes_received, done
|
||||
except ssl.SSLWantReadError:
|
||||
return nw, 0, False
|
||||
except:
|
||||
return nw, 0, True
|
||||
try:
|
||||
bytes_received, done, skip = nw.recv_chunk()
|
||||
except:
|
||||
bytes_received, done, skip = (0, False, False)
|
||||
|
||||
def __check_speed(self):
|
||||
BPSMeter = sabnzbd.BPSMeter
|
||||
if BPSMeter.bps + BPSMeter.sum_cached_amount > self.bandwidth_limit:
|
||||
BPSMeter.update()
|
||||
while BPSMeter.bps > self.bandwidth_limit:
|
||||
time.sleep(0.01)
|
||||
BPSMeter.update()
|
||||
if skip:
|
||||
continue
|
||||
|
||||
def __handle_recv_result(self, nw: NewsWrapper, bytes_received: int = 0, done: bool = False):
|
||||
if not bytes_received:
|
||||
if done:
|
||||
self.__reset_nw(nw, "server closed connection", wait=False)
|
||||
return
|
||||
|
||||
article = nw.article
|
||||
server = nw.server
|
||||
sabnzbd.BPSMeter.update(server.id, bytes_received)
|
||||
|
||||
if nw.status_code != 222 and not done:
|
||||
if not nw.connected or nw.status_code == 480:
|
||||
if not self.__finish_connect_nw(nw):
|
||||
return
|
||||
if nw.connected:
|
||||
logging.info("Connecting %s@%s finished", nw.thrdnum, nw.server.host)
|
||||
self.__request_article(nw)
|
||||
|
||||
elif nw.status_code == 223:
|
||||
done = True
|
||||
logging.debug("Article <%s> is present", article.article)
|
||||
|
||||
elif nw.status_code == 211:
|
||||
logging.debug("group command ok -> %s", nw.nntp_msg)
|
||||
nw.group = nw.article.nzf.nzo.group
|
||||
nw.reset_data_buffer()
|
||||
self.__request_article(nw)
|
||||
|
||||
elif nw.status_code in (411, 423, 430):
|
||||
done = True
|
||||
logging.debug(
|
||||
"Thread %s@%s: Article %s missing (error=%s)",
|
||||
nw.thrdnum,
|
||||
nw.server.host,
|
||||
article.article,
|
||||
nw.status_code,
|
||||
)
|
||||
nw.reset_data_buffer()
|
||||
|
||||
elif nw.status_code == 500:
|
||||
if article.nzf.nzo.precheck:
|
||||
# Assume "STAT" command is not supported
|
||||
server.have_stat = False
|
||||
logging.debug("Server %s does not support STAT", server.host)
|
||||
if bytes_received < 1:
|
||||
self.__reset_nw(nw, "server closed connection", wait=False)
|
||||
continue
|
||||
else:
|
||||
# Assume "BODY" command is not supported
|
||||
server.have_body = False
|
||||
logging.debug("Server %s does not support BODY", server.host)
|
||||
nw.reset_data_buffer()
|
||||
self.__request_article(nw)
|
||||
BPSMeter.update(server.id, bytes_received)
|
||||
|
||||
if done:
|
||||
# Successful data, clear "bad" counter
|
||||
server.bad_cons = 0
|
||||
server.errormsg = server.warning = ""
|
||||
if self.bandwidth_limit:
|
||||
if BPSMeter.bps + BPSMeter.sum_cached_amount > self.bandwidth_limit:
|
||||
BPSMeter.update()
|
||||
while BPSMeter.bps > self.bandwidth_limit:
|
||||
time.sleep(0.01)
|
||||
BPSMeter.update()
|
||||
|
||||
# Update statistics and decode
|
||||
article.nzf.nzo.update_download_stats(sabnzbd.BPSMeter.bps, server.id, nw.data_position)
|
||||
self.decode(article, nw.get_data_buffer(), nw.data_position)
|
||||
if nw.status_code != 222 and not done:
|
||||
if not nw.connected or nw.status_code == 480:
|
||||
try:
|
||||
nw.finish_connect(nw.status_code)
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug(
|
||||
"%s@%s last message -> %s", nw.thrdnum, nw.server.host, nntp_to_msg(nw.data)
|
||||
)
|
||||
nw.clear_data()
|
||||
except NNTPPermanentError as error:
|
||||
# Handle login problems
|
||||
block = False
|
||||
penalty = 0
|
||||
display_msg = " [%s]" % error.msg
|
||||
logging.debug("Server login problem: %s", error.msg)
|
||||
if error.code in (502, 400, 481, 482) and clues_too_many(error.msg):
|
||||
# Too many connections: remove this thread and reduce thread-setting for server
|
||||
# Plan to go back to the full number after a penalty timeout
|
||||
if server.active:
|
||||
errormsg = T("Too many connections to server %s") % display_msg
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(T("Too many connections to server %s"), server.host)
|
||||
# Don't count this for the tries (max_art_tries) on this server
|
||||
self.__reset_nw(nw, send_quit=True)
|
||||
self.plan_server(server, _PENALTY_TOOMANY)
|
||||
server.threads -= 1
|
||||
elif error.code in (502, 481, 482) and clues_too_many_ip(error.msg):
|
||||
# Account sharing?
|
||||
if server.active:
|
||||
errormsg = T("Probable account sharing") + display_msg
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
name = " (%s)" % server.host
|
||||
logging.warning(T("Probable account sharing") + name)
|
||||
penalty = _PENALTY_SHARE
|
||||
block = True
|
||||
elif error.code in (452, 481, 482, 381) or (
|
||||
error.code in (500, 502) and clues_login(error.msg)
|
||||
):
|
||||
# Cannot login, block this server
|
||||
if server.active:
|
||||
errormsg = T("Failed login for server %s") % display_msg
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.error(T("Failed login for server %s"), server.host)
|
||||
penalty = _PENALTY_PERM
|
||||
block = True
|
||||
elif error.code in (502, 482):
|
||||
# Cannot connect (other reasons), block this server
|
||||
if server.active:
|
||||
errormsg = T("Cannot connect to server %s [%s]") % ("", error.msg)
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(T("Cannot connect to server %s [%s]"), server.host, error.msg)
|
||||
if clues_pay(error.msg):
|
||||
penalty = _PENALTY_PERM
|
||||
else:
|
||||
penalty = _PENALTY_502
|
||||
block = True
|
||||
elif error.code == 400:
|
||||
# Temp connection problem?
|
||||
if server.active:
|
||||
logging.debug("Unspecified error 400 from server %s", server.host)
|
||||
penalty = _PENALTY_VERYSHORT
|
||||
block = True
|
||||
else:
|
||||
# Unknown error, just keep trying
|
||||
if server.active:
|
||||
errormsg = T("Cannot connect to server %s [%s]") % ("", display_msg)
|
||||
if server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(T("Cannot connect to server %s [%s]"), server.host, error.msg)
|
||||
penalty = _PENALTY_UNKNOWN
|
||||
block = True
|
||||
if block or (penalty and server.optional):
|
||||
retry_article = False
|
||||
if server.active:
|
||||
if server.required:
|
||||
sabnzbd.Scheduler.plan_required_server_resume()
|
||||
retry_article = True
|
||||
else:
|
||||
server.deactivate()
|
||||
if penalty and (block or server.optional):
|
||||
self.plan_server(server, penalty)
|
||||
# Note that the article is discard for this server if the server is not required
|
||||
self.__reset_nw(nw, retry_article=retry_article, send_quit=True)
|
||||
continue
|
||||
except:
|
||||
logging.error(
|
||||
T("Connecting %s@%s failed, message=%s"),
|
||||
nw.thrdnum,
|
||||
nw.server.host,
|
||||
nntp_to_msg(nw.data),
|
||||
)
|
||||
# No reset-warning needed, above logging is sufficient
|
||||
self.__reset_nw(nw, retry_article=False)
|
||||
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug("Thread %s@%s: %s done", nw.thrdnum, server.host, article.article)
|
||||
if nw.connected:
|
||||
logging.info("Connecting %s@%s finished", nw.thrdnum, nw.server.host)
|
||||
self.__request_article(nw)
|
||||
|
||||
# Reset connection for new activity
|
||||
nw.soft_reset()
|
||||
# Request a new article immediately if possible
|
||||
if nw.connected and server.active and not (self.paused or self.shutdown or self.paused_for_postproc):
|
||||
nw.article = server.get_article()
|
||||
if nw.article:
|
||||
self.__request_article(nw)
|
||||
return
|
||||
server.busy_threads.remove(nw)
|
||||
server.idle_threads.append(nw)
|
||||
self.remove_socket(nw)
|
||||
elif nw.status_code == 223:
|
||||
done = True
|
||||
logging.debug("Article <%s> is present", article.article)
|
||||
|
||||
def __finish_connect_nw(self, nw: NewsWrapper) -> bool:
|
||||
server = nw.server
|
||||
try:
|
||||
nw.finish_connect(nw.status_code)
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug("%s@%s last message -> %s", nw.thrdnum, server.host, nw.nntp_msg)
|
||||
nw.reset_data_buffer()
|
||||
except NNTPPermanentError as error:
|
||||
# Handle login problems
|
||||
block = False
|
||||
penalty = 0
|
||||
errormsg = None
|
||||
logging.debug("Server login problem: %s", error.msg)
|
||||
if error.code in (502, 400, 481, 482) and clues_too_many(error.msg):
|
||||
# Too many connections: remove this thread and reduce thread-setting for server
|
||||
# Plan to go back to the full number after a penalty timeout
|
||||
errormsg = T("Too many connections to server %s [%s]") % (server.host, error.msg)
|
||||
if server.active:
|
||||
# Don't count this for the tries (max_art_tries) on this server
|
||||
self.__reset_nw(nw, send_quit=True)
|
||||
self.plan_server(server, _PENALTY_TOOMANY)
|
||||
server.threads -= 1
|
||||
elif error.code in (502, 481, 482) and clues_too_many_ip(error.msg):
|
||||
# Login from (too many) different IP addresses
|
||||
errormsg = T(
|
||||
"Login from too many different IP addresses to server %s [%s] - https://sabnzbd.org/multiple-adresses"
|
||||
) % (server.host, error.msg)
|
||||
penalty = _PENALTY_SHARE
|
||||
block = True
|
||||
elif error.code in (452, 481, 482, 381) or (error.code in (500, 502) and clues_login(error.msg)):
|
||||
# Cannot login, block this server
|
||||
errormsg = T("Failed login for server %s [%s]") % (server.host, error.msg)
|
||||
penalty = _PENALTY_PERM
|
||||
block = True
|
||||
elif error.code in (502, 482):
|
||||
# Cannot connect (other reasons), block this server
|
||||
errormsg = T("Cannot connect to server %s [%s]") % (server.host, error.msg)
|
||||
if clues_pay(error.msg):
|
||||
penalty = _PENALTY_PERM
|
||||
else:
|
||||
penalty = _PENALTY_502
|
||||
block = True
|
||||
elif error.code == 400:
|
||||
# Temp connection problem?
|
||||
logging.debug("Unspecified error 400 from server %s", server.host)
|
||||
penalty = _PENALTY_VERYSHORT
|
||||
block = True
|
||||
else:
|
||||
# Unknown error, just keep trying
|
||||
errormsg = T("Cannot connect to server %s [%s]") % (server.host, error.msg)
|
||||
penalty = _PENALTY_UNKNOWN
|
||||
block = True
|
||||
if block or (penalty and server.optional):
|
||||
retry_article = False
|
||||
if server.active:
|
||||
if server.required:
|
||||
sabnzbd.Scheduler.plan_required_server_resume()
|
||||
retry_article = True
|
||||
else:
|
||||
server.deactivate()
|
||||
if penalty and (block or server.optional):
|
||||
self.plan_server(server, penalty)
|
||||
# Note that the article is discard for this server if the server is not required
|
||||
self.__reset_nw(nw, retry_article=retry_article, send_quit=True)
|
||||
elif nw.status_code == 211:
|
||||
logging.debug("group command ok -> %s", nntp_to_msg(nw.data))
|
||||
nw.group = nw.article.nzf.nzo.group
|
||||
nw.clear_data()
|
||||
self.__request_article(nw)
|
||||
|
||||
# Set error for server and warn user if it was first time thrown
|
||||
if errormsg and server.active and server.errormsg != errormsg:
|
||||
server.errormsg = errormsg
|
||||
logging.warning(errormsg)
|
||||
return False
|
||||
except:
|
||||
logging.error(
|
||||
T("Connecting %s@%s failed, message=%s"),
|
||||
nw.thrdnum,
|
||||
nw.server.host,
|
||||
nw.nntp_msg,
|
||||
)
|
||||
# No reset-warning needed, above logging is sufficient
|
||||
self.__reset_nw(nw, retry_article=False)
|
||||
return True
|
||||
elif nw.status_code in (411, 423, 430):
|
||||
done = True
|
||||
logging.debug(
|
||||
"Thread %s@%s: Article %s missing (error=%s)",
|
||||
nw.thrdnum,
|
||||
nw.server.host,
|
||||
article.article,
|
||||
nw.status_code,
|
||||
)
|
||||
nw.clear_data()
|
||||
|
||||
elif nw.status_code == 500:
|
||||
if article.nzf.nzo.precheck:
|
||||
# Assume "STAT" command is not supported
|
||||
server.have_stat = False
|
||||
logging.debug("Server %s does not support STAT", server.host)
|
||||
else:
|
||||
# Assume "BODY" command is not supported
|
||||
server.have_body = False
|
||||
logging.debug("Server %s does not support BODY", server.host)
|
||||
nw.clear_data()
|
||||
self.__request_article(nw)
|
||||
|
||||
if done:
|
||||
# Successful data, clear "bad" counter
|
||||
server.bad_cons = 0
|
||||
server.errormsg = server.warning = ""
|
||||
|
||||
# Update statistics and decode
|
||||
article.nzf.nzo.update_download_stats(BPSMeter.bps, server.id, nw.data_size)
|
||||
self.decode(article, nw.data, nw.data_size)
|
||||
|
||||
if sabnzbd.LOG_ALL:
|
||||
logging.debug("Thread %s@%s: %s done", nw.thrdnum, server.host, article.article)
|
||||
|
||||
# Reset connection for new activity
|
||||
nw.soft_reset()
|
||||
server.busy_threads.remove(nw)
|
||||
server.idle_threads.append(nw)
|
||||
self.remove_socket(nw)
|
||||
|
||||
def __reset_nw(
|
||||
self,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 The SABnzbd-Team <team@sabnzbd.org>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/python3 -OO
|
||||
# Copyright 2007-2023 The SABnzbd-Team <team@sabnzbd.org>
|
||||
# Copyright 2007-2022 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
|
||||
@@ -36,7 +36,7 @@ def utob(str_in: AnyStr) -> bytes:
|
||||
|
||||
def ubtou(str_in: AnyStr) -> str:
|
||||
"""Shorthand for converting unicode bytes to UTF-8 string"""
|
||||
if isinstance(str_in, str):
|
||||
if not isinstance(str_in, bytes):
|
||||
return str_in
|
||||
return str_in.decode("utf-8")
|
||||
|
||||
|
||||
@@ -67,7 +67,8 @@ def is_listed_ext(ext: str, ext_list: list) -> bool:
|
||||
thus return false for extensions such as 'r007' despite the substring match on 'r00').
|
||||
"""
|
||||
for item in ext_list:
|
||||
if RE_EXT := sabnzbd.misc.convert_filter(item):
|
||||
RE_EXT = sabnzbd.misc.convert_filter(item)
|
||||
if RE_EXT:
|
||||
try:
|
||||
if len(RE_EXT.match(ext).group()) == len(ext):
|
||||
return True
|
||||
@@ -120,14 +121,6 @@ def is_writable(path: str) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
def is_size(filepath: str, size: int) -> bool:
|
||||
"""Return True if filepath exists and is specified size"""
|
||||
try:
|
||||
return os.path.getsize(filepath) == size
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
_DEVICES = (
|
||||
"con",
|
||||
"prn",
|
||||
@@ -184,13 +177,10 @@ def has_win_device(filename: str) -> bool:
|
||||
return False
|
||||
|
||||
|
||||
CH_ILLEGAL = "\0/"
|
||||
CH_LEGAL = "_+"
|
||||
CH_ILLEGAL_WIN = '\\/<>?*|":'
|
||||
CH_LEGAL_WIN = "++{}!@#'-"
|
||||
for i in range(1, 32):
|
||||
CH_ILLEGAL_WIN += chr(i)
|
||||
CH_LEGAL_WIN += "_"
|
||||
CH_ILLEGAL = "/"
|
||||
CH_LEGAL = "+"
|
||||
CH_ILLEGAL_WIN = '\\/<>?*|"\t:'
|
||||
CH_LEGAL_WIN = "++{}!@#'+-"
|
||||
|
||||
|
||||
def sanitize_filename(name: str) -> str:
|
||||
@@ -624,7 +614,8 @@ def set_chmod(path: str, permissions: int, allow_failures: bool = False):
|
||||
def set_permissions(path: str, recursive: bool = True):
|
||||
"""Give folder tree and its files their proper permissions"""
|
||||
if not sabnzbd.WIN32:
|
||||
if custom_permissions := sabnzbd.cfg.permissions():
|
||||
custom_permissions = sabnzbd.cfg.permissions()
|
||||
if custom_permissions:
|
||||
# If user set permissions, parse them
|
||||
custom_permissions = int(custom_permissions, 8)
|
||||
|
||||
@@ -1221,7 +1212,8 @@ def backup_exists(filename: str) -> bool:
|
||||
|
||||
def backup_nzb(nzb_path: str):
|
||||
"""Backup NZB file, return path to nzb if it was saved"""
|
||||
if nzb_backup_dir := sabnzbd.cfg.nzb_backup_dir.get_path():
|
||||
nzb_backup_dir = sabnzbd.cfg.nzb_backup_dir.get_path()
|
||||
if nzb_backup_dir:
|
||||
logging.debug("Saving copy of %s in %s", get_filename(nzb_path), nzb_backup_dir)
|
||||
shutil.copy(nzb_path, nzb_backup_dir)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user