mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2026-01-10 08:30:45 -05:00
Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3a6f04496d | ||
|
|
47f2df2112 | ||
|
|
363a26b8a1 | ||
|
|
7e50a00f55 | ||
|
|
a7d6a80e82 | ||
|
|
e7da95b2ac | ||
|
|
422b4fce7b | ||
|
|
e3a7226648 | ||
|
|
5b9fc86319 | ||
|
|
5afea2d3c7 | ||
|
|
5f942a6943 | ||
|
|
18075c5c51 | ||
|
|
a728225782 | ||
|
|
74fca23d59 | ||
|
|
0a12fa1253 | ||
|
|
3e6ae26710 | ||
|
|
a8a4e442a8 | ||
|
|
c16e91734d | ||
|
|
bb9ad4b546 | ||
|
|
43045e5d4e | ||
|
|
63c7dbdb4d | ||
|
|
ef217bba90 | ||
|
|
ca9924c38f | ||
|
|
c3c47507e7 | ||
|
|
dc237c752a | ||
|
|
08892c71b2 | ||
|
|
026717b7c2 | ||
|
|
be06290f6c | ||
|
|
9ec55478c9 | ||
|
|
4172b4a2a6 | ||
|
|
59620c2217 | ||
|
|
c410c646b2 | ||
|
|
0b515996d7 | ||
|
|
8b9b8319a1 | ||
|
|
161cf14519 | ||
|
|
c6ac09e938 | ||
|
|
fde8f9d133 | ||
|
|
2bd222ca1c | ||
|
|
12228fe1fb | ||
|
|
c63b2592f1 | ||
|
|
e65980258c | ||
|
|
bd0a90d2dd | ||
|
|
33a7e92f4c | ||
|
|
51d1a1994d | ||
|
|
835745e485 | ||
|
|
bcb553d9f9 | ||
|
|
b73b8aae6a | ||
|
|
51792e31a8 | ||
|
|
636a391db3 | ||
|
|
57d5ed2f21 | ||
|
|
bbb1d1d908 | ||
|
|
c5d8f52f03 | ||
|
|
1b49e4a355 | ||
|
|
878cb589c3 | ||
|
|
53ce88d3d2 | ||
|
|
85e9bea9e7 | ||
|
|
7c7f88ebb5 | ||
|
|
cbd007b81a | ||
|
|
ac0438de42 |
1
.github/renovate.json
vendored
1
.github/renovate.json
vendored
@@ -15,6 +15,7 @@
|
||||
"fileMatch": [
|
||||
"requirements.txt",
|
||||
"builder/requirements.txt",
|
||||
"builder/release-requirements.txt",
|
||||
"builder/osx/requirements.txt"
|
||||
]
|
||||
},
|
||||
|
||||
54
.github/workflows/build_release.yml
vendored
54
.github/workflows/build_release.yml
vendored
@@ -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
|
||||
|
||||
18
.github/workflows/integration_testing.yml
vendored
18
.github/workflows/integration_testing.yml
vendored
@@ -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: |
|
||||
|
||||
8
.github/workflows/translations.yml
vendored
8
.github/workflows/translations.yml
vendored
@@ -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
|
||||
|
||||
10
PKG-INFO
10
PKG-INFO
@@ -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
|
||||
26
README.mkd
26
README.mkd
@@ -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
46
README.txt
Normal 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\>
|
||||
@@ -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"
|
||||
|
||||
@@ -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
62
builder/constants.py
Normal 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/",
|
||||
]
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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"])
|
||||
|
||||
2
builder/release-requirements.txt
Normal file
2
builder/release-requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
PyGithub==1.58.2
|
||||
praw==7.7.0
|
||||
247
builder/release.py
Normal file
247
builder/release.py
Normal 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.")
|
||||
@@ -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'
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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#-->
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"'#-->>
|
||||
|
||||
@@ -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> »
|
||||
$active_feed
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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!)"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)()
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 ""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"),
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user