Compare commits

...

59 Commits
4.0.1 ... 4.0.2

Author SHA1 Message Date
Safihre
3a6f04496d Set version to 4.0.2 2023-06-07 17:31:29 +02:00
Safihre
47f2df2112 Merge branch '4.0.x' 2023-06-07 17:25:45 +02:00
Safihre
363a26b8a1 Update text files for 4.0.2 2023-06-07 17:24:54 +02:00
Safihre
7e50a00f55 Correct parameter in release script to merge PR of update 2023-05-31 22:06:26 +02:00
Safihre
a7d6a80e82 Update text files for 4.0.2RC2 2023-05-31 21:49:02 +02:00
Safihre
e7da95b2ac Merge branch 'develop' into 4.0.x 2023-05-31 21:38:48 +02:00
Safihre
422b4fce7b Notification Script did not get environment variables 2023-05-31 21:16:15 +02:00
Safihre
e3a7226648 Move Notification Script Parameters to environment variable
Fixes #2549
2023-05-31 11:35:23 +02:00
Michael Nightingale
5b9fc86319 Fix uu decode workaround (#2573)
* Fix uu decode workaround

* Remove trailing junk test because workaround handles it
2023-05-29 14:20:01 +02:00
renovate[bot]
5afea2d3c7 Update dependency orjson to v3.8.14 2023-05-29 02:10:08 +00:00
SABnzbd Automation
5f942a6943 Update translatable texts
[skip ci]
2023-05-24 15:45:03 +00:00
Safihre
18075c5c51 Print last line in case of error
Closes #2566
2023-05-24 17:44:10 +02:00
Safihre
a728225782 Automatically merge website update during release 2023-05-24 09:38:15 +02:00
Safihre
74fca23d59 Update text files for 4.0.2RC1 2023-05-23 21:31:43 +02:00
Safihre
0a12fa1253 Merge branch 'develop' into 4.0.x 2023-05-23 21:31:11 +02:00
Safihre
3e6ae26710 Tray icon could not be disabled on macOS 2023-05-23 21:18:49 +02:00
Safihre
a8a4e442a8 Add PYTHONUNBUFFERED env variable for Python post-processing scripts 2023-05-23 20:34:38 +02:00
Safihre
c16e91734d Catch all errors during rarfile header parsing
Closes #2569
2023-05-22 10:23:28 +02:00
Safihre
bb9ad4b546 Disable buffering in POpen calls
Closes #2567
2023-05-22 10:10:46 +02:00
renovate[bot]
43045e5d4e Update all dependencies 2023-05-22 03:18:21 +00:00
Safihre
63c7dbdb4d Rely on POpen's text mode to handle encoding 2023-05-17 17:08:16 +02:00
Safihre
ef217bba90 Only open pipe for stdin when we actually need it 2023-05-17 16:52:59 +02:00
Safihre
ca9924c38f Only warn about sabctools linking if OpenSSL >= 1.1.1
Relates to #2421
2023-05-17 16:39:06 +02:00
SABnzbd Automation
c3c47507e7 Update translatable texts
[skip ci]
2023-05-16 11:18:41 +00:00
Safihre
dc237c752a Do not push local translations to allow modifications 2023-05-16 13:17:58 +02:00
SABnzbd Automation
08892c71b2 Update translatable texts
[skip ci]
2023-05-16 11:06:46 +00:00
Safihre
026717b7c2 Build binaries without dependencies 2023-05-16 13:05:23 +02:00
Michael Nightingale
be06290f6c Addnzbfile enums and keep empty (#2554)
* Add enum result to add_nzbfile

* Do not delete invalid single file NZBs if file could not be decoded

* Move enum to constants and make it a class
2023-05-15 14:28:49 +02:00
SABnzbd Automation
9ec55478c9 Update translatable texts
[skip ci]
2023-05-15 00:42:16 +00:00
renovate[bot]
4172b4a2a6 Update all dependencies 2023-05-15 00:41:05 +00:00
Safihre
59620c2217 Remove debugging code for Downloader sleep time
Seems your solution worked @puzzledsab!
2023-05-10 21:31:15 +02:00
SABnzbd Automation
c410c646b2 Update translatable texts
[skip ci]
2023-05-10 19:26:14 +00:00
Safihre
0b515996d7 Wrap Downloader in try/except
We need diagnostic info. No clue why we didn't do this before.
Relates to #2559
2023-05-10 21:24:28 +02:00
Safihre
8b9b8319a1 Warn users against using application directory as their Scripts Folder
Closes #2557
2023-05-10 21:16:49 +02:00
Safihre
161cf14519 Disabling a server during download doesn't stop it from downloading
Closes #2555
2023-05-10 10:28:18 +02:00
thezoggy
c6ac09e938 Disable sorting on pattern key so you can select text on it / prevent it from moving. (#2556) 2023-05-10 06:40:53 +02:00
Safihre
fde8f9d133 Allow longer binary startup during release quick-test 2023-05-08 17:04:45 +02:00
SABnzbd Automation
2bd222ca1c Update translatable texts
[skip ci]
2023-05-08 14:57:52 +00:00
Safihre
12228fe1fb Update Watched Folder text to include supported extensions
Relates to #2550
2023-05-08 16:56:32 +02:00
SABnzbd Automation
c63b2592f1 Update translatable texts
[skip ci]
2023-05-08 09:52:03 +00:00
Sander
e65980258c test writing long and unicode filenames (#2542)
* test writing long and unicode filenames

* Update sabnzbd/filesystem.py

Co-authored-by: Safihre <safihre@sabnzbd.org>

* Update sabnzbd/filesystem.py

Co-authored-by: Safihre <safihre@sabnzbd.org>

* Update sabnzbd/filesystem.py

Co-authored-by: Safihre <safihre@sabnzbd.org>

* Update sabnzbd/filesystem.py

Co-authored-by: Safihre <safihre@sabnzbd.org>

* test writing long and unicode filenames

* seperate function test_filesystem_capabilities

* rename test_filesystem_capabilities to filesystem_capabilities

* rename filesystem_capabilities to check_filesystem_capabilities

---------

Co-authored-by: sander <san.d.erjonkers+github@gmail.com>
Co-authored-by: Safihre <safihre@sabnzbd.org>
2023-05-08 11:50:49 +02:00
SABnzbd Automation
bd0a90d2dd Update translatable texts
[skip ci]
2023-05-08 06:15:40 +00:00
renovate[bot]
33a7e92f4c Update dependency orjson to v3.8.12 2023-05-08 08:14:31 +02:00
Safihre
51d1a1994d Allow for more time to start and shutdown during testing
macOS sometimes needs more time
2023-05-03 14:53:46 +02:00
Safihre
835745e485 Remove PKG-INFO
Closes #2548
2023-05-03 14:25:03 +02:00
Safihre
bcb553d9f9 Move release actions to separate build step 2023-05-03 14:22:50 +02:00
Safihre
b73b8aae6a Post release notes to Reddit after release
Add praw to builder requirements
2023-05-03 14:22:50 +02:00
Safihre
51792e31a8 Add release to PR of new release 2023-05-02 10:45:48 +02:00
Safihre
636a391db3 Update appdata for 4.0.1 release 2023-05-01 21:36:13 +02:00
Safihre
57d5ed2f21 Add Windows Python 3.8 32bit to CI test
Since we also use it for the release.
2023-05-01 21:33:49 +02:00
Safihre
bbb1d1d908 Update sabctools to 7.0.2 2023-05-01 21:29:19 +02:00
François M
c5d8f52f03 Add releases tag (#2539)
* Add 3.7.2 release tag

* Add 4.0.0 placeholder
2023-05-01 21:23:30 +02:00
renovate[bot]
1b49e4a355 Update all dependencies 2023-05-01 02:16:27 +00:00
Safihre
878cb589c3 Show a better crash on Python <3.8 2023-04-30 21:37:16 +02:00
Safihre
53ce88d3d2 Make Config link to wiki dynamic 2023-04-26 22:24:53 +02:00
Safihre
85e9bea9e7 Make sure all paths are unique in deobfuscate
Closes #2535
2023-04-26 17:22:56 +02:00
Safihre
7c7f88ebb5 Correctly set version to 4.1.0-develop 2023-04-26 17:20:11 +02:00
SABnzbd Automation
cbd007b81a Update translatable texts
[skip ci]
2023-04-26 13:28:51 +00:00
Safihre
ac0438de42 Set version to 4.1.0-develop 2023-04-26 15:27:31 +02:00
107 changed files with 1480 additions and 989 deletions

View File

@@ -15,6 +15,7 @@
"fileMatch": [
"requirements.txt",
"builder/requirements.txt",
"builder/release-requirements.txt",
"builder/osx/requirements.txt"
]
},

View File

@@ -4,7 +4,6 @@ on: [push, pull_request]
# Setting PYTHONNODEBUGRANGES reduces binary size
env:
AUTOMATION_GITHUB_TOKEN: ${{ secrets.AUTOMATION_GITHUB_TOKEN }}
PYTHONNODEBUGRANGES: 1
jobs:
@@ -25,16 +24,15 @@ jobs:
with:
custom_virtualenv_dir: "venv64"
custom_cache_key_element: "release"
requirement_files: |
**/requirements.txt
PKG-INFO
requirement_files: "**/requirements.txt"
- name: Install Python dependencies (64bit)
if: steps.cache-virtualenv-64bit.outputs.cache-hit != 'true'
# Without dependencies to make sure everything is covered in the requirements.txt
run: |
python --version
python -m pip install --upgrade pip wheel
pip install --upgrade -r requirements.txt
pip install --upgrade -r builder/requirements.txt
pip install --upgrade -r requirements.txt --no-dependencies
pip install --upgrade -r builder/requirements.txt --no-dependencies
- name: Build Windows standalone binary and installer (64bit)
run: python builder/package.py installer
- name: Upload Windows standalone binary (64bit)
@@ -58,14 +56,13 @@ jobs:
with:
custom_virtualenv_dir: "venv32"
custom_cache_key_element: "release"
requirement_files: |
**/requirements.txt
PKG-INFO
requirement_files: "**/requirements.txt"
- name: Install Python dependencies (32bit and legacy)
if: steps.cache-virtualenv-32bit.outputs.cache-hit != 'true'
# We do not care about the extra dependencies for the legacy build
run: |
python --version
pip install --upgrade pip wheel
python -m pip install --upgrade pip wheel
pip install --upgrade -r requirements.txt
pip install --upgrade -r builder/requirements.txt
- name: Build Windows standalone binary (32bit and legacy)
@@ -75,9 +72,6 @@ jobs:
with:
path: "*-win32-bin.zip"
name: Windows Windows standalone binary (32bit and legacy)
- name: Prepare official release
if: env.AUTOMATION_GITHUB_TOKEN && startsWith(github.ref, 'refs/tags/')
run: python builder/package.py release
build_macos:
name: Build macOS binary
@@ -113,15 +107,14 @@ jobs:
id: cache-virtualenv
with:
custom_cache_key_element: "release"
requirement_files: |
**/requirements.txt
PKG-INFO
requirement_files: "**/requirements.txt"
- name: Install Python dependencies
# We have to manually take a few steps:
# 1. Because building cryptography is hard, and we cannot force pip to fetch universal2 version we
# first install the x86 version (and it's dependencies) and then manually fetch the universal2 build
# https://github.com/pyca/cryptography/issues/5918
# 2. We need to build the PyInstaller bootloader:
# 2. Due to PyObjC we cannot run pip on the main requirements without installing dependencies
# 3. We need to build the PyInstaller bootloader:
# https://github.com/pyinstaller/pyinstaller/issues/6235
if: steps.cache-virtualenv.outputs.cache-hit != 'true'
run: |
@@ -134,7 +127,7 @@ jobs:
pip3 download -r builder/osx/requirements.txt --platform macosx_10_12_universal2 --only-binary :all: --no-deps --dest .
pip3 install -r builder/osx/requirements.txt --no-cache-dir --no-index --find-links .
PYINSTALLER_COMPILE_BOOTLOADER=1 pip3 install --upgrade -r builder/requirements.txt --no-binary pyinstaller
PYINSTALLER_COMPILE_BOOTLOADER=1 pip3 install --upgrade -r builder/requirements.txt --no-binary pyinstaller --no-dependencies
- name: Import macOS codesign certificates
# Taken from https://github.com/Apple-Actions/import-codesign-certs/pull/27 (comments)
env:
@@ -171,23 +164,34 @@ jobs:
with:
path: "*-osx.dmg"
name: macOS binary (not notarized)
- name: Prepare official release
if: env.AUTOMATION_GITHUB_TOKEN && startsWith(github.ref, 'refs/tags/')
run: python3 builder/package.py release
release_snap:
name: Release Snap
release:
name: Publish Release
runs-on: ubuntu-latest
needs: [build_windows, build_macos]
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_TOKEN }}
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: "3.x"
- name: Download all artifacts
uses: actions/download-artifact@v3
with:
path: dist
- name: Move all artifacts to main folder
run: find dist -type f -exec mv {} . \;
- name: Prepare official release
env:
AUTOMATION_GITHUB_TOKEN: ${{ secrets.AUTOMATION_GITHUB_TOKEN }}
REDDIT_TOKEN: ${{ secrets.REDDIT_TOKEN }}
run: |
pip3 install -r builder/release-requirements.txt
python3 builder/release.py
- name: Release latest available Snap
env:
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAP_TOKEN }}
run: |
sudo snap install snapcraft --classic
python3 snap/local/release_snap.py

View File

@@ -32,22 +32,30 @@ jobs:
fail-fast: false
matrix:
python-version: ["3.8", "3.9", "3.10", "3.11"]
python-architecture: ["x64"]
name: ["Linux"]
os: [ubuntu-20.04]
include:
- name: macOS
os: macos-latest
python-version: "3.11"
python-architecture: "x64"
- name: Windows
os: windows-latest
python-version: "3.11"
python-architecture: "x64"
- name: Windows (32bit)
os: windows-latest
python-version: "3.8"
python-architecture: "x86"
steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
- name: Set up Python ${{ matrix.python-version }} ${{ matrix.python-architecture }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: "x64"
architecture: ${{ matrix.python-architecture }}
- name: Install system dependencies
if: runner.os == 'Linux'
run: sudo apt-get install unrar p7zip-full par2
@@ -55,10 +63,8 @@ jobs:
uses: syphar/restore-virtualenv@v1.3
id: cache-virtualenv
with:
custom_cache_key_element: "ci"
requirement_files: |
**/requirements.txt
PKG-INFO
custom_cache_key_element: ci-${{ matrix.python-architecture }}
requirement_files: "**/requirements.txt"
- name: Install Python dependencies
if: steps.cache-virtualenv.outputs.cache-hit != 'true'
run: |

View File

@@ -20,11 +20,11 @@ jobs:
python3 tools/extract_pot.py
- name: Push/pull Transifex translations
if: env.TX_TOKEN
# We sleep so all files are updated when we pull them back in
# Add --translation to the push command in order to update Transifex using local translation edits
# However, this prevents modifying existing translations in Transifex as they will be overwritten by the push!
run: |
curl -o- https://raw.githubusercontent.com/transifex/cli/master/install.sh | bash
./tx push --translation --source
sleep 10s
./tx push --source
./tx pull --all --force
- name: Compile translations to validate them
run: |
@@ -33,7 +33,7 @@ jobs:
uses: stefanzweifel/git-auto-commit-action@v4.16.0
if: env.TX_TOKEN
with:
commit_message: |
commit_message: |
Update translatable texts
[skip ci]
commit_user_name: SABnzbd Automation

View File

@@ -1,10 +0,0 @@
Metadata-Version: 1.0
Name: SABnzbd
Version: 4.0.1
Summary: SABnzbd-4.0.1
Home-page: https://sabnzbd.org
Author: The SABnzbd Team
Author-email: team@sabnzbd.org
License: GNU General Public License 2 (GPL2 or later)
Description: Fully automated Usenet Binary Downloader
Platform: posix

View File

@@ -1,12 +1,28 @@
Release Notes - SABnzbd 4.0.1
Release Notes - SABnzbd 4.0.2
=========================================================
## Bugfixes since 4.0.0
- Windows: Prevent fatal crash on 32bit Windows.
## Breaking change
- The `Parameters` setting of a `Notification Script` is now passed as
environment variable `SAB_NOTIFICATION_PARAMETERS` instead of as a
command-line parameter. This prevents the possibility of remote code
execution on systems exposed to the internet without a username/password.
If you use `nzb-notify` you need to update it to the latest version.
## Bugfixes and changes since 4.0.1
- Disabling a server during download did not stop it from downloading.
- Show last line of post-processing script output even if it failed.
- Prevent crash during Deobfuscate on non-unique paths.
- Files that could not be parsed were removed from the `Watched Folder`.
- Warn if the file system does not support unicode or long filenames.
- Warn if `Scripts Folder` is inside the application directory.
- Prevent output buffering of Python post-processing scripts.
- The `PKG-INFO` file was removed from the `src` release.
- Correctly decode partially malformed UUencoded posts.
- macOS: Tray icon could not be disabled.
## Changes since 3.7.2
- In this major update we optimized a core part of the SSL handling.
This results in large performance increases when downloading from news
This results in large performance increase when downloading from news
servers with SSL enabled. In addition, the general connection handling
was improved, resulting in performance improvements for all news servers.
Special thanks to: mnightingale, puzzledsab and animetosho!
@@ -15,7 +31,7 @@ Release Notes - SABnzbd 4.0.1
- 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.
- Slow down more gracefully when the cache fills up.
- Replaced separate Series/Movie/Date Sorting with general Sorter.
- HTTPS files are included in the `Backup`.
- Improved `Watched Folder` scanning and processing.

46
README.txt Normal file
View File

@@ -0,0 +1,46 @@
Release Notes - SABnzbd 4.0.0 Release Candidate 2
=========================================================
## 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!
- There are 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!
- 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.
- Replaced separate Series/Movie/Date Sorting with general Sorter.
- HTTPS files are included in the `Backup`.
- Improved `Watched Folder` scanning and processing.
- Ignore resource fork files created by macOS.
- `Deobfuscate final filenames` is enabled for new installations.
- Dropped support for Python 3.7.
## Bugfixes since 3.7.2
- Restore applying `History Retention` setting at startup.
- Windows: Not all invalid characters were removed from filenames.
- Windows: Firewall rules were not removed by uninstaller.
## Upgrade notices
- The download statistics file `totals10.sab` is updated in 3.2.x
version. If you downgrade to 3.1.x or lower, detailed download
statistics will be lost.
## Known problems and solutions
- Read the file "ISSUES.txt"
## About
SABnzbd is an open-source cross-platform binary newsreader.
It simplifies the process of downloading from Usenet dramatically, thanks
to its web-based user interface and advanced built-in post-processing options
that automatically verify, repair, extract and clean up posts downloaded
from Usenet.
(c) Copyright 2007-2023 by "The SABnzbd-team" \<team@sabnzbd.org\>

View File

@@ -427,7 +427,8 @@ def print_modules():
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:
# It won't work on OpenSSL < 1.1.1 anyway, so we skip the check there
if not sabnzbd.decoder.SABCTOOLS_OPENSSL_LINKED and ssl.OPENSSL_VERSION_INFO >= (1, 1, 1):
logging.warning(
"Could not link to OpenSSL library, please report here: "
"https://github.com/sabnzbd/sabnzbd/issues/2421"

View File

@@ -2,43 +2,17 @@
import os
import re
import sys
import pkginfo
from PyInstaller.building.api import EXE, COLLECT, PYZ
from PyInstaller.building.build_main import Analysis
from PyInstaller.building.osx import BUNDLE
from PyInstaller.utils.hooks import collect_data_files, collect_submodules
from builder.constants import EXTRA_FILES, EXTRA_FOLDERS, RELEASE_VERSION
# Add extra files in the PyInstaller-spec
extra_pyinstaller_files = []
# Also modify these in "package.py"!
extra_files = [
"README.txt",
"INSTALL.txt",
"LICENSE.txt",
"GPL2.txt",
"GPL3.txt",
"COPYRIGHT.txt",
"ISSUES.txt",
"PKG-INFO",
]
extra_folders = [
"scripts/",
"licenses/",
"locale/",
"email/",
"interfaces/Glitter/",
"interfaces/wizard/",
"interfaces/Config/",
"scripts/",
"icons/",
]
# Get the version
RELEASE_VERSION = pkginfo.Develop(".").version
# Add hidden imports
extra_hiddenimports = ["Cheetah.DummyTransaction", "cheroot.ssl.builtin", "certifi"]
extra_hiddenimports.extend(collect_submodules("babelfish.converters"))
@@ -48,7 +22,7 @@ extra_hiddenimports.extend(collect_submodules("guessit.data"))
if sys.platform == "darwin":
extra_hiddenimports.extend(["objc", "PyObjCTools"])
# macOS folders
extra_folders += ["osx/par2/", "osx/unrar/", "osx/7zip/"]
EXTRA_FOLDERS += ["osx/par2/", "osx/unrar/", "osx/7zip/"]
# Add NZB-icon file
extra_pyinstaller_files.append(("builder/osx/image/nzbfile.icns", "."))
# Version information is set differently on macOS
@@ -67,8 +41,8 @@ else:
# Windows
extra_hiddenimports.append("win32timezone")
extra_folders += ["win/multipar/", "win/unrar/", "win/7zip/"]
extra_files += ["portable.cmd"]
EXTRA_FOLDERS += ["win/multipar/", "win/unrar/", "win/7zip/"]
EXTRA_FILES += ["portable.cmd"]
# Parse the version info
version_regexed = re.search(r"(\d+)\.(\d+)\.(\d+)([a-zA-Z]*)(\d*)", RELEASE_VERSION)
@@ -109,9 +83,9 @@ else:
)
# Process the extra-files and folders
for file_item in extra_files:
for file_item in EXTRA_FILES:
extra_pyinstaller_files.append((file_item, "."))
for folder_item in extra_folders:
for folder_item in EXTRA_FOLDERS:
extra_pyinstaller_files.append((folder_item, folder_item))
# Add babelfish data files

62
builder/constants.py Normal file
View File

@@ -0,0 +1,62 @@
#!/usr/bin/python3 -OO
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import os
# Constants
VERSION_FILE = "sabnzbd/version.py"
# To draft a release or not to draft a release?
ON_GITHUB_ACTIONS = os.environ.get("CI", False)
RELEASE_THIS = "refs/tags/" in os.environ.get("GITHUB_REF", "")
# Import version.py without the sabnzbd overhead
with open(VERSION_FILE) as version_file:
exec(version_file.read())
RELEASE_VERSION = __version__
# Define release name
RELEASE_NAME = "SABnzbd-%s" % RELEASE_VERSION
RELEASE_TITLE = "SABnzbd %s" % RELEASE_VERSION
RELEASE_SRC = RELEASE_NAME + "-src.tar.gz"
RELEASE_BINARY_32 = RELEASE_NAME + "-win32-bin.zip"
RELEASE_BINARY_64 = RELEASE_NAME + "-win64-bin.zip"
RELEASE_INSTALLER = RELEASE_NAME + "-win-setup.exe"
RELEASE_MACOS = RELEASE_NAME + "-osx.dmg"
RELEASE_README = "README.mkd"
# Used in package.py and SABnzbd.spec
EXTRA_FILES = [
"README.mkd",
"INSTALL.txt",
"LICENSE.txt",
"GPL2.txt",
"GPL3.txt",
"COPYRIGHT.txt",
"ISSUES.txt",
]
EXTRA_FOLDERS = [
"scripts/",
"licenses/",
"locale/",
"email/",
"interfaces/Glitter/",
"interfaces/wizard/",
"interfaces/Config/",
"scripts/",
"icons/",
]

View File

@@ -16,7 +16,7 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import os
import pkginfo
from constants import RELEASE_VERSION
# We need to call dmgbuild from command-line, so here we can setup how
@@ -37,7 +37,7 @@ if __name__ == "__main__":
# Extract version info and set DMG path
# Create sub-folder to upload later
release = pkginfo.Develop(".").version
release = RELEASE_VERSION
prod = "SABnzbd-" + release
fileDmg = prod + "-osx.dmg"

View File

@@ -16,7 +16,6 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import glob
import hashlib
import platform
import re
import sys
@@ -29,37 +28,22 @@ import tarfile
import urllib.request
import urllib.error
import configobj
import pkginfo
import github
from typing import List
VERSION_FILE = "sabnzbd/version.py"
SPEC_FILE = "SABnzbd.spec"
# Also modify these in "SABnzbd.spec"!
extra_files = [
"README.mkd",
"INSTALL.txt",
"LICENSE.txt",
"GPL2.txt",
"GPL3.txt",
"COPYRIGHT.txt",
"ISSUES.txt",
"PKG-INFO",
]
extra_folders = [
"scripts/",
"licenses/",
"locale/",
"email/",
"interfaces/Glitter/",
"interfaces/wizard/",
"interfaces/Config/",
"scripts/",
"icons/",
]
from constants import (
RELEASE_VERSION,
VERSION_FILE,
RELEASE_README,
RELEASE_NAME,
RELEASE_BINARY_32,
RELEASE_BINARY_64,
RELEASE_INSTALLER,
ON_GITHUB_ACTIONS,
RELEASE_THIS,
RELEASE_SRC,
EXTRA_FILES,
EXTRA_FOLDERS,
)
# Support functions
@@ -132,13 +116,16 @@ def test_sab_binary(binary_path: str):
# Wait for SAB to respond
base_url = "http://127.0.0.1:8080/"
for _ in range(10):
for _ in range(30):
try:
urllib.request.urlopen(base_url, timeout=1).read()
break
except:
time.sleep(1)
else:
# Print console output and give some time to print
print(sabnzbd_process.stdout.read())
time.sleep(1)
raise urllib.error.URLError("Could not connect to SABnzbd")
# Open a number of API calls and pages, to see if we are really up
@@ -173,7 +160,7 @@ def test_sab_binary(binary_path: str):
print(log_file.read())
# So we have time to print the file before the directory is removed
time.sleep(1)
time.sleep(5)
if __name__ == "__main__":
@@ -185,32 +172,15 @@ if __name__ == "__main__":
if not os.path.exists("builder"):
raise FileNotFoundError("Run from the main SABnzbd source folder: python builder/package.py")
# Extract version info
RELEASE_VERSION = pkginfo.Develop(".").version
# Check if we have the needed certificates
try:
import certifi
except ImportError:
raise FileNotFoundError("Need certifi module")
# Define release name
RELEASE_NAME = "SABnzbd-%s" % RELEASE_VERSION
RELEASE_TITLE = "SABnzbd %s" % RELEASE_VERSION
RELEASE_SRC = RELEASE_NAME + "-src.tar.gz"
RELEASE_BINARY_32 = RELEASE_NAME + "-win32-bin.zip"
RELEASE_BINARY_64 = RELEASE_NAME + "-win64-bin.zip"
RELEASE_INSTALLER = RELEASE_NAME + "-win-setup.exe"
RELEASE_MACOS = RELEASE_NAME + "-osx.dmg"
RELEASE_README = "README.mkd"
# Patch release file
patch_version_file(RELEASE_VERSION)
# To draft a release or not to draft a release?
ON_GITHUB_ACTIONS = os.environ.get("CI", False)
RELEASE_THIS = "refs/tags/" in os.environ.get("GITHUB_REF", "")
# Rename release notes file
safe_remove("README.txt")
shutil.copyfile(RELEASE_README, "README.txt")
@@ -229,7 +199,7 @@ if __name__ == "__main__":
safe_remove(RELEASE_NAME)
# Copy the specification
shutil.copyfile("builder/%s" % SPEC_FILE, SPEC_FILE)
shutil.copyfile("builder/SABnzbd.spec", "SABnzbd.spec")
if "binary" in sys.argv or "installer" in sys.argv:
# Must be run on Windows
@@ -256,7 +226,6 @@ if __name__ == "__main__":
delete_files_glob("dist/SABnzbd/ucrtbase.dll")
# Remove other files we don't need
delete_files_glob("dist/SABnzbd/PKG-INFO")
delete_files_glob("dist/SABnzbd/win32ui.pyd")
delete_files_glob("dist/SABnzbd/winxpgui.pyd")
@@ -435,15 +404,15 @@ if __name__ == "__main__":
safe_remove(RELEASE_SRC)
# Add extra files and folders need for source dist
extra_folders.extend(["sabnzbd/", "po/", "linux/", "tools/", "tests/"])
extra_files.extend(["SABnzbd.py", "requirements.txt"])
EXTRA_FOLDERS.extend(["sabnzbd/", "po/", "linux/", "tools/", "tests/"])
EXTRA_FILES.extend(["SABnzbd.py", "requirements.txt"])
# Copy all folders and files to the new folder
for source_folder in extra_folders:
for source_folder in EXTRA_FOLDERS:
shutil.copytree(source_folder, os.path.join(src_folder, source_folder), dirs_exist_ok=True)
# Copy all files
for source_file in extra_files:
for source_file in EXTRA_FILES:
shutil.copyfile(source_file, os.path.join(src_folder, source_file))
# Make sure all line-endings are correct
@@ -483,173 +452,6 @@ if __name__ == "__main__":
# Remove source folder
safe_remove(src_folder)
# Calculate hashes for Synology release
with open(RELEASE_SRC, "rb") as inp_file:
source_data = inp_file.read()
print("----")
print(RELEASE_SRC, "SHA1", hashlib.sha1(source_data).hexdigest())
print(RELEASE_SRC, "SHA256", hashlib.sha256(source_data).hexdigest())
print(RELEASE_SRC, "MD5", hashlib.md5(source_data).hexdigest())
print("----")
# Release to github
if "release" in sys.argv:
# Check if tagged as release and check for token
gh_token = os.environ.get("AUTOMATION_GITHUB_TOKEN", "")
if RELEASE_THIS and gh_token:
gh_obj = github.Github(gh_token)
gh_repo = gh_obj.get_repo("sabnzbd/sabnzbd")
# Read the release notes
with open(RELEASE_README, "r") as readme_file:
readme_data = readme_file.read()
# Pre-releases are longer than 6 characters (e.g. 3.1.0Beta1 vs 3.1.0, but also 3.0.11)
prerelease = len(RELEASE_VERSION) > 5
# We have to manually check if we already created this release
for release in gh_repo.get_releases():
if release.tag_name == RELEASE_VERSION:
gh_release = release
print("Found existing release %s" % gh_release.title)
break
else:
# Did not find it, so create the release, use the GitHub tag we got as input
print("Creating GitHub release SABnzbd %s" % RELEASE_VERSION)
gh_release = gh_repo.create_git_release(
tag=RELEASE_VERSION,
name=RELEASE_TITLE,
message=readme_data,
draft=True,
prerelease=prerelease,
)
# Fetch existing assets, as overwriting is not allowed by GitHub
gh_assets = gh_release.get_assets()
# Upload the assets
files_to_check = (
RELEASE_SRC,
RELEASE_BINARY_32,
RELEASE_BINARY_64,
RELEASE_INSTALLER,
RELEASE_MACOS,
RELEASE_README,
)
for file_to_check in files_to_check:
if os.path.exists(file_to_check):
# Check if this file was previously uploaded
if gh_assets.totalCount:
for gh_asset in gh_assets:
if gh_asset.name == file_to_check:
print("Removing existing asset %s " % gh_asset.name)
gh_asset.delete_asset()
# Upload the new one
print("Uploading %s to release %s" % (file_to_check, gh_release.title))
gh_release.upload_asset(file_to_check)
# Check if we now have all files
gh_new_assets = gh_release.get_assets()
if gh_new_assets.totalCount:
all_assets = [gh_asset.name for gh_asset in gh_new_assets]
# Check if we have all files, using set-comparison
if set(files_to_check) == set(all_assets):
print("All assets present, releasing %s" % RELEASE_VERSION)
# Publish release
gh_release.update_release(
tag_name=RELEASE_VERSION,
name=RELEASE_TITLE,
message=readme_data,
draft=False,
prerelease=prerelease,
)
# Update the website
gh_repo_web = gh_obj.get_repo("sabnzbd/sabnzbd.github.io")
# Check if the branch already exists, only create one if it doesn't
skip_website_update = False
try:
gh_repo_web.get_branch(RELEASE_VERSION)
print("Branch %s on sabnzbd/sabnzbd.github.io already exists, skipping update" % RELEASE_VERSION)
skip_website_update = True
except github.GithubException:
# Create a new branch to have the changes
sb = gh_repo_web.get_branch("master")
print("Creating branch %s on sabnzbd/sabnzbd.github.io" % RELEASE_VERSION)
new_branch = gh_repo_web.create_git_ref(ref="refs/heads/" + RELEASE_VERSION, sha=sb.commit.sha)
# Update the files
if not skip_website_update:
# We need bytes version to interact with GitHub
RELEASE_VERSION_BYTES = RELEASE_VERSION.encode()
# Get all the version files
latest_txt = gh_repo_web.get_contents("latest.txt")
latest_txt_items = latest_txt.decoded_content.split()
new_latest_txt_items = latest_txt_items[:2]
config_yml = gh_repo_web.get_contents("_config.yml")
if prerelease:
# If it's a pre-release, we append to current version in latest.txt
new_latest_txt_items.extend([RELEASE_VERSION_BYTES, latest_txt_items[1]])
# And replace in _config.yml
new_config_yml = re.sub(
b"latest_testing: '[^']*'",
b"latest_testing: '%s'" % RELEASE_VERSION_BYTES,
config_yml.decoded_content,
)
else:
# New stable release, replace the version
new_latest_txt_items[0] = RELEASE_VERSION_BYTES
# And replace in _config.yml
new_config_yml = re.sub(
b"latest_testing: '[^']*'",
b"latest_testing: ''",
config_yml.decoded_content,
)
new_config_yml = re.sub(
b"latest_stable: '[^']*'",
b"latest_stable: '%s'" % RELEASE_VERSION_BYTES,
new_config_yml,
)
# Also update the wiki-settings, these only use x.x notation
new_config_yml = re.sub(
b"wiki_version: '[^']*'",
b"wiki_version: '%s'" % RELEASE_VERSION_BYTES[:3],
new_config_yml,
)
# Update the files
print("Updating latest.txt")
gh_repo_web.update_file(
"latest.txt",
"Release %s: latest.txt" % RELEASE_VERSION,
b"\n".join(new_latest_txt_items),
latest_txt.sha,
RELEASE_VERSION,
)
print("Updating _config.yml")
gh_repo_web.update_file(
"_config.yml",
"Release %s: _config.yml" % RELEASE_VERSION,
new_config_yml,
config_yml.sha,
RELEASE_VERSION,
)
# Create pull-request
print("Creating pull request in sabnzbd/sabnzbd.github.io for the update")
gh_repo_web.create_pull(
title=RELEASE_VERSION,
base="master",
body="Automated update of release files",
head=RELEASE_VERSION,
)
else:
print("To push release to GitHub, first tag the commit.")
print("Or missing the AUTOMATION_GITHUB_TOKEN, cannot push to GitHub without it.")
# Reset!
run_git_command(["reset", "--hard"])
run_git_command(["clean", "-f"])

View File

@@ -0,0 +1,2 @@
PyGithub==1.58.2
praw==7.7.0

247
builder/release.py Normal file
View File

@@ -0,0 +1,247 @@
#!/usr/bin/python3 -OO
# Copyright 2008-2017 The SABnzbd-Team <team@sabnzbd.org>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
import hashlib
import json
import os
import re
import github
import praw
from constants import (
RELEASE_VERSION,
RELEASE_SRC,
RELEASE_BINARY_32,
RELEASE_BINARY_64,
RELEASE_INSTALLER,
RELEASE_MACOS,
RELEASE_README,
RELEASE_THIS,
RELEASE_TITLE,
)
# Verify we have all assets
files_to_check = (
RELEASE_SRC,
RELEASE_BINARY_32,
RELEASE_BINARY_64,
RELEASE_INSTALLER,
RELEASE_MACOS,
RELEASE_README,
)
for file_to_check in files_to_check:
if not os.path.exists(file_to_check):
raise RuntimeError("Not all release files are present!")
print("All release files are present")
# Calculate hashes for Synology release
with open(RELEASE_SRC, "rb") as inp_file:
source_data = inp_file.read()
print("---- Synology spksrc digest hashes ---- ")
print(RELEASE_SRC, "SHA1", hashlib.sha1(source_data).hexdigest())
print(RELEASE_SRC, "SHA256", hashlib.sha256(source_data).hexdigest())
print(RELEASE_SRC, "MD5", hashlib.md5(source_data).hexdigest())
print("----")
# Check if tagged as release and check for token
gh_token = os.environ.get("AUTOMATION_GITHUB_TOKEN", "")
if RELEASE_THIS and gh_token:
gh_obj = github.Github(gh_token)
gh_repo = gh_obj.get_repo("sabnzbd/sabnzbd")
# Read the release notes
with open(RELEASE_README, "r") as readme_file:
readme_data = readme_file.read()
# Pre-releases are longer than 6 characters (e.g. 3.1.0Beta1 vs 3.1.0, but also 3.0.11)
prerelease = len(RELEASE_VERSION) > 5
# We have to manually check if we already created this release
for release in gh_repo.get_releases():
if release.tag_name == RELEASE_VERSION:
gh_release = release
print("Found existing release %s" % gh_release.title)
break
else:
# Did not find it, so create the release, use the GitHub tag we got as input
print("Creating GitHub release SABnzbd %s" % RELEASE_VERSION)
gh_release = gh_repo.create_git_release(
tag=RELEASE_VERSION,
name=RELEASE_TITLE,
message=readme_data,
draft=True,
prerelease=prerelease,
)
# Fetch existing assets, as overwriting is not allowed by GitHub
gh_assets = gh_release.get_assets()
# Upload the assets
for file_to_check in files_to_check:
if os.path.exists(file_to_check):
# Check if this file was previously uploaded
if gh_assets.totalCount:
for gh_asset in gh_assets:
if gh_asset.name == file_to_check:
print("Removing existing asset %s " % gh_asset.name)
gh_asset.delete_asset()
# Upload the new one
print("Uploading %s to release %s" % (file_to_check, gh_release.title))
gh_release.upload_asset(file_to_check)
# Check if we now have all files
gh_new_assets = gh_release.get_assets()
if gh_new_assets.totalCount:
all_assets = [gh_asset.name for gh_asset in gh_new_assets]
# Check if we have all files, using set-comparison
if set(files_to_check) == set(all_assets):
print("All assets present, releasing %s" % RELEASE_VERSION)
# Publish release
gh_release.update_release(
tag_name=RELEASE_VERSION,
name=RELEASE_TITLE,
message=readme_data,
draft=False,
prerelease=prerelease,
)
# Update the website
gh_repo_web = gh_obj.get_repo("sabnzbd/sabnzbd.github.io")
# Check if the branch already exists, only create one if it doesn't
skip_website_update = False
try:
gh_repo_web.get_branch(RELEASE_VERSION)
print("Branch %s on sabnzbd/sabnzbd.github.io already exists, skipping update" % RELEASE_VERSION)
skip_website_update = True
except github.GithubException:
# Create a new branch to have the changes
sb = gh_repo_web.get_branch("master")
print("Creating branch %s on sabnzbd/sabnzbd.github.io" % RELEASE_VERSION)
new_branch = gh_repo_web.create_git_ref(ref="refs/heads/" + RELEASE_VERSION, sha=sb.commit.sha)
# Update the files
if not skip_website_update:
# We need bytes version to interact with GitHub
RELEASE_VERSION_BYTES = RELEASE_VERSION.encode()
# Get all the version files
latest_txt = gh_repo_web.get_contents("latest.txt")
latest_txt_items = latest_txt.decoded_content.split()
new_latest_txt_items = latest_txt_items[:2]
config_yml = gh_repo_web.get_contents("_config.yml")
if prerelease:
# If it's a pre-release, we append to current version in latest.txt
new_latest_txt_items.extend([RELEASE_VERSION_BYTES, latest_txt_items[1]])
# And replace in _config.yml
new_config_yml = re.sub(
b"latest_testing: '[^']*'",
b"latest_testing: '%s'" % RELEASE_VERSION_BYTES,
config_yml.decoded_content,
)
else:
# New stable release, replace the version
new_latest_txt_items[0] = RELEASE_VERSION_BYTES
# And replace in _config.yml
new_config_yml = re.sub(
b"latest_testing: '[^']*'",
b"latest_testing: ''",
config_yml.decoded_content,
)
new_config_yml = re.sub(
b"latest_stable: '[^']*'",
b"latest_stable: '%s'" % RELEASE_VERSION_BYTES,
new_config_yml,
)
# Also update the wiki-settings, these only use x.x notation
new_config_yml = re.sub(
b"wiki_version: '[^']*'",
b"wiki_version: '%s'" % RELEASE_VERSION_BYTES[:3],
new_config_yml,
)
# Update the files
print("Updating latest.txt")
gh_repo_web.update_file(
"latest.txt",
"Release %s: latest.txt" % RELEASE_VERSION,
b"\n".join(new_latest_txt_items),
latest_txt.sha,
RELEASE_VERSION,
)
print("Updating _config.yml")
gh_repo_web.update_file(
"_config.yml",
"Release %s: _config.yml" % RELEASE_VERSION,
new_config_yml,
config_yml.sha,
RELEASE_VERSION,
)
# Create pull-request
print("Creating pull request in sabnzbd/sabnzbd.github.io for the update")
update_pr = gh_repo_web.create_pull(
title="Release %s" % RELEASE_VERSION,
base="master",
body="Automated update of release files",
head=RELEASE_VERSION,
)
# Merge pull-request
print("Merging pull request in sabnzbd/sabnzbd.github.io for the update")
update_pr.merge(merge_method="squash")
# Only with GitHub success we proceed to Reddit
if reddit_token := os.environ.get("REDDIT_TOKEN", ""):
# Token format (without whitespace):
# {
# "client_id":"XXX",
# "client_secret":"XXX",
# "user_agent":"SABnzbd release script",
# "username":"Safihre",
# "password":"XXX"
# }
credentials = json.loads(reddit_token)
reddit = praw.Reddit(**credentials)
subreddit_sabnzbd = reddit.subreddit("sabnzbd")
subreddit_usenet = reddit.subreddit("usenet")
# Read the release notes
with open(RELEASE_README, "r") as readme_file:
readme_lines = readme_file.readlines()
# Use the header in the readme as title
title = readme_lines[0]
release_notes_text = "".join(readme_lines[3:])
# Post always to r/SABnzbd
print("Posting release notes to Reddit: r/sabnzbd")
submission = subreddit_sabnzbd.submit(title, selftext=release_notes_text)
# Only stable releases to r/usenet
if not prerelease:
print("Cross-posting release notes to Reddit: r/usenet")
submission.crosspost(subreddit_usenet)
else:
print("Missing REDDIT_TOKEN")
else:
print("To push release to GitHub, first tag the commit.")
print("Or missing the AUTOMATION_GITHUB_TOKEN, cannot push to GitHub without it.")

View File

@@ -1,18 +1,19 @@
# Basic build requirements
# Note that not all sub-dependencies are listed, but only ones we know could cause trouble
pyinstaller==5.10.1
pyinstaller-hooks-contrib==2023.2
pyinstaller==5.11.0
pyinstaller-hooks-contrib==2023.3
altgraph==0.17.3
wrapt==1.15.0
setuptools==67.7.1
pkginfo==1.9.6
PyGithub==1.58.1
charset-normalizer==3.1.0
setuptools==67.8.0
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.10; python_version > '3.8'
orjson==3.8.14; python_version > '3.8'
# For the Windows build
pefile==2023.2.7; sys_platform == 'win32'
pywin32-ctypes==0.2.0; sys_platform == 'win32'
# For the macOS build
dmgbuild==1.6.1; sys_platform == 'darwin'

View File

@@ -181,7 +181,7 @@
</a>
</li>
<li>
<a href="$helpuri$help_uri" target="_blank">
<a href="$help_uri" target="_blank">
<span class="glyphicon glyphicon-question-sign"></span>
<strong>$T('menu-help')</strong>
</a>

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Config"#-->
<!--#set global $help_uri="configuration/4.0/configure"#-->
<!--#set global $help_uri = $confighelpuri + "configure"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#from sabnzbd.encoding import CODEPAGE#-->
@@ -25,7 +25,7 @@
</tr>
<tr>
<th scope="row">$T('pythonVersion'): </th>
<td>$sys.version[:120] [$CODEPAGE]</td>
<td>$sys.version [$CODEPAGE]</td>
</tr>
<tr>
<th scope="row">OpenSSL:</th>
@@ -49,7 +49,7 @@
<span class="glyphicon glyphicon-ok"></span>
<!--#else#-->
<span class="label label-warning">$T('notAvailable')</span> $T('explain-getpar2mt')
<a href="${helpuri}installation/multicore-par2" target="_blank">${helpuri}installation/multicore-par2</a>
<a href="https://sabnzbd.org/wiki/installation/multicore-par2" target="_blank">https://sabnzbd.org/wiki/installation/multicore-par2</a>
<!--#end if#-->
</td>
</tr>
@@ -59,7 +59,7 @@
<th scope="row">SABCTools:</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="$help_uri#no_sabctools" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
</td>
</tr>
<!--#end if#-->
@@ -68,7 +68,7 @@
<th scope="row">$T('opt-enable_unzip'):</th>
<td>
<span class="label label-warning">$T('notAvailable')</span>
<a href="${helpuri}installation/install-off-modules#toc8" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<a href="https://sabnzbd.org/wiki/installation/install-off-modules#toc8" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
</td>
</tr>
<!--#end if#-->
@@ -77,7 +77,7 @@
<th scope="row">$T('opt-enable_7zip'):</th>
<td>
<span class="label label-warning">$T('notAvailable')</span>
<a href="${helpuri}installation/install-off-modules#toc8" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<a href="https://sabnzbd.org/wiki/installation/install-off-modules#toc8" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
</td>
</tr>
<!--#end if#-->

View File

@@ -1,10 +1,10 @@
<!--#set global $pane="Categories"#-->
<!--#set global $help_uri="configuration/4.0/categories"#-->
<!--#set global $help_uri = $confighelpuri + "categories"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
<div class="section">
<div class="padTable">
<a class="main-helplink" href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<a class="main-helplink" href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<p>$T('explain-catTags2')<br/>$T('explain-catTags')</p>
<hr>
<h5 class="darkred"><strong>$T('explain-relFolder'):</strong> <span class="path">$defdir</span></h5>

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Folders"#-->
<!--#set global $help_uri="configuration/4.0/folders"#-->
<!--#set global $help_uri = $confighelpuri + "folders"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
@@ -14,7 +14,7 @@
<input type="hidden" id="ajax" name="ajax" value="1" />
<div class="section">
<div class="col2">
<h3>$T('userFolders') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('userFolders') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<p>$T('explain-folderConfig')</p>
</div><!-- /col2 -->
<div class="col1">
@@ -58,7 +58,7 @@
<div class="field-pair">
<label class="config" for="dirscan_dir">$T('opt-dirscan_dir')</label>
<input type="text" name="dirscan_dir" id="dirscan_dir" value="$dirscan_dir" data-initialdir="$my_home" />
<span class="desc">$T('explain-dirscan_dir')</span>
<span class="desc">$T('explain-dirscan_dir').replace(".nzb", $file_exts)</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="dirscan_speed">$T('opt-dirscan_speed')</label>
@@ -91,7 +91,7 @@
</div><!-- /section -->
<div class="section advanced-settings">
<div class="col2">
<h3>$T('systemFolders') <a href="$helpuri$help_uri#toc1" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('systemFolders') <a href="$help_uri#toc1" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<p>$T('explain-folderConfig')</p>
</div><!-- /col2 -->
<div class="col1">

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="General"#-->
<!--#set global $help_uri="configuration/4.0/general"#-->
<!--#set global $help_uri = $confighelpuri + "general"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
@@ -14,7 +14,7 @@
<input type="hidden" name="output" value="json" />
<div class="section">
<div class="col2">
<h3>$T('webServer') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('webServer') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<p><b>$T('restartRequired')</b></p>
</div><!-- /col2 -->
<div class="col1">
@@ -102,7 +102,7 @@
</div>
<div class="section">
<div class="col2">
<h3>$T('security') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('security') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<p><b>$T('restartRequired')</b></p>
</div><!-- /col2 -->
<div class="col1">
@@ -156,7 +156,7 @@
</div><!-- /section -->
<div class="section">
<div class="col2">
<h3>$T('cmenu-switches') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('cmenu-switches') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -192,7 +192,7 @@
</div><!-- /section -->
<div class="section">
<div class="col2">
<h3>$T('tuning') <a href="$helpuri$help_uri#toc2" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('tuning') <a href="$help_uri#toc2" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -230,7 +230,7 @@
<input type="hidden" name="output" value="json" />
<div class="section">
<div class="col2">
<h3>$T('backup') <a href="$helpuri$help_uri#toc3" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('backup') <a href="$help_uri#toc3" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Email"#-->
<!--#set global $help_uri="configuration/4.0/notifications"#-->
<!--#set global $help_uri = $confighelpuri + "notifications"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#def show_notify_checkboxes($section_label)#-->
@@ -33,7 +33,7 @@
<input type="hidden" id="ajax" name="ajax" value="1" />
<div class="section" id="email">
<div class="col2">
<h3>$T('cmenu-email') <a href="$helpuri$help_uri#toc0" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('cmenu-email') <a href="$help_uri#toc0" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<div class="col2-cats" <!--#if int($email_endjob) > 0 then '' else 'style="display:none"'#-->>
<b>$T('affectedCat')</b><br/>
<select name="email_cats" multiple="multiple" class="multiple_cats" size="$len($categories)">
@@ -153,7 +153,7 @@
<!--#if $have_ntfosd#-->
<div class="section">
<div class="col2">
<h3>$T('section-OSD') <a href="$helpuri$help_uri#toc4" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('section-OSD') <a href="$help_uri#toc4" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<table>
<tr>
<td><input type="checkbox" name="ntfosd_enable" id="ntfosd_enable" value="1" <!--#if int($ntfosd_enable) > 0 then 'checked="checked"' else ""#--> /></td>
@@ -178,14 +178,14 @@
<!--#end if#-->
<div class="section" id="nscript">
<div class="col2">
<h3>$T('section-NScript') <a href="$helpuri$help_uri#nscript" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('section-NScript') <a href="$help_uri#nscript" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<table>
<tr>
<td><input type="checkbox" name="nscript_enable" id="nscript_enable" value="1" <!--#if int($nscript_enable) > 0 then 'checked="checked"' else ""#--> /></td>
<td><label for="nscript_enable"> $T('opt-nscript_enable')</label></td>
</tr>
</table>
<em>$T('explain-nscript_enable')</em><br><a href="$helpuri$help_uri#nscript" target="_blank">$T('readwiki')</a>
<em>$T('explain-nscript_enable')</em><br><a href="$help_uri#nscript" target="_blank">$T('readwiki')</a>
$show_cat_box('nscript')
</div>
<div class="col1" <!--#if int($nscript_enable) > 0 then '' else 'style="display:none"'#-->>

View File

@@ -1,12 +1,12 @@
<!--#set global $pane="RSS"#-->
<!--#set global $help_uri="configuration/4.0/rss"#-->
<!--#set global $help_uri = $confighelpuri + "rss"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#import html#-->
<div class="colmask">
<!--#if not $active_feed#-->
<div class="section">
<div class="padTable">
<a class="main-helplink" href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<a class="main-helplink" href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<p>$T('explain-RSS')</p>
<form action="add_rss_feed" method="post" autocomplete="off">
<input type="hidden" name="apikey" value="$apikey" />
@@ -105,7 +105,7 @@
<!--#set $feed = html.unescape($active_feed)#-->
<div class="section rss-section">
<div class="padTable">
<a class="main-helplink" href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<a class="main-helplink" href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<h2 class="nomargin activeRSS">
<a href="${root}config/rss/">$T('cmenu-rss')</a> &raquo;
$active_feed

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Scheduling"#-->
<!--#set global $help_uri="configuration/4.0/scheduling"#-->
<!--#set global $help_uri = $confighelpuri + "scheduling"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<%
@@ -15,7 +15,7 @@ else:
<div class="colmask">
<div class="section">
<div class="col2">
<h3>$T('addSchedule') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('addSchedule') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<form action="addSchedule" method="post" autocomplete="off">
<input type="hidden" id="apikey" name="apikey" value="$apikey" />

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Servers"#-->
<!--#set global $help_uri="configuration/4.0/servers"#-->
<!--#set global $help_uri = $confighelpuri + "servers"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<!--#import json#-->
@@ -29,7 +29,7 @@
</div>
<div class="section" id="addServerContent" style="display: none;">
<div class="col2">
<h3>$T('addServer') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('addServer') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div>
<div class="col1">
<form action="addServer" method="post" autocomplete="off" onsubmit="removeObfuscation();">
@@ -96,7 +96,7 @@
<label class="config" for="ssl_ciphers">$T('opt-ssl_ciphers')</label>
<input type="text" name="ssl_ciphers" id="ssl_ciphers" />
<span class="desc">$T('explain-ssl_ciphers') <br>$T('readwiki')
<a href="${helpuri}advanced/ssl-ciphers" target="_blank">${helpuri}advanced/ssl-ciphers</a></span>
<a href="https://sabnzbd.org/wiki/advanced/ssl-ciphers" target="_blank">https://sabnzbd.org/wiki/advanced/ssl-ciphers</a></span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="send_group">$T('srv-send_group')</label>
@@ -151,7 +151,7 @@
<div class="section <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
<div class="col2 <!--#if int($server['enable']) == 0 then 'server-disabled' else ""#-->">
<h3 title="$server['displayname']">$server['displayname'] <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3 title="$server['displayname']">$server['displayname'] <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<!--#if int($server['enable']) != 0 #-->
<!--#if $last_prio != $server['priority'] and $cur_prio_color+1 < len($prio_colors) #-->
<!--#set $cur_prio_color = $cur_prio_color+1 #-->
@@ -228,7 +228,7 @@
<label class="config" for="ssl_ciphers$cur">$T('opt-ssl_ciphers')</label>
<input type="text" name="ssl_ciphers" id="ssl_ciphers$cur" value="$server['ssl_ciphers']" />
<span class="desc">$T('explain-ssl_ciphers') <br>$T('readwiki')
<a href="${helpuri}advanced/ssl-ciphers" target="_blank">${helpuri}advanced/ssl-ciphers</a></span>
<a href="https://sabnzbd.org/wiki/advanced/ssl-ciphers" target="_blank">https://sabnzbd.org/wiki/advanced/ssl-ciphers</a></span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="required$cur">$T('srv-required')</label>

View File

@@ -1,9 +1,9 @@
<!--#set global $pane="Sorting"#-->
<!--#set global $help_uri="configuration/4.0/sorting"#-->
<!--#set global $help_uri = $confighelpuri + "sorting"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="padTable section explain-sorting">
<a class="main-helplink" href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
<a class="main-helplink" href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a>
$T('explain-sorting')
</div>
<div class="colmask">
@@ -33,9 +33,9 @@
</div>
<div class="col2">
<!--#if $cur == 0#-->
<h3>$T('add-sorter') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('add-sorter') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<!--#else#-->
<h3>$slot.name <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$slot.name <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<div class="sorter-switch-container wide">
<input type="checkbox" class="toggleSorterCheckbox sorter-switch float-left" rel="$slot.name" name="is_active" id="is_active_$cur" value="$slot.is_active" <!--#if $slot.is_active != 0 then 'checked="checked"' else ""#--> />
<label class="sorter-switch float-left" for="is_active_$cur">$T('enabled')</label>
@@ -472,6 +472,7 @@
ui.placeholder.height(hPlaceholder + hExtra);
\$('<div class="sorter-placeholder-anim" data-height="' + hPlaceholder + '"></div>').insertAfter(ui.placeholder);
},
cancel: ".pattern-table",
change: function(event, ui) {
ui.placeholder.stop().height(0).animate({
height: ui.item.outerHeight() + hExtra

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Special"#-->
<!--#set global $help_uri="configuration/4.0/special"#-->
<!--#set global $help_uri = $confighelpuri + "special"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
@@ -10,7 +10,7 @@
</div>
<div class="section">
<div class="col2">
<h3>$T('sptag-boolean') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('sptag-boolean') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -33,7 +33,7 @@
</div><!-- /section -->
<div class="section">
<div class="col2">
<h3>$T('sptag-entries') <a href="$helpuri$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('sptag-entries') <a href="$help_uri" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>

View File

@@ -1,5 +1,5 @@
<!--#set global $pane="Switches"#-->
<!--#set global $help_uri="configuration/4.0/switches"#-->
<!--#set global $help_uri = $confighelpuri + "switches"#-->
<!--#include $webdir + "/_inc_header_uc.tmpl"#-->
<div class="colmask">
@@ -14,7 +14,7 @@
<input type="hidden" name="output" value="json" />
<div class="section advanced-settings">
<div class="col2">
<h3>$T('swtag-server') <a href="$helpuri$help_uri#toc1" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('swtag-server') <a href="$help_uri#toc1" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -46,7 +46,7 @@
</div><!-- /section -->
<div class="section">
<div class="col2">
<h3>$T('swtag-queue') <a href="$helpuri$help_uri#toc2" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('swtag-queue') <a href="$help_uri#toc2" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -165,7 +165,7 @@
</div><!-- /section -->
<div class="section">
<div class="col2">
<h3>$T('swtag-pp') <a href="$helpuri$help_uri#toc3" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('swtag-pp') <a href="$help_uri#toc3" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -274,7 +274,7 @@
</div><!-- /section -->
<div class="section advanced-settings">
<div class="col2">
<h3>$T('swtag-naming') <a href="$helpuri$help_uri#toc4" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('swtag-naming') <a href="$help_uri#toc4" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>
@@ -314,7 +314,7 @@
</div><!-- /section -->
<div class="section">
<div class="col2">
<h3>$T('swtag-quota') <a href="$helpuri$help_uri#toc5" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
<h3>$T('swtag-quota') <a href="$help_uri#toc5" target="_blank"><span class="glyphicon glyphicon-question-sign"></span></a></h3>
</div><!-- /col2 -->
<div class="col1">
<fieldset>

View File

@@ -32,7 +32,7 @@
</div>
<hr/>
<p>$T('wizard-tip-wiki') <a target="_blank" href="$helpuri">$T('menu-wiki')</a> <span class="glyphicon glyphicon-info-sign"></span></p>
<p>$T('wizard-tip-wiki') <a target="_blank" href="https://sabnzbd.org/wiki/">$T('menu-wiki')</a> <span class="glyphicon glyphicon-info-sign"></span></p>
</div>
<hr />

View File

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

View File

@@ -4,7 +4,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0Beta2\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Language-Team: Czech (https://app.transifex.com/sabnzbd/teams/111101/cs/)\n"
"MIME-Version: 1.0\n"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -5,7 +5,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.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"
@@ -270,6 +270,11 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr ""
#. Warning message
#: sabnzbd/cfg.py
msgid "Do not use a folder in the application folder as your Scripts Folder, it might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -406,6 +411,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr ""
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr ""
@@ -555,12 +565,22 @@ msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable with special character filenames. This can cause problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable with special character filenames. This can cause problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1410,11 +1430,11 @@ msgid "Running user script %s"
msgstr ""
#: sabnzbd/postproc.py
msgid "Ran %s"
msgid "Script exit code is %s"
msgstr ""
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgid "Ran %s"
msgstr ""
#: sabnzbd/postproc.py, sabnzbd/skintext.py
@@ -2783,7 +2803,7 @@ msgid "Watched Folder"
msgstr ""
#: sabnzbd/skintext.py
msgid "Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz archives for .nzb files.</i>"
msgid "Folder to monitor for .nzb files."
msgstr ""
#: sabnzbd/skintext.py

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Czech (https://app.transifex.com/sabnzbd/teams/111101/cs/)\n"
@@ -297,6 +297,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Chyba: Fronta nené prázdná, nelze změnit složku."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -440,6 +447,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr ""
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Příliš mnoho spojení k serveru %s [%s]"
@@ -591,14 +603,24 @@ msgstr "Načítání %s selhalo"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1482,14 +1504,14 @@ msgstr "Nezdařilo se přesunout soubory"
msgid "Running user script %s"
msgstr "Spouštím uživatelský skript %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Spuštěno %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Navratový kód skriptu je %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Spuštěno %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Více"
@@ -2912,9 +2934,7 @@ msgid "Watched Folder"
msgstr ""
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgid "Folder to monitor for .nzb files."
msgstr ""
#: sabnzbd/skintext.py

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Danish (https://app.transifex.com/sabnzbd/teams/111101/da/)\n"
@@ -297,6 +297,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Fejl: Køen er ikke tom, kan ikke skifte mappe."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -438,6 +445,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Det lykkedes ikke at initialisere %s@%s med begrundelse %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Alt for mange forbindelser til serveren %s [%s]"
@@ -599,14 +611,24 @@ msgstr "Downloadning af %s mislykkedes"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1513,14 +1535,14 @@ msgstr "Kunne ikke flytte filer"
msgid "Running user script %s"
msgstr "Kør bruger script %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Kørte %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Script exit kode er %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Kørte %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Mere"
@@ -2971,12 +2993,8 @@ msgid "Watched Folder"
msgstr "Overvåget Mappe"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Mappe til at gennemsøge for. Nzb filer.<br /><i>Skanner også for .zip .rar "
"og .tar.gz arkiver efter .nzb filer.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Mappe til at gennemsøge for .nzb filer."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -11,14 +11,14 @@
# Simon W., 2021
# Nils Briggen, 2022
# reloxx13 <reloxx@interia.pl>, 2022
# Safihre <safihre@sabnzbd.org>, 2023
# kameb, 2023
# Safihre <safihre@sabnzbd.org>, 2023
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: kameb, 2023\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: German (https://app.transifex.com/sabnzbd/teams/111101/de/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -320,6 +320,13 @@ msgstr ""
"Fehler: Ordner kann nicht geändert werden, da die Warteschlange nicht leer "
"ist."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -468,6 +475,11 @@ 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"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Zu viele Verbindungen zu Server %s [%s]"
@@ -631,6 +643,21 @@ msgstr "Fehler beim Speichern von %s"
msgid "Loading %s failed"
msgstr "Fehler beim Laden von %s"
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr "%s ist nicht beschreibbar. Downloads sind dadurch blockiert."
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
@@ -640,11 +667,6 @@ msgstr ""
"Dateinamen mit Umlaute können nicht in %s gespeichert werden. Dies kann zu "
"Problemen führen."
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr "%s ist nicht beschreibbar. Downloads sind dadurch blockiert."
#: sabnzbd/interface.py
msgid "Refused connection from:"
msgstr "Abgelehnte Verbindung von:"
@@ -1580,14 +1602,14 @@ msgstr "Dateien verschieben fehlgeschlagen"
msgid "Running user script %s"
msgstr "Ausführen des Benutzer-Skripts %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s ausgeführt"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Exit-Code des Skripts ist %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s ausgeführt"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Mehr"
@@ -3080,12 +3102,8 @@ msgid "Watched Folder"
msgstr "Überwachter Ordner"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Ordner, der auf neue NZB-Dateien überwacht werden soll.<br /><i>Erkennt auch"
" ZIP-, RAR- und TAR.GZ-Archive mit NZB-Dateien.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Ordner, der auf neue .nzb Dateien überwacht werden soll."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -9,7 +9,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Spanish (https://app.transifex.com/sabnzbd/teams/111101/es/)\n"
@@ -312,6 +312,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Error: Cola no esta vacía, no se puede cambiar el directorio"
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -459,6 +466,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Error al inicializar %s@%s con la razón: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Demasiadas conexiones con el servidor %s [%s]"
@@ -621,14 +633,24 @@ msgstr "Cargar de %s no se pudo completar."
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1567,14 +1589,14 @@ msgstr "Error al mover ficheros"
msgid "Running user script %s"
msgstr "Ejecutando script de usuario %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Se ejecutó %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "El código de retorno del Script es %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Se ejecutó %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Más"
@@ -3050,12 +3072,8 @@ msgid "Watched Folder"
msgstr "Directorio a vigilar"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Directorio a monitorizar en busca de ficheros .nzb.<br /><i>También escanea "
"ficheros .zip .rar y .tar.gz en busca de ficheros .nzb.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Directorio a monitorizar en busca de ficheros .nzb."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Finnish (https://app.transifex.com/sabnzbd/teams/111101/fi/)\n"
@@ -295,6 +295,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Virhe: Jono ei ole tyhjä, kansiota ei voida vaihtaa."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -435,6 +442,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Alustaminen epäonnistui kohteessa %s@%s syy: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Liikaa yhteyksiä palvelimelle %s [%s]"
@@ -596,14 +608,24 @@ msgstr "Kohteen %s lataaminen epäonnistui"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1507,14 +1529,14 @@ msgstr "Tiedostojen siirto epäonnistui"
msgid "Running user script %s"
msgstr "Ajetaan käyttäjän skripti %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Ajettiin %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Skriptin lopetuskoodi on %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Ajettiin %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Lisää"
@@ -2974,12 +2996,8 @@ msgid "Watched Folder"
msgstr "Vahdittu kansio"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Kansio jota vahditaan .nzb tiedostojen varalta.<br /><i>Etsii .nzb "
"tiedostoja myös .zip .rar ja .tar.gz arkistojen sisältä.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Kansio jota vahditaan .nzb tiedostojen varalta."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Fred L <88com88@gmail.com>, 2023\n"
"Language-Team: French (https://app.transifex.com/sabnzbd/teams/111101/fr/)\n"
@@ -317,6 +317,15 @@ msgid "Error: Queue not empty, cannot change folder."
msgstr ""
"Erreur : La file d'attente n'est pas vide, impossible de changer le dossier."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
"N'utilisez pas un dossier à l'intérieur du dossier de l'application pour y "
"stocker les scripts, il pourrait être vidé lors des mises à jour."
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -463,6 +472,11 @@ 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"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr "Erreur fatale dans le Téléchargeur"
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Trop de connexions au serveur %s [%s]"
@@ -626,6 +640,25 @@ msgstr "L'enregistrement de %s a échoué"
msgid "Loading %s failed"
msgstr "Echec du chargement de %s"
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr "%s n'est pas du tout inscriptible. Les téléchargements sont bloqués."
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
"Impossible d'écrire un nom de fichier long dans %s. Cela peut causer des "
"problèmes."
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
"Impossible d'écrire un nom de fichier unicode dans %s. Cela peut causer des "
"problèmes."
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
@@ -635,11 +668,6 @@ msgstr ""
"Le fichier %s n'est pas inscriptible à cause des caractères spéciaux dans le"
" nom. Cela peut causer des problèmes."
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr "%s n'est pas du tout inscriptible. Les téléchargements sont bloqués."
#: sabnzbd/interface.py
msgid "Refused connection from:"
msgstr "Connexion refusée de:"
@@ -1571,14 +1599,14 @@ msgstr "Impossible de déplacer les fichiers"
msgid "Running user script %s"
msgstr "Exécution du script utilisateur %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s exécuté"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Le code script de sortie est %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s exécuté"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Plus"
@@ -3073,12 +3101,8 @@ msgid "Watched Folder"
msgstr "Dossier à surveiller"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Dossier d'import automatique des fichiers .nzb.<br /><i>Prends en compte "
"également les nzb contenus dans les fichiers .zip, .rar et .tar.gz.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Dossier d'import automatique des fichiers .nzb."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"
@@ -4748,6 +4772,7 @@ msgstr "Raccourcis clavier"
#: sabnzbd/skintext.py
msgid "Shift+Arrow key: Browse Queue and History pages"
msgstr ""
"Maj+flèche : parcourir les pages de la file d'attente et de l'historique"
#: sabnzbd/skintext.py
msgid "How long or untill when do you want to pause? (in English!)"

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Hebrew (https://app.transifex.com/sabnzbd/teams/111101/he/)\n"
@@ -294,6 +294,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "שגיאה: התור אינו ריק, לא ניתן לשנות תיקייה."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -435,6 +442,11 @@ msgstr "אין שרתים פעילים!"
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "נכשל באתחול %s@%s עם סיבה: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "יותר מדי חיבורים לשרת %s [%s]"
@@ -594,6 +606,21 @@ msgstr "שמירת %s נכשלה"
msgid "Loading %s failed"
msgstr "טעינת %s נכשלה"
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr "%s אינו בר־כתיבה בכלל. זה חוסם הורדות."
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
@@ -601,11 +628,6 @@ msgid ""
"problems."
msgstr "%s אינו בר־כתיבה עם שמות קבצים עם תו מיוחד. זה יכול לגרום לבעיות."
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr "%s אינו בר־כתיבה בכלל. זה חוסם הורדות."
#: sabnzbd/interface.py
msgid "Refused connection from:"
msgstr "חיבור מסורב מאת:"
@@ -1514,14 +1536,14 @@ msgstr "נכשל בהעברת קבצים"
msgid "Running user script %s"
msgstr "מריץ תסריט משתמש %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "הריץ את %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "קוד יציאת תסריט הוא %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "הריץ את %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "עוד"
@@ -2982,12 +3004,8 @@ msgid "Watched Folder"
msgstr "תיקייה מושגחת"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"תיקייה לניטור אחר קבצי nzb.<br /><i>סורק גם ארכיונים מסוג .zip .rar "
"ו־.tar.gz ואחר קבצי nzb.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "תיקייה לניטור אחר קבצי nzb."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Norwegian Bokmål (https://app.transifex.com/sabnzbd/teams/111101/nb/)\n"
@@ -291,6 +291,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Feil: Køen er ikke tom, kan ikke bytte mappe."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -430,6 +437,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Feilet å starte %s@%s grunnet: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "For mange tilkoblinger til server %s [%s]"
@@ -591,14 +603,24 @@ msgstr "Lasting av %s mislyktes"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1503,14 +1525,14 @@ msgstr "Klarte ikke å flytte filer"
msgid "Running user script %s"
msgstr "Kjør brukerskript %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Kjørte i %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Skript-avsluttingskode er %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Kjørte i %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Mer"
@@ -2959,12 +2981,8 @@ msgid "Watched Folder"
msgstr "Overvåket Mappe"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Mappe som automatiskt søkes igjennom etter .nzb filer.<br /><i>Skanner også "
"igjennom .zip .rar og .tar.gz arkiver etter .nzb filer.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Mappe som automatiskt søkes igjennom etter .nzb filer."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -4,11 +4,12 @@
#
# Translators:
# Rik Brouwer, 2022
# Robert Lampe, 2023
# Safihre <safihre@sabnzbd.org>, 2023
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Dutch (https://app.transifex.com/sabnzbd/teams/111101/nl/)\n"
@@ -308,6 +309,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Fout: Wachtrij is niet leeg, andere map kiezen niet mogelijk."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -457,6 +465,11 @@ msgstr "Er zijn geen actieve servers!"
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Initialisatie van %s@%s mislukt, vanwege: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Te veel verbindingen met server %s [%s]"
@@ -618,6 +631,23 @@ msgstr "Opslaan van %s lukt niet"
msgid "Loading %s failed"
msgstr "Inlezen van %s mislukt"
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
"Het is niet mogelijk bestanden te schrijven in %s. Hierdoor kan er niet "
"gedownload worden."
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
@@ -627,13 +657,6 @@ msgstr ""
"Het is niet mogelijk bestanden met speciale tekens op te slaan in %s. Dit "
"geeft mogelijk problemen bij het verwerken van downloads."
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
"Het is niet mogelijk bestanden te schrijven in %s. Hierdoor kan er niet "
"gedownload worden."
#: sabnzbd/interface.py
msgid "Refused connection from:"
msgstr "Verbinding geweigerd van: "
@@ -703,11 +726,11 @@ msgstr "Feed"
#: sabnzbd/interface.py
msgid "Daily"
msgstr "dagelijks"
msgstr "Dagelijks"
#: sabnzbd/interface.py, sabnzbd/skintext.py
msgid "Monday"
msgstr "maandag"
msgstr "Maandag"
#: sabnzbd/interface.py, sabnzbd/skintext.py
msgid "Tuesday"
@@ -1553,14 +1576,14 @@ msgstr "Verplaatsen van bestanden mislukt"
msgid "Running user script %s"
msgstr "Gebruiker script %s loopt"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s is klaar"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Exit code van het script is %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s is klaar"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Meer"
@@ -3036,12 +3059,9 @@ msgid "Watched Folder"
msgstr "Bewaakte map"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgid "Folder to monitor for .nzb files."
msgstr ""
".NZB en .ZIP-bestanden in deze map worden automatisch toegevoegd aan de "
"wachtrij."
".nzb bestanden in deze map worden automatisch toegevoegd aan de wachtrij."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"
@@ -4384,7 +4404,7 @@ msgstr "GuessIt_Eigenschap"
#: sabnzbd/skintext.py
msgid "Minimum Filesize"
msgstr ""
msgstr "Minimale bestandsgrootte"
#: sabnzbd/skintext.py
msgid "Affected Job Types"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Polish (https://app.transifex.com/sabnzbd/teams/111101/pl/)\n"
@@ -287,6 +287,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Błąd: Kolejka nie jest pusta, nie można zmienić katalogu."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -428,6 +435,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Błąd podczas inicjalizacji %s@%s: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Zbyt wiele połączeń do serwera %s [%s]"
@@ -591,14 +603,24 @@ msgstr "Nie udało się wczytać %s"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1509,14 +1531,14 @@ msgstr "Nie udało się przenieść plików"
msgid "Running user script %s"
msgstr "Uruchamianie skryptu użytkownika %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Uruchomiono %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Kod zakończenia skryptu: %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Uruchomiono %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Więcej"
@@ -2966,12 +2988,8 @@ msgid "Watched Folder"
msgstr "Obserwowany katalog"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Katalog monitorowany w poszukiwaniu plików .nzb.<br /><i>Skanowane są "
"również pliki .zip, .rar oraz .tar.gz.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Katalog monitorowany w poszukiwaniu plików .nzb."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Portuguese (Brazil) (https://app.transifex.com/sabnzbd/teams/111101/pt_BR/)\n"
@@ -291,6 +291,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Erro: A fila não está vazia. Não será possível mudar de pasta."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -434,6 +441,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Falha ao iniciar %s@%s devido as seguintes razões: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Excesso de conexões ao servidor %s [%s]"
@@ -595,14 +607,24 @@ msgstr "Falha ao carregar %s"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1511,14 +1533,14 @@ msgstr "Falha ao mover arquivos"
msgid "Running user script %s"
msgstr "Executando script de usuário %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s executado"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Código de saída do script é %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s executado"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Mais"
@@ -2968,12 +2990,8 @@ msgid "Watched Folder"
msgstr "Pasta de Assistidos"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Pasta para monitorar por arquivos .nzb.<br /><i>Também procura arquivos .nzb"
" em arquivos .zip, .rar e .tar.gz.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Pasta para monitorar por arquivos .nzb."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Romanian (https://app.transifex.com/sabnzbd/teams/111101/ro/)\n"
@@ -302,6 +302,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Eroare: Coada nu este goală, nu pot schimba dosar."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -447,6 +454,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Nu am putu inițializa %s@%s din cauza următorului motiv: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Prea multe conexiuni la serverul %s [%s]"
@@ -608,14 +620,24 @@ msgstr "Încărcarea %s nereuşită"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1539,14 +1561,14 @@ msgstr "Nu am putu muta fişier"
msgid "Running user script %s"
msgstr "Rulare script utilizator %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Durată %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Codul de ieșire a scriptului este %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Durată %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Mai mult"
@@ -2995,12 +3017,8 @@ msgid "Watched Folder"
msgstr "Dosar Monitorizat"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Dosar pentru supraveghere fişiere .nzb.<br /><i>Scanează de asemenea şi "
"arhivele .zip .rar .tar.gz de fişiere .nzb.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Dosar pentru supraveghere fişiere .nzb."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Russian (https://app.transifex.com/sabnzbd/teams/111101/ru/)\n"
@@ -291,6 +291,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Ошибка: очередь не пустая, папку нельзя изменить."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -430,6 +437,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr ""
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr ""
@@ -591,14 +603,24 @@ msgstr "Ошибка загрузки %s"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1508,14 +1530,14 @@ msgstr "Не удалось переместить файлы"
msgid "Running user script %s"
msgstr "Запуск пользовательского сценария %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Запущено %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr ""
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Запущено %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Подробнее"
@@ -2964,12 +2986,8 @@ msgid "Watched Folder"
msgstr "Наблюдаемая папка"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Папка для поиска NZB-файлов.<br /><i>NZB-файлы также ищутся в архивах ZIP, "
"RAR и TAR.GZ.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Папка для поиска NZB-файлов."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Serbian (https://app.transifex.com/sabnzbd/teams/111101/sr/)\n"
@@ -289,6 +289,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Грешка: ред није празан, фасцикла се не може променити."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -429,6 +436,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Neuspešna inicijalizacija %s@%s iz razloga: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "Previše konekcija ka serveru %s [%s]"
@@ -590,14 +602,24 @@ msgstr "Učitavanje %s neuspešno"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1500,14 +1522,14 @@ msgstr "Неуспешно премештање датотека"
msgid "Running user script %s"
msgstr "Покретање скрипта %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s покренуто"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Kod prekida skripte je %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "%s покренуто"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Више"
@@ -2950,13 +2972,8 @@ msgid "Watched Folder"
msgstr "Надгледана фасцикла"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Фасцикла за надгледање <b>.nzb</b> датотека.<br /><i>Такође скенира "
"<b>.zip</b> <b>.rar</b> и <b>.tar.gz</b> архиве у потрази за <b>.nzb</b> "
"датотекама.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Фасцикла за надгледање .nzb датотека."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Swedish (https://app.transifex.com/sabnzbd/teams/111101/sv/)\n"
@@ -289,6 +289,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "Fel: Kön är inte tom, kan inte byta mapp."
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -429,6 +436,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "Misslyckades att initiera %s@%s med orsak %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "För många anslutningar till servern %s [%s]"
@@ -590,14 +602,24 @@ msgstr "Laddning av %s misslyckades"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1506,14 +1528,14 @@ msgstr "Misslyckades med att flytta filer"
msgid "Running user script %s"
msgstr "Kör användarskript %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Körde %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "Skriptets utgångskod är %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "Körde %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "Mer"
@@ -2961,12 +2983,8 @@ msgid "Watched Folder"
msgstr "Övervakad Mapp"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"Mapp som igenomsöks automatiskt efter .nzb filer.<br /><i>Skannar även "
"igenom .zip .rar och .tar.gz arkiv efter .nzb filer.</i>"
msgid "Folder to monitor for .nzb files."
msgstr "Mapp som igenomsöks automatiskt efter .nzb filer."
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:49+0000\n"
"Last-Translator: Safihre <safihre@sabnzbd.org>, 2023\n"
"Language-Team: Chinese (China) (https://app.transifex.com/sabnzbd/teams/111101/zh_CN/)\n"
@@ -287,6 +287,13 @@ msgstr ""
msgid "Error: Queue not empty, cannot change folder."
msgstr "错误: 队列非空,无法变更文件夹。"
#. Warning message
#: sabnzbd/cfg.py
msgid ""
"Do not use a folder in the application folder as your Scripts Folder, it "
"might be emptied during updates."
msgstr ""
#. Warning message
#: sabnzbd/config.py
msgid "Configuration locked, cannot save settings"
@@ -426,6 +433,11 @@ msgstr ""
msgid "Failed to initialize %s@%s with reason: %s"
msgstr "无法初始化 %s@%s原因为: %s"
#. Error message
#: sabnzbd/downloader.py
msgid "Fatal error in Downloader"
msgstr ""
#: sabnzbd/downloader.py
msgid "Too many connections to server %s [%s]"
msgstr "服务器 %s 连接数过多 [%s]"
@@ -587,14 +599,24 @@ msgstr "加载 %s 失败"
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgid "%s is not writable at all. This blocks downloads."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "%s is not writable at all. This blocks downloads."
msgid "Cannot write a long filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid "Cannot write a unicode filename to %s. This can cause problems."
msgstr ""
#. Warning message
#: sabnzbd/filesystem.py
msgid ""
"%s is not writable with special character filenames. This can cause "
"problems."
msgstr ""
#: sabnzbd/interface.py
@@ -1493,14 +1515,14 @@ msgstr "移动文件失败"
msgid "Running user script %s"
msgstr "正在执行用户脚本 %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "执行 %s"
#: sabnzbd/postproc.py
msgid "Script exit code is %s"
msgstr "脚本退出代码为 %s"
#: sabnzbd/postproc.py
msgid "Ran %s"
msgstr "执行 %s"
#: sabnzbd/postproc.py, sabnzbd/skintext.py
msgid "More"
msgstr "更多"
@@ -2921,11 +2943,8 @@ msgid "Watched Folder"
msgstr "监视文件夹"
#: sabnzbd/skintext.py
msgid ""
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz "
"archives for .nzb files.</i>"
msgstr ""
"要监视 .nzb 文件的文件夹。<br /><i>会同时扫描 .zip .rar 及 .tar.gz 压缩文件中的 .nzb 文件。</i>"
msgid "Folder to monitor for .nzb files."
msgstr "要监视 .nzb 文件的文件夹。"
#: sabnzbd/skintext.py
msgid "Watched Folder Scan Speed"

View File

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

View File

@@ -7,7 +7,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0Beta2\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Pavel C <quoing_transifex@mess.cz>, 2022\n"
"Language-Team: Czech (https://app.transifex.com/sabnzbd/teams/111101/cs/)\n"

View File

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

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0RC1\n"
"Project-Id-Version: SABnzbd-4.1.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://app.transifex.com/sabnzbd/teams/111101/de/)\n"

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0Beta2\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Ester Molla Aragones <moarages@gmail.com>, 2020\n"
"Language-Team: Spanish (https://app.transifex.com/sabnzbd/teams/111101/es/)\n"

View File

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

View File

@@ -8,7 +8,7 @@
#
msgid ""
msgstr ""
"Project-Id-Version: SABnzbd-4.0.0Beta2\n"
"Project-Id-Version: SABnzbd-4.1.0-develop\n"
"PO-Revision-Date: 2020-06-27 15:56+0000\n"
"Last-Translator: Fred L <88com88@gmail.com>, 2021\n"
"Language-Team: French (https://app.transifex.com/sabnzbd/teams/111101/fr/)\n"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,7 +6,7 @@ cffi==1.15.1
pycparser==2.21
feedparser==6.0.10
configobj==5.0.8
cheroot==9.0.0
cheroot==10.0.0
six==1.16.0
cherrypy==18.8.0
jaraco.functools==3.6.0

View File

@@ -50,6 +50,7 @@ from sabnzbd.constants import (
KIBI,
MEBI,
GIGI,
AddNzbFileResult,
)
import sabnzbd.config as config
import sabnzbd.cfg as cfg
@@ -305,7 +306,7 @@ def _api_addfile(name, kwargs):
nzbname=kwargs.get("nzbname"),
password=kwargs.get("password"),
)
return report(keyword="", data={"status": res == 0, "nzo_ids": nzo_ids})
return report(keyword="", data={"status": res is AddNzbFileResult.OK, "nzo_ids": nzo_ids})
else:
return report(_MSG_NO_VALUE)
@@ -350,7 +351,7 @@ def _api_addlocalfile(name, kwargs):
nzbname=kwargs.get("nzbname"),
password=kwargs.get("password"),
)
return report(keyword="", data={"status": res == 0, "nzo_ids": nzo_ids})
return report(keyword="", data={"status": res is AddNzbFileResult.OK, "nzo_ids": nzo_ids})
else:
logging.info('API-call addlocalfile: "%s" is not a supported file', name)
return report(_MSG_NO_FILE)
@@ -1570,7 +1571,7 @@ def build_header(webdir: str = "", for_template: bool = True, trans_functions: b
header["uptime"] = calc_age(sabnzbd.START)
header["color_scheme"] = sabnzbd.WEB_COLOR or ""
header["helpuri"] = "https://sabnzbd.org/wiki/"
header["confighelpuri"] = f"https://sabnzbd.org/wiki/configuration/{sabnzbd.__version__[:3]}/"
header["pid"] = os.getpid()
header["active_lang"] = cfg.language()

View File

@@ -20,6 +20,7 @@ sabnzbd.cfg - Configuration Parameters
"""
import logging
import os
import re
import argparse
import socket
@@ -50,6 +51,7 @@ from sabnzbd.constants import (
DEF_HTTPS_CERT_FILE,
DEF_HTTPS_KEY_FILE,
)
from sabnzbd.filesystem import long_path
##############################################################################
@@ -231,6 +233,18 @@ def validate_safedir(root, value, default):
return T("Error: Queue not empty, cannot change folder."), None
def validate_scriptdir_not_appdir(root, value, default):
"""Warn users to not use the Program Files folder for their scripts"""
if value and long_path(os.path.join(root, value)).startswith(long_path(sabnzbd.DIR_PROG)):
# Warn, but do not block
sabnzbd.misc.helpful_warning(
T(
"Do not use a folder in the application folder as your Scripts Folder, it might be emptied during updates."
)
)
return None, value
def validate_notempty(root, value, default):
"""If value is empty, return default"""
if value:
@@ -304,7 +318,7 @@ complete_dir = OptionDir(
)
complete_free = OptionStr("misc", "complete_free")
fulldisk_autoresume = OptionBool("misc", "fulldisk_autoresume", False)
script_dir = OptionDir("misc", "script_dir", writable=False)
script_dir = OptionDir("misc", "script_dir", writable=False, validation=validate_scriptdir_not_appdir)
nzb_backup_dir = OptionDir("misc", "nzb_backup_dir", DEF_NZBBACK_DIR)
admin_dir = OptionDir("misc", "admin_dir", DEF_ADMIN_DIR, validation=validate_safedir)
backup_dir = OptionDir("misc", "backup_dir")

View File

@@ -162,3 +162,10 @@ class Status:
VERIFYING = "Verifying" # PP: Job is being verified (by par2)
DELETED = "Deleted" # Q: Job has been deleted (and is almost gone)
PROP = "Propagating" # Q: Delayed download
class AddNzbFileResult:
RETRY = "Retry" # File could not be read
ERROR = "Error" # Rejected as duplicate, by pre-queue script or other failure to process file
OK = "OK" # Added to queue
NO_FILES_FOUND = "No files found" # Malformed or might not be an NZB file

View File

@@ -292,7 +292,7 @@ def decode_uu(article: Article, raw_data: bytearray) -> bytes:
except binascii.Error as msg:
try:
# Workaround for broken uuencoders by Fredrik Lundh
nbytes = (((ord(line[0]) - 32) & 63) * 4 + 5) / 3
nbytes = (((line[0] - 32) & 63) * 4 + 5) // 3
decoded_line = binascii.a2b_uu(line[:nbytes])
except Exception as msg2:
logging.info(

View File

@@ -33,6 +33,7 @@ import logging
import os
import re
import sabnzbd
from sabnzbd.filesystem import get_unique_filename, renamer, get_ext
from sabnzbd.par2file import is_parfile, parse_par2_file
import sabnzbd.utils.file_extension as file_extension
@@ -223,8 +224,8 @@ def deobfuscate(nzo, filelist: List[str], usefulname: str):
# Can't be imported directly due to circular import
nzo: sabnzbd.nzbstuff.NzbObject
# to be sure, only keep really existing files:
filelist = [f for f in filelist if os.path.isfile(f)]
# to be sure, only keep really existing files and remove any duplicates:
filelist = set(f for f in filelist if os.path.isfile(f))
# Do not deobfuscate/rename anything if there is a typical DVD or Bluray directory:
ignored_movie_folders_with_dir_sep = tuple(os.path.sep + f + os.path.sep for f in IGNORED_MOVIE_FOLDERS)

View File

@@ -439,7 +439,9 @@ class DirectUnpacker(threading.Thread):
self.cur_volume = 1
# Need to disable buffer to have direct feedback
self.active_instance = build_and_run_command(command, windows_unrar_command=True, bufsize=0)
self.active_instance = build_and_run_command(
command, windows_unrar_command=True, text_mode=False, stdin=subprocess.PIPE
)
# Add to runners
ACTIVE_UNPACKERS.append(self)

View File

@@ -26,7 +26,7 @@ import threading
from typing import Generator, Set, Optional, Tuple
import sabnzbd
from sabnzbd.constants import SCAN_FILE_NAME, VALID_ARCHIVES, VALID_NZB_FILES
from sabnzbd.constants import SCAN_FILE_NAME, VALID_ARCHIVES, VALID_NZB_FILES, AddNzbFileResult
import sabnzbd.filesystem as filesystem
import sabnzbd.config as config
import sabnzbd.cfg as cfg
@@ -205,10 +205,10 @@ class DirScanner(threading.Thread):
# Add the NZB's
res, _ = sabnzbd.nzbparser.add_nzbfile(path, catdir=catdir, keep=False)
if res < 0:
if res is AddNzbFileResult.RETRY or res is AddNzbFileResult.ERROR:
# Retry later, for example when we can't read the file
self.suspected[path] = stat_tuple
elif res == 0:
elif res is AddNzbFileResult.OK:
self.error_reported = False
else:
self.ignored[path] = 1

View File

@@ -582,208 +582,185 @@ class Downloader(Thread):
BPSMeter.update()
next_bpsmeter_update = 0
# Debugging code for v4 test release
sleep_count_start: float = time.time()
sleep_count: int = 0
time_slept: float = 0
# Check server expiration dates
check_server_expiration()
while 1:
now = time.time()
# Catch all errors, just in case
try:
while 1:
now = time.time()
# Set Article to None so references from this
# thread do not keep the parent objects alive (see #1628)
article = None
# Set Article to None so references from this
# thread do not keep the parent objects alive (see #1628)
article = None
for server in self.servers:
# Skip this server if there's no point searching for new stuff to do
if not server.busy_threads and server.next_article_search > now:
continue
if server.next_busy_threads_check < now:
server.next_busy_threads_check = now + _SERVER_CHECK_DELAY
for nw in server.busy_threads[:]:
if (nw.nntp and nw.nntp.error_msg) or (nw.timeout and now > nw.timeout):
if nw.nntp and nw.nntp.error_msg:
# Already showed error
self.__reset_nw(nw)
else:
self.__reset_nw(nw, "timed out", warn=True)
server.bad_cons += 1
self.maybe_block_server(server)
if server.restart:
if not server.busy_threads:
newid = server.newid
server.stop()
self.servers.remove(server)
if newid:
self.init_server(None, newid)
self.server_restarts -= 1
# Have to leave this loop, because we removed element
break
else:
# Restart pending, don't add new articles
for server in self.servers:
# Skip this server if there's no point searching for new stuff to do
if not server.busy_threads and server.next_article_search > now:
continue
if (
not server.idle_threads
or self.no_active_jobs()
or self.shutdown
or self.paused_for_postproc
or not server.active
):
if server.next_busy_threads_check < now:
server.next_busy_threads_check = now + _SERVER_CHECK_DELAY
for nw in server.busy_threads[:]:
if (nw.nntp and nw.nntp.error_msg) or (nw.timeout and now > nw.timeout):
if nw.nntp and nw.nntp.error_msg:
# Already showed error
self.__reset_nw(nw)
else:
self.__reset_nw(nw, "timed out", warn=True)
server.bad_cons += 1
self.maybe_block_server(server)
if server.restart:
if not server.busy_threads:
server.stop()
self.servers.remove(server)
if newid := server.newid:
self.init_server(None, newid)
self.server_restarts -= 1
# Have to leave this loop, because we removed element
break
else:
# Restart pending, don't add new articles
continue
if (
not server.idle_threads
or self.no_active_jobs()
or self.shutdown
or self.paused_for_postproc
or not server.active
):
continue
for nw in server.idle_threads[:]:
if nw.timeout:
if now < nw.timeout:
continue
else:
nw.timeout = None
if not server.info:
# Only request info if there's stuff in the queue
if not sabnzbd.NzbQueue.is_empty():
self.maybe_block_server(server)
server.request_info()
break
nw.article = server.get_article()
if not nw.article:
break
server.idle_threads.remove(nw)
server.busy_threads.append(nw)
if nw.connected:
self.__request_article(nw)
else:
try:
logging.info("%s@%s: Initiating connection", nw.thrdnum, server.host)
nw.init_connect()
except:
logging.error(
T("Failed to initialize %s@%s with reason: %s"),
nw.thrdnum,
server.host,
sys.exc_info()[1],
)
self.__reset_nw(nw, "failed to initialize", warn=True)
if self.force_disconnect or self.shutdown:
for server in self.servers:
for nw in server.idle_threads + server.busy_threads:
# Send goodbye if we have open socket
if nw.nntp:
self.__reset_nw(
nw, "forcing disconnect", wait=False, count_article_try=False, send_quit=True
)
# Make sure server address resolution is refreshed
server.info = None
server.reset_article_queue()
self.force_disconnect = False
# Make sure we update the stats
BPSMeter.update()
# Exit-point
if self.shutdown:
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 self.last_max_chunk_size > self.max_chunk_size:
self.max_chunk_size = self.last_max_chunk_size
elif self.last_max_chunk_size < self.max_chunk_size / 3:
time.sleep(self.sleep_time)
now = time.time()
self.last_max_chunk_size = 0
# Use select to find sockets ready for reading/writing
if readkeys := self.read_fds.keys():
read, _, _ = select.select(readkeys, (), (), 1.0)
else:
read = []
BPSMeter.reset()
time.sleep(1.0)
self.max_chunk_size = _DEFAULT_CHUNK_SIZE
with DOWNLOADER_CV:
while (
(sabnzbd.NzbQueue.is_empty() or self.no_active_jobs() or self.paused_for_postproc)
and not self.shutdown
and not self.force_disconnect
and not self.server_restarts
):
DOWNLOADER_CV.wait()
if now > next_bpsmeter_update:
BPSMeter.update()
next_bpsmeter_update = now + _BPSMETER_UPDATE_DELAY
if not read:
continue
for nw in server.idle_threads[:]:
if nw.timeout:
if now < nw.timeout:
continue
else:
nw.timeout = None
if self.recv_threads > 1:
# Submit a process_nw task to the pool for every NewWrapper which is readable
for selected in read:
self.process_tasks.add(self.recv_pool.submit(self.process_nw, self.read_fds[selected]))
if not server.info:
# Only request info if there's stuff in the queue
if not sabnzbd.NzbQueue.is_empty():
self.maybe_block_server(server)
server.request_info()
break
# Wait for all the tasks to complete
concurrent.futures.wait(self.process_tasks)
nw.article = server.get_article()
if not nw.article:
break
# Clear task list
self.process_tasks.clear()
else:
for selected in read:
self.process_nw(self.read_fds[selected])
server.idle_threads.remove(nw)
server.busy_threads.append(nw)
# Check the Assembler queue to see if we need to delay, depending on queue size
if (assembler_level := sabnzbd.Assembler.queue_level()) > SOFT_QUEUE_LIMIT:
time.sleep(min((assembler_level - SOFT_QUEUE_LIMIT) / 4, 0.15))
sabnzbd.BPSMeter.delayed_assembler += 1
logged_counter = 0
if nw.connected:
self.__request_article(nw)
else:
try:
logging.info("%s@%s: Initiating connection", nw.thrdnum, server.host)
nw.init_connect()
except:
logging.error(
T("Failed to initialize %s@%s with reason: %s"),
nw.thrdnum,
server.host,
sys.exc_info()[1],
)
self.__reset_nw(nw, "failed to initialize", warn=True)
while not self.shutdown and 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()
if self.force_disconnect or self.shutdown:
for server in self.servers:
for nw in server.idle_threads + server.busy_threads:
# Send goodbye if we have open socket
if nw.nntp:
self.__reset_nw(
nw, "forcing disconnect", wait=False, count_article_try=False, send_quit=True
)
# Make sure server address resolution is refreshed
server.info = None
server.reset_article_queue()
self.force_disconnect = False
# Make sure we update the stats
BPSMeter.update()
# Exit-point
if self.shutdown:
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 self.last_max_chunk_size > self.max_chunk_size:
logging.debug("New max_chunk_size %d -> %d", self.max_chunk_size, self.last_max_chunk_size)
self.max_chunk_size = self.last_max_chunk_size
elif self.last_max_chunk_size < self.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:
# Update who is delaying us
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,
"Delayed - %d seconds - Assembler queue: %d",
logged_counter / 10,
sabnzbd.Assembler.queue.qsize(),
)
sleep_count_start = now
sleep_count = 0
time_slept = 0
self.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)
else:
read = []
BPSMeter.reset()
time.sleep(1.0)
self.max_chunk_size = _DEFAULT_CHUNK_SIZE
with DOWNLOADER_CV:
while (
(sabnzbd.NzbQueue.is_empty() or self.no_active_jobs() or self.paused_for_postproc)
and not self.shutdown
and not self.force_disconnect
and not self.server_restarts
):
DOWNLOADER_CV.wait()
if now > next_bpsmeter_update:
BPSMeter.update()
next_bpsmeter_update = now + _BPSMETER_UPDATE_DELAY
if not read:
continue
if self.recv_threads > 1:
# Submit a process_nw task to the pool for every NewWrapper which is readable
for selected in read:
self.process_tasks.add(self.recv_pool.submit(self.process_nw, self.read_fds[selected]))
# Wait for all the tasks to complete
concurrent.futures.wait(self.process_tasks)
# Clear task list
self.process_tasks.clear()
else:
for selected in read:
self.process_nw(self.read_fds[selected])
# Check the Assembler queue to see if we need to delay, depending on queue size
if (assembler_level := sabnzbd.Assembler.queue_level()) > SOFT_QUEUE_LIMIT:
time.sleep(min((assembler_level - SOFT_QUEUE_LIMIT) / 4, 0.15))
sabnzbd.BPSMeter.delayed_assembler += 1
logged_counter = 0
while not self.shutdown and 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 - Assembler queue: %d",
logged_counter / 10,
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
except:
logging.error(T("Fatal error in Downloader"), exc_info=True)
def process_nw(self, nw: NewsWrapper):
"""Receive data from NewsWrapper and handle response"""
@@ -871,7 +848,12 @@ class Downloader(Thread):
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):
if (
nw.connected
and server.active
and not server.restart
and not (self.paused or self.shutdown or self.paused_for_postproc)
):
nw.article = server.get_article()
if nw.article:
self.__request_article(nw)

View File

@@ -31,6 +31,7 @@ import time
import fnmatch
import stat
import ctypes
import random
from typing import Union, List, Tuple, Any, Dict, Optional, BinaryIO
try:
@@ -1272,15 +1273,37 @@ def directory_is_writable_with_file(mydir, myfilename):
def directory_is_writable(test_dir: str) -> bool:
"""Checks if dir is writable at all, and (on non-Windows), writable with special chars.
"""Checks if dir is writable at all, with long filenames, with unicode,
and (on non-Windows), writable with special chars.
Returns True if all OK, otherwise False"""
if directory_is_writable_with_file(test_dir, "sab_test.txt"):
if not sabnzbd.WIN32 and not directory_is_writable_with_file(test_dir, "sab_test \\ bla :: , bla.txt"):
sabnzbd.misc.helpful_warning(
T("%s is not writable with special character filenames. This can cause problems."), test_dir
)
return False
else:
if not directory_is_writable_with_file(test_dir, "sab_test.txt"):
sabnzbd.misc.helpful_warning(T("%s is not writable at all. This blocks downloads."), test_dir)
return False
return True
def check_filesystem_capabilities(test_dir: str) -> bool:
"""Checks if we can write long and unicode filenames to the given directory.
If not on Windows, also check for special chars like \ and :
Returns True if all OK, otherwise False"""
allgood = True # default return value: all OK
# long filename; normal filesystems accept 255 byte filenames
if not directory_is_writable_with_file(test_dir, "A" * 245 + str(random.randrange(10000, 99999))):
sabnzbd.misc.helpful_warning(T("Cannot write a long filename to %s. This can cause problems."), test_dir)
allgood = False
# unicode in filename
if not directory_is_writable_with_file(test_dir, "🚀" * 20):
sabnzbd.misc.helpful_warning(T("Cannot write a unicode filename to %s. This can cause problems."), test_dir)
allgood = False
# if not on Windows, check special chars like \ and :
if not sabnzbd.WIN32 and not directory_is_writable_with_file(test_dir, "sab_test \\ bla :: , bla.txt"):
sabnzbd.misc.helpful_warning(
T("%s is not writable with special character filenames. This can cause problems."), test_dir
)
allgood = False
return allgood

View File

@@ -78,6 +78,8 @@ from sabnzbd.constants import (
DEF_HTTPS_CERT_FILE,
DEF_SORTER_RENAME_SIZE,
GUESSIT_SORT_TYPES,
VALID_NZB_FILES,
VALID_ARCHIVES,
)
from sabnzbd.lang import list_languages
from sabnzbd.api import (
@@ -725,6 +727,8 @@ class ConfigFolders:
def index(self, **kwargs):
conf = build_header(sabnzbd.WEB_DIR_CONFIG)
conf["file_exts"] = ", ".join(VALID_NZB_FILES + VALID_ARCHIVES)
for kw in LIST_DIRPAGE + LIST_BOOL_DIRPAGE:
conf[kw] = config.get_config("misc", kw)()

View File

@@ -50,7 +50,7 @@ from sabnzbd.constants import (
)
import sabnzbd.config as config
import sabnzbd.cfg as cfg
from sabnzbd.encoding import ubtou, platform_btou
from sabnzbd.encoding import ubtou
from sabnzbd.filesystem import userxbit, make_script_path, remove_file, is_valid_script
if sabnzbd.WIN32:
@@ -1110,7 +1110,7 @@ def list2cmdline_unrar(lst: List[str]) -> str:
return " ".join(nlst)
def build_and_run_command(command: List[str], windows_unrar_command: bool = False, **kwargs):
def build_and_run_command(command: List[str], windows_unrar_command: bool = False, text_mode: bool = True, **kwargs):
"""Builds and then runs command with necessary flags and optional
IONice and Nice commands. Optional Popen arguments can be supplied.
On Windows we need to run our own list2cmdline for Unrar.
@@ -1156,12 +1156,18 @@ def build_and_run_command(command: List[str], windows_unrar_command: bool = Fals
# Set the basic Popen arguments
popen_kwargs = {
"stdin": subprocess.PIPE,
"stdout": subprocess.PIPE,
"stderr": subprocess.STDOUT,
"bufsize": 0,
"startupinfo": startupinfo,
"creationflags": creationflags,
}
# In text mode we ignore errors
if text_mode:
# We default to utf8, and hope for the best
popen_kwargs.update({"text": True, "encoding": "utf8", "errors": "replace"})
# Update with the supplied ones
popen_kwargs.update(kwargs)
@@ -1174,7 +1180,7 @@ def build_and_run_command(command: List[str], windows_unrar_command: bool = Fals
def run_command(cmd: List[str], **kwargs):
"""Run simple external command and return output as a string."""
with build_and_run_command(cmd, **kwargs) as p:
txt = platform_btou(p.stdout.read())
txt = p.stdout.read()
p.wait()
return txt

View File

@@ -25,14 +25,13 @@ import re
import subprocess
import logging
import time
import zlib
import io
import shutil
import functools
from typing import Tuple, List, BinaryIO, Optional, Dict, Any, Union
import sabnzbd
from sabnzbd.encoding import platform_btou, correct_unknown_encoding, ubtou
from sabnzbd.encoding import correct_unknown_encoding, ubtou
import sabnzbd.utils.rarfile as rarfile
from sabnzbd.misc import (
format_time_string,
@@ -221,18 +220,18 @@ def external_processing(
"orig_nzb_gz": clip_path(nzb_paths[0]) if nzb_paths else "",
}
# Make sure that if we run a Python script it's output is unbuffered, so we can show it to the user
if extern_proc.endswith(".py"):
extra_env_fields["pythonunbuffered"] = True
try:
p = build_and_run_command(command, env=create_env(nzo, extra_env_fields))
sabnzbd.PostProcessor.external_process = p
# Follow the output, so we can abort it
proc = p.stdout
if p.stdin:
p.stdin.close()
lines = []
while 1:
line = platform_btou(proc.readline())
line = p.stdout.readline()
if not line:
break
line = line.strip()
@@ -691,7 +690,6 @@ def rar_extract_core(
elif RAR_PROBLEM:
# Use only oldest options, specifically no "-or" or "-scf"
# Luckily platform_btou has a fallback for non-UTF-8
command = [
RAR_COMMAND,
action,
@@ -724,10 +722,6 @@ def rar_extract_core(
p = build_and_run_command(command, windows_unrar_command=True)
sabnzbd.PostProcessor.external_process = p
proc = p.stdout
if p.stdin:
p.stdin.close()
nzo.set_action_line(T("Unpacking"), "00/%02d" % numrars)
# Loop over the output from rar!
@@ -739,7 +733,7 @@ def rar_extract_core(
lines = []
while 1:
line = platform_btou(proc.readline())
line = p.stdout.readline()
if not line:
break
@@ -788,7 +782,7 @@ def rar_extract_core(
fail = 1
elif line.startswith("Cannot create"):
line2 = platform_btou(proc.readline())
line2 = p.stdout.readline()
if "must not exceed 260" in line2:
msg = "%s: %s" % (T("Unpacking failed, path is too long"), line[13:])
else:
@@ -844,14 +838,14 @@ def rar_extract_core(
extracted.append(real_path(extraction_path, unpacked_file))
if fail:
if proc:
proc.close()
if p.stdout:
p.stdout.close()
p.wait()
logging.debug("UNRAR output %s", "\n".join(lines))
return fail, [], []
if proc:
proc.close()
if p.stdout:
p.stdout.close()
p.wait()
# Which files did we use to extract this?
@@ -937,10 +931,8 @@ def unzip_core(zipfile, extraction_path, one_folder):
command.insert(3, "-j") # Unpack without folders
p = build_and_run_command(command)
output = platform_btou(p.stdout.read())
ret = p.wait()
logging.debug("unzip output: \n%s", output)
return ret
logging.debug("unzip output: \n%s", p.stdout.read())
return p.wait()
##############################################################################
@@ -1055,7 +1047,7 @@ def seven_extract_core(
command = [SEVENZIP_COMMAND, method, "-y", overwrite, case, password, "-o%s" % extraction_path, seven_path]
p = build_and_run_command(command)
sabnzbd.PostProcessor.external_process = p
output = platform_btou(p.stdout.read())
output = p.stdout.read()
logging.debug("7za output: %s", output)
# ret contains the 7z/7za exit code: 0 = Normal, 1 = Warning, 2 = Fatal error, etc
@@ -1258,10 +1250,6 @@ def par2cmdline_verify(
# Run the external command
p = build_and_run_command(command)
sabnzbd.PostProcessor.external_process = p
proc = p.stdout
if p.stdin:
p.stdin.close()
# Set up our variables
lines = []
@@ -1283,7 +1271,7 @@ def par2cmdline_verify(
# Loop over the output, whee
while 1:
char = platform_btou(proc.read(1))
char = p.stdout.read(1)
if not char:
break
@@ -1552,16 +1540,13 @@ def multipar_verify(
# Run MultiPar
p = build_and_run_command(command)
sabnzbd.PostProcessor.external_process = p
proc = p.stdout
if p.stdin:
p.stdin.close()
# Set up our variables
lines = []
renames = {}
reconstructed = []
linebuf = b""
linebuf = ""
finished = False
readd = False
@@ -1578,17 +1563,17 @@ def multipar_verify(
# Loop over the output, whee
while 1:
char = proc.read(1)
char = p.stdout.read(1)
if not char:
break
# Line not complete yet
if char not in (b"\n", b"\r"):
if char not in ("\n", "\r"):
linebuf += char
continue
line = ubtou(linebuf).strip()
linebuf = b""
line = linebuf.strip()
linebuf = ""
# Skip empty lines
if line == "":
@@ -1923,9 +1908,6 @@ def create_env(nzo: Optional[NzbObject] = None, extra_env_fields: Dict[str, Any]
del env["PYTHONPATH"]
if "PYTHONHOME" in env:
del env["PYTHONHOME"]
elif not nzo:
# No modification
return None
return env
@@ -2334,7 +2316,7 @@ def pre_queue(nzo: NzbObject, pp, cat):
logging.debug("Failed script %s, Traceback: ", script_path, exc_info=True)
return values
output = platform_btou(p.stdout.read())
output = p.stdout.read()
ret = p.wait()
logging.info("Pre-queue script returned %s and output=\n%s", ret, output)
if ret == 0:
@@ -2402,7 +2384,7 @@ class SevenZip:
"""Read named file from 7Zip and return data"""
command = [SEVENZIP_COMMAND, "e", "-p", "-y", "-so", self.path, name]
# Ignore diagnostic output, otherwise it will be appended to content
with build_and_run_command(command, stderr=subprocess.DEVNULL) as p:
with build_and_run_command(command, text_mode=False, stderr=subprocess.DEVNULL) as p:
data = io.BytesIO(p.stdout.read())
p.wait()
return data

View File

@@ -31,7 +31,7 @@ from threading import Thread
import sabnzbd
import sabnzbd.cfg
from sabnzbd.encoding import platform_btou, utob
from sabnzbd.encoding import utob
from sabnzbd.filesystem import make_script_path
from sabnzbd.misc import build_and_run_command
from sabnzbd.newsunpack import create_env
@@ -350,11 +350,11 @@ def send_nscript(title, msg, gtype, force=False, test=None):
"""Run user's notification script"""
if test:
script = test.get("nscript_script")
nscript_parameters = test.get("nscript_parameters")
env_params = {"notification_parameters": test.get("nscript_parameters")}
else:
script = sabnzbd.cfg.nscript_script()
nscript_parameters = sabnzbd.cfg.nscript_parameters()
nscript_parameters = nscript_parameters.split()
env_params = {"notification_parameters": sabnzbd.cfg.nscript_parameters()}
if not script:
return T("Cannot send, missing required data")
title = "SABnzbd: " + T(NOTIFICATION.get(gtype, "other"))
@@ -365,17 +365,18 @@ def send_nscript(title, msg, gtype, force=False, test=None):
ret = -1
output = None
try:
p = build_and_run_command([script_path, gtype, title, msg] + nscript_parameters, env=create_env())
output = platform_btou(p.stdout.read())
p = build_and_run_command([script_path, gtype, title, msg], env=create_env(extra_env_fields=env_params))
output = p.stdout.read()
ret = p.wait()
except:
logging.info("Failed script %s, Traceback: ", script, exc_info=True)
logging.info("Failed to run script %s", script, exc_info=True)
if ret:
logging.error(T('Script returned exit code %s and output "%s"'), ret, output)
return T('Script returned exit code %s and output "%s"') % (ret, output)
else:
logging.info("Successfully executed notification script %s", script_path)
logging.debug("Script output: %s", output)
else:
return T('Notification script "%s" does not exist') % script_path
return ""

View File

@@ -28,6 +28,7 @@ import xml.etree.ElementTree
import datetime
import zipfile
import tempfile
import cherrypy._cpreqbody
from typing import Optional, Dict, Any, Union, List, Tuple
@@ -43,7 +44,7 @@ from sabnzbd.filesystem import (
remove_data,
)
from sabnzbd.misc import name_to_cat
from sabnzbd.constants import DEFAULT_PRIORITY, VALID_ARCHIVES
from sabnzbd.constants import DEFAULT_PRIORITY, VALID_ARCHIVES, AddNzbFileResult
from sabnzbd.utils import rarfile
@@ -158,11 +159,9 @@ def process_nzb_archive_file(
url: Optional[str] = None,
password: Optional[str] = None,
nzo_id: Optional[str] = None,
) -> Tuple[int, List[str]]:
) -> Tuple[AddNzbFileResult, List[str]]:
"""Analyse archive and create job(s).
Accepts archive files with ONLY nzb/nfo/folder files in it.
returns (status, nzo_ids)
status: -2==Error/retry, -1==Error, 0==OK, 1==No files found
"""
nzo_ids = []
if catdir is None:
@@ -178,21 +177,21 @@ def process_nzb_archive_file(
zf = sabnzbd.newsunpack.SevenZip(path)
else:
logging.info("File %s is not a supported archive!", filename)
return -1, []
return AddNzbFileResult.ERROR, []
except:
logging.info(T("Cannot read %s"), path, exc_info=True)
return -2, []
return AddNzbFileResult.RETRY, []
status = 1
status: AddNzbFileResult = AddNzbFileResult.NO_FILES_FOUND
names = zf.namelist()
nzbcount = 0
for name in names:
name = name.lower()
if name.endswith(".nzb"):
status = 0
status = AddNzbFileResult.OK
nzbcount += 1
if status == 0:
if status == AddNzbFileResult.OK:
if nzbcount != 1:
nzbname = None
for name in names:
@@ -202,7 +201,7 @@ def process_nzb_archive_file(
except OSError:
logging.error(T("Cannot read %s"), name, exc_info=True)
zf.close()
return -1, []
return AddNzbFileResult.ERROR, []
name = get_filename(name)
if datap:
nzo = None
@@ -254,7 +253,7 @@ def process_nzb_archive_file(
# If all were rejected/empty/etc, update status
if not nzo_ids:
status = 1
status = AddNzbFileResult.NO_FILES_FOUND
return status, nzo_ids
@@ -275,11 +274,9 @@ def process_single_nzb(
url: Optional[str] = None,
password: Optional[str] = None,
nzo_id: Optional[str] = None,
) -> Tuple[int, List[str]]:
) -> Tuple[AddNzbFileResult, List[str]]:
"""Analyze file and create a job from it
Supports NZB, NZB.BZ2, NZB.GZ and GZ.NZB-in-disguise
returns (status, nzo_ids)
status: -2==Error/retry, -1==Error, 0==OK
"""
if catdir is None:
catdir = cat
@@ -302,7 +299,7 @@ def process_single_nzb(
except OSError:
logging.warning(T("Cannot read %s"), clip_path(path))
logging.info("Traceback: ", exc_info=True)
return -2, []
return AddNzbFileResult.RETRY, []
if filename:
filename, cat = name_to_cat(filename, catdir)
@@ -312,7 +309,7 @@ def process_single_nzb(
nzbname = get_filename(filename)
# Parse the data
result = 0
result: AddNzbFileResult = AddNzbFileResult.OK
nzo = None
nzo_ids = []
try:
@@ -332,17 +329,19 @@ def process_single_nzb(
)
if not nzo.password:
nzo.password = password
except (sabnzbd.nzbstuff.NzbEmpty, sabnzbd.nzbstuff.NzbRejected):
# Empty or fully rejected
result = -1
pass
except sabnzbd.nzbstuff.NzbEmpty:
# Malformed or might not be an NZB file
result = AddNzbFileResult.NO_FILES_FOUND
except sabnzbd.nzbstuff.NzbRejected:
# Rejected as duplicate or by pre-queue script
result = AddNzbFileResult.ERROR
except sabnzbd.nzbstuff.NzbRejectedToHistory as err:
# Duplicate or unwanted extension that was failed to history
nzo_ids.append(err.nzo_id)
except:
# Something else is wrong, show error
logging.error(T("Error while adding %s, removing"), filename, exc_info=True)
result = -1
result = AddNzbFileResult.ERROR
finally:
nzb_fp.close()
@@ -350,7 +349,7 @@ def process_single_nzb(
nzo_ids.append(sabnzbd.NzbQueue.add(nzo, quiet=bool(reuse)))
try:
if not keep:
if not keep and result in {AddNzbFileResult.ERROR, AddNzbFileResult.OK}:
remove_file(path)
except OSError:
# Job was still added to the queue, so throw error but don't report failed add

View File

@@ -53,6 +53,10 @@ class SABnzbdDelegate(NSObject):
history_db = None
def awakeFromNib(self):
# Wait for SABnzbd to be ready, otherwise tray_icon might not be read from config yet
while not sabnzbd.WEBUI_READY and not sabnzbd.SABSTOP:
time.sleep(0.5)
# Do we want the menu
if sabnzbd.cfg.tray_icon():
# Status Bar initialize
@@ -84,10 +88,6 @@ class SABnzbdDelegate(NSObject):
self.status_item.setToolTip_("SABnzbd")
self.status_item.setEnabled_(YES)
# Wait for translated texts to be loaded
while not sabnzbd.WEBUI_READY and not sabnzbd.SABSTOP:
time.sleep(0.5)
# Variables
self.state = "Idle"
self.speed = 0

View File

@@ -64,6 +64,7 @@ from sabnzbd.filesystem import (
get_ext,
get_filename,
directory_is_writable,
check_filesystem_capabilities,
)
from sabnzbd.nzbstuff import NzbObject
from sabnzbd.sorting import Sorter
@@ -231,8 +232,10 @@ class PostProcessor(Thread):
else:
logging.debug("Completed Download Folder %s is not on FAT", complete_dir)
directory_is_writable(sabnzbd.cfg.download_dir.get_path())
directory_is_writable(sabnzbd.cfg.complete_dir.get_path())
if directory_is_writable(sabnzbd.cfg.download_dir.get_path()):
check_filesystem_capabilities(sabnzbd.cfg.download_dir.get_path())
if directory_is_writable(sabnzbd.cfg.complete_dir.get_path()):
check_filesystem_capabilities(sabnzbd.cfg.complete_dir.get_path())
# Do an extra purge of the history on startup to ensure timely removal on systems that
# aren't on 24/7 and typically don't benefit from the daily scheduled call at midnight
@@ -481,7 +484,6 @@ def process_job(nzo: NzbObject):
# Full cleanup including nzb's
cleanup_list(tmp_workdir_complete, skip_nzb=False)
script_output = ""
script_ret = 0
script_error = False
if not nzb_list:
@@ -542,18 +544,23 @@ def process_job(nzo: NzbObject):
script_log, script_ret = external_processing(
script_path, nzo, clip_path(workdir_complete), nzo.final_name, job_result
)
if script_log:
script_output = nzo.nzo_id
if script_line := get_last_line(script_log):
nzo.set_unpack_info("Script", script_line, unique=True)
else:
nzo.set_unpack_info("Script", T("Ran %s") % script, unique=True)
# Format output depending on return status
script_line = get_last_line(script_log)
if script_ret:
if script_line:
script_line = "Exit(%s): %s " % (script_ret, script_line)
else:
script_line = T("Script exit code is %s") % script_ret
elif not script_line:
script_line = T("Ran %s") % script
nzo.set_unpack_info("Script", script_line, unique=True)
# Maybe bad script result should fail job
if script_ret and cfg.script_can_fail():
script_error = True
all_ok = False
nzo.fail_msg = T("Script exit code is %s") % script_ret
nzo.fail_msg = script_line
# Email the results
if not nzb_list and cfg.email_endjob():
@@ -571,21 +578,13 @@ def process_job(nzo: NzbObject):
script_ret,
)
if script_output:
if script_log and len(script_log.rstrip().split("\n")) > 1:
# Can do this only now, otherwise it would show up in the email
if script_ret:
script_ret = "Exit(%s) " % script_ret
else:
script_ret = ""
if len(script_log.rstrip().split("\n")) > 1:
nzo.set_unpack_info(
"Script",
'%s%s <a href="./scriptlog?name=%s">(%s)</a>' % (script_ret, script_line, script_output, T("More")),
unique=True,
)
else:
# No '(more)' button needed
nzo.set_unpack_info("Script", "%s%s " % (script_ret, script_line), unique=True)
nzo.set_unpack_info(
"Script",
'%s <a href="./scriptlog?name=%s">(%s)</a>' % (script_line, nzo.nzo_id, T("More")),
unique=True,
)
# Cleanup again, including NZB files
if all_ok and os.path.isdir(workdir_complete):

View File

@@ -375,9 +375,7 @@ SKIN_TEXT = {
'Set permissions pattern for completed files/folders.<br /><i>In octal notation. For example: "755" or "777"</i>'
),
"opt-dirscan_dir": TT("Watched Folder"),
"explain-dirscan_dir": TT(
"Folder to monitor for .nzb files.<br /><i>Also scans .zip .rar and .tar.gz archives for .nzb files.</i>"
),
"explain-dirscan_dir": TT("Folder to monitor for .nzb files."),
"opt-dirscan_speed": TT("Watched Folder Scan Speed"),
"explain-dirscan_speed": TT("Number of seconds between scans for .nzb files."),
"opt-script_dir": TT("Scripts Folder"),

View File

@@ -40,6 +40,7 @@ import sabnzbd.cfg as cfg
import sabnzbd.emailer as emailer
import sabnzbd.notifier as notifier
from sabnzbd.encoding import ubtou, utob
from sabnzbd.nzbparser import AddNzbFileResult
from sabnzbd.nzbstuff import NzbObject
@@ -255,14 +256,13 @@ class URLGrabber(Thread):
password=future_nzo.password,
nzo_id=future_nzo.nzo_id,
)
# -2==Error/retry, -1==Error, 0==OK, 1==Empty
if res == -2:
if res is AddNzbFileResult.RETRY:
logging.info("Incomplete NZB, retry after 5 min %s", url)
self.add(url, future_nzo, when=300)
elif res == -1:
elif res is AddNzbFileResult.ERROR:
# Error already thrown
self.fail_to_history(future_nzo, url)
elif res == 1:
elif res is AddNzbFileResult.NO_FILES_FOUND:
# No NZB-files inside archive
self.fail_to_history(future_nzo, url, T("Empty NZB file %s") % filename)
else:

View File

@@ -1132,7 +1132,9 @@ class CommonParser(object):
# now read actual header
return self._parse_block_header(fd)
except struct.error:
except:
# SABnzbd-edit:
# Catch all errors
self._set_error("Broken header in RAR file")
return None

View File

@@ -5,5 +5,5 @@
# You MUST use double quotes (so " and not ')
__version__ = "4.0.1"
__baseline__ = "916c191b18195bb0a38e9d638909d9afbc21983d"
__version__ = "4.0.2"
__baseline__ = "47f2df21123b26d4feb9d200aae39b216f02bf4e"

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