mirror of
https://github.com/clinton-hall/nzbToMedia.git
synced 2025-08-22 06:13:19 -07:00
Merge branch 'nightly' into bluray-1
This commit is contained in:
commit
b02d6ef419
71 changed files with 957 additions and 311 deletions
|
@ -1,16 +1,22 @@
|
|||
#!/usr/bin/env python
|
||||
# coding=utf-8
|
||||
|
||||
import eol
|
||||
eol.check()
|
||||
|
||||
import cleanup
|
||||
cleanup.clean(cleanup.FOLDER_STRUCTURE)
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
import eol
|
||||
import cleanup
|
||||
eol.check()
|
||||
cleanup.clean(cleanup.FOLDER_STRUCTURE)
|
||||
|
||||
import core
|
||||
from core import logger, main_db
|
||||
from core.auto_process import comics, games, movies, music, tv, books
|
||||
|
@ -18,7 +24,11 @@ from core.auto_process.common import ProcessResult
|
|||
from core.plugins.plex import plex_update
|
||||
from core.user_scripts import external_script
|
||||
from core.utils import char_replace, convert_to_ascii, replace_links
|
||||
from six import text_type
|
||||
|
||||
try:
|
||||
text_type = unicode
|
||||
except NameError:
|
||||
text_type = str
|
||||
|
||||
|
||||
def process_torrent(input_directory, input_name, input_category, input_hash, input_id, client_agent):
|
||||
|
@ -60,13 +70,13 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
|
|||
input_category = 'UNCAT'
|
||||
|
||||
usercat = input_category
|
||||
#try:
|
||||
# try:
|
||||
# input_name = input_name.encode(core.SYS_ENCODING)
|
||||
#except UnicodeError:
|
||||
# except UnicodeError:
|
||||
# pass
|
||||
#try:
|
||||
# try:
|
||||
# input_directory = input_directory.encode(core.SYS_ENCODING)
|
||||
#except UnicodeError:
|
||||
# except UnicodeError:
|
||||
# pass
|
||||
|
||||
logger.debug('Determined Directory: {0} | Name: {1} | Category: {2}'.format
|
||||
|
@ -125,9 +135,9 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
|
|||
else:
|
||||
output_destination = os.path.normpath(
|
||||
core.os.path.join(core.OUTPUT_DIRECTORY, input_category))
|
||||
#try:
|
||||
# try:
|
||||
# output_destination = output_destination.encode(core.SYS_ENCODING)
|
||||
#except UnicodeError:
|
||||
# except UnicodeError:
|
||||
# pass
|
||||
|
||||
if output_destination in input_directory:
|
||||
|
@ -170,9 +180,9 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
|
|||
core.os.path.join(output_destination, os.path.basename(file_path)), full_file_name)
|
||||
logger.debug('Setting outputDestination to {0} to preserve folder structure'.format
|
||||
(os.path.dirname(target_file)))
|
||||
#try:
|
||||
# try:
|
||||
# target_file = target_file.encode(core.SYS_ENCODING)
|
||||
#except UnicodeError:
|
||||
# except UnicodeError:
|
||||
# pass
|
||||
if root == 1:
|
||||
if not found_file:
|
||||
|
@ -259,7 +269,6 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
|
|||
elif section_name == 'LazyLibrarian':
|
||||
result = books.process(section_name, output_destination, input_name, status, client_agent, input_category)
|
||||
|
||||
|
||||
plex_update(input_category)
|
||||
|
||||
if result.status_code != 0:
|
||||
|
@ -279,7 +288,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
|
|||
# remove torrent
|
||||
if core.USE_LINK == 'move-sym' and not core.DELETE_ORIGINAL == 1:
|
||||
logger.debug('Checking for sym-links to re-direct in: {0}'.format(input_directory))
|
||||
for dirpath, dirs, files in os.walk(input_directory):
|
||||
for dirpath, _, files in os.walk(input_directory):
|
||||
for file in files:
|
||||
logger.debug('Checking symlink: {0}'.format(os.path.join(dirpath, file)))
|
||||
replace_links(os.path.join(dirpath, file))
|
||||
|
@ -353,14 +362,14 @@ def main(args):
|
|||
if client_agent.lower() not in core.TORRENT_CLIENTS:
|
||||
continue
|
||||
|
||||
#try:
|
||||
# try:
|
||||
# dir_name = dir_name.encode(core.SYS_ENCODING)
|
||||
#except UnicodeError:
|
||||
# except UnicodeError:
|
||||
# pass
|
||||
input_name = os.path.basename(dir_name)
|
||||
#try:
|
||||
# try:
|
||||
# input_name = input_name.encode(core.SYS_ENCODING)
|
||||
#except UnicodeError:
|
||||
# except UnicodeError:
|
||||
# pass
|
||||
|
||||
results = process_torrent(dir_name, input_name, subsection, input_hash or None, input_id or None,
|
||||
|
|
10
cleanup.py
10
cleanup.py
|
@ -1,6 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
@ -25,6 +30,7 @@ FOLDER_STRUCTURE = {
|
|||
|
||||
class WorkingDirectory(object):
|
||||
"""Context manager for changing current working directory."""
|
||||
|
||||
def __init__(self, new, original=None):
|
||||
self.working_directory = new
|
||||
self.original_directory = os.getcwd() if original is None else original
|
||||
|
@ -43,7 +49,7 @@ class WorkingDirectory(object):
|
|||
original_directory=self.original_directory,
|
||||
error=error,
|
||||
working_directory=self.working_directory,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import itertools
|
||||
import locale
|
||||
|
@ -108,9 +113,9 @@ FORKS = {
|
|||
FORK_SICKCHILL: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'force_next': None},
|
||||
FORK_SICKBEARD_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete': None, 'force_next': None},
|
||||
FORK_MEDUSA: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'ignore_subs': None},
|
||||
FORK_MEDUSA_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete_files': None, 'is_priority': None},
|
||||
FORK_MEDUSA_API: {'path': None, 'failed': None, 'process_method': None, 'force_replace': None, 'return_data': None, 'type': None, 'delete_files': None, 'is_priority': None},
|
||||
FORK_SICKGEAR: {'dir': None, 'failed': None, 'process_method': None, 'force': None},
|
||||
FORK_STHENO: {"proc_dir": None, "failed": None, "process_method": None, "force": None, "delete_on": None, "ignore_subs": None}
|
||||
FORK_STHENO: {'proc_dir': None, 'failed': None, 'process_method': None, 'force': None, 'delete_on': None, 'ignore_subs': None},
|
||||
}
|
||||
ALL_FORKS = {k: None for k in set(list(itertools.chain.from_iterable([FORKS[x].keys() for x in FORKS.keys()])))}
|
||||
|
||||
|
@ -656,7 +661,7 @@ def configure_transcoder():
|
|||
codec_alias = {
|
||||
'libx264': ['libx264', 'h264', 'h.264', 'AVC', 'MPEG-4'],
|
||||
'libmp3lame': ['libmp3lame', 'mp3'],
|
||||
'libfaac': ['libfaac', 'aac', 'faac']
|
||||
'libfaac': ['libfaac', 'aac', 'faac'],
|
||||
}
|
||||
transcode_defaults = {
|
||||
'iPad': {
|
||||
|
@ -665,7 +670,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'iPad-1080p': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -673,7 +678,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'iPad-720p': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -681,7 +686,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': None, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'Apple-TV': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -689,7 +694,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6,
|
||||
'ACODEC2': 'aac', 'ACODEC2_ALLOW': ['libfaac'], 'ABITRATE2': None, 'ACHANNELS2': 2,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'iPod': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -697,7 +702,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
|
||||
'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'iPhone': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -705,7 +710,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
|
||||
'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'PS3': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -713,7 +718,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6,
|
||||
'ACODEC2': 'aac', 'ACODEC2_ALLOW': ['libfaac'], 'ABITRATE2': None, 'ACHANNELS2': 2,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'xbox': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -721,7 +726,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'ac3', 'ACODEC_ALLOW': ['ac3'], 'ABITRATE': None, 'ACHANNELS': 6,
|
||||
'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'Roku-480p': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -729,7 +734,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'Roku-720p': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -737,7 +742,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'Roku-1080p': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -745,7 +750,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 160000, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'mkv': {
|
||||
'VEXTENSION': '.mkv', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -761,7 +766,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8,
|
||||
'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
|
||||
'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'mp4-scene-release': {
|
||||
'VEXTENSION': '.mp4', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': None, 'VCRF': 19, 'VLEVEL': '3.1',
|
||||
|
@ -769,7 +774,7 @@ def configure_transcoder():
|
|||
'ACODEC': 'dts', 'ACODEC_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE': None, 'ACHANNELS': 8,
|
||||
'ACODEC2': None, 'ACODEC2_ALLOW': [], 'ABITRATE2': None, 'ACHANNELS2': None,
|
||||
'ACODEC3': 'ac3', 'ACODEC3_ALLOW': ['libfaac', 'dts', 'ac3', 'mp2', 'mp3'], 'ABITRATE3': None, 'ACHANNELS3': 8,
|
||||
'SCODEC': 'mov_text'
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
'MKV-SD': {
|
||||
'VEXTENSION': '.mkv', 'VCODEC': 'libx264', 'VPRESET': None, 'VFRAMERATE': None, 'VBITRATE': '1200k', 'VCRF': None, 'VLEVEL': None,
|
||||
|
@ -777,8 +782,8 @@ def configure_transcoder():
|
|||
'ACODEC': 'aac', 'ACODEC_ALLOW': ['libfaac'], 'ABITRATE': 128000, 'ACHANNELS': 2,
|
||||
'ACODEC2': 'ac3', 'ACODEC2_ALLOW': ['ac3'], 'ABITRATE2': None, 'ACHANNELS2': 6,
|
||||
'ACODEC3': None, 'ACODEC3_ALLOW': [], 'ABITRATE3': None, 'ACHANNELS3': None,
|
||||
'SCODEC': 'mov_text'
|
||||
}
|
||||
'SCODEC': 'mov_text',
|
||||
},
|
||||
}
|
||||
if DEFAULTS and DEFAULTS in transcode_defaults:
|
||||
VEXTENSION = transcode_defaults[DEFAULTS]['VEXTENSION']
|
||||
|
@ -881,7 +886,7 @@ def configure_utility_locations():
|
|||
|
||||
else:
|
||||
if SYS_PATH:
|
||||
os.environ['PATH'] += ':'+SYS_PATH
|
||||
os.environ['PATH'] += ':' + SYS_PATH
|
||||
try:
|
||||
SEVENZIP = subprocess.Popen(['which', '7z'], stdout=subprocess.PIPE).communicate()[0].strip().decode()
|
||||
except Exception:
|
||||
|
@ -968,7 +973,7 @@ def check_python():
|
|||
major=sys.version_info[0],
|
||||
minor=sys.version_info[1],
|
||||
x=days_left,
|
||||
)
|
||||
),
|
||||
)
|
||||
if days_left <= grace_period:
|
||||
logger.warning('Please upgrade to a more recent Python version.')
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
# coding=utf-8
|
||||
|
||||
import os
|
||||
import shutil
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import requests
|
||||
|
||||
import core
|
||||
from core import logger
|
||||
from core.auto_process.common import ProcessResult
|
||||
from core.utils import convert_to_ascii, server_responding
|
||||
from core.utils import (
|
||||
convert_to_ascii,
|
||||
remote_dir,
|
||||
server_responding,
|
||||
)
|
||||
|
||||
|
||||
requests.packages.urllib3.disable_warnings()
|
||||
|
||||
|
@ -24,6 +33,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
ssl = int(cfg.get('ssl', 0))
|
||||
web_root = cfg.get('web_root', '')
|
||||
protocol = 'https://' if ssl else 'http://'
|
||||
remote_path = int(cfg.get('remote_path', 0))
|
||||
|
||||
url = '{0}{1}:{2}{3}/api'.format(protocol, host, port, web_root)
|
||||
if not server_responding(url):
|
||||
|
@ -38,7 +48,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
params = {
|
||||
'apikey': apikey,
|
||||
'cmd': 'forceProcess',
|
||||
'dir': dir_name,
|
||||
'dir': remote_dir(dir_name) if remote_path else dir_name,
|
||||
}
|
||||
logger.debug('Opening URL: {0} with params: {1}'.format(url, params), section)
|
||||
|
||||
|
@ -52,7 +62,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
)
|
||||
|
||||
logger.postprocess('{0}'.format(r.text), section)
|
||||
|
||||
|
||||
if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
|
||||
logger.error('Server returned status {0}'.format(r.status_code), section)
|
||||
return ProcessResult(
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
@ -60,7 +67,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
logger.error('Unable to open URL', section)
|
||||
return ProcessResult(
|
||||
message='{0}: Failed to post-process - Unable to connect to {0}'.format(section),
|
||||
status_code=1
|
||||
status_code=1,
|
||||
)
|
||||
if r.status_code not in [requests.codes.ok, requests.codes.created, requests.codes.accepted]:
|
||||
logger.error('Server returned status {0}'.format(r.status_code), section)
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import requests
|
||||
|
||||
from core import logger
|
||||
|
@ -17,7 +24,7 @@ class ProcessResult(object):
|
|||
def __str__(self):
|
||||
return 'Processing {0}: {1}'.format(
|
||||
'succeeded' if bool(self) else 'failed',
|
||||
self.message
|
||||
self.message,
|
||||
)
|
||||
|
||||
def __repr__(self):
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
@ -46,7 +53,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
'api_key': apikey,
|
||||
'mode': 'UPDATEREQUESTEDSTATUS',
|
||||
'db_id': gamez_id,
|
||||
'status': download_status
|
||||
'status': download_status,
|
||||
}
|
||||
|
||||
logger.debug('Opening URL: {0}'.format(url), section)
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
|
@ -256,7 +263,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
return ProcessResult(
|
||||
message='{0}: Sending failed download back to {0}'.format(section),
|
||||
status_code=1, # Return as failed to flag this in the downloader.
|
||||
) # Return failed flag, but log the event as successful.
|
||||
) # Return failed flag, but log the event as successful.
|
||||
|
||||
if delete_failed and os.path.isdir(dir_name) and not os.path.dirname(dir_name) == dir_name:
|
||||
logger.postprocess('Deleting failed files and folder {0}'.format(dir_name), section)
|
||||
|
@ -373,22 +380,22 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
except Exception:
|
||||
pass
|
||||
elif scan_id:
|
||||
url = '{0}/{1}'.format(base_url, scan_id)
|
||||
command_status = command_complete(url, params, headers, section)
|
||||
if command_status:
|
||||
logger.debug('The Scan command return status: {0}'.format(command_status), section)
|
||||
if command_status in ['completed']:
|
||||
logger.debug('The Scan command has completed successfully. Renaming was successful.', section)
|
||||
return ProcessResult(
|
||||
message='{0}: Successfully post-processed {1}'.format(section, input_name),
|
||||
status_code=0,
|
||||
)
|
||||
elif command_status in ['failed']:
|
||||
logger.debug('The Scan command has failed. Renaming was not successful.', section)
|
||||
# return ProcessResult(
|
||||
# message='{0}: Failed to post-process {1}'.format(section, input_name),
|
||||
# status_code=1,
|
||||
# )
|
||||
url = '{0}/{1}'.format(base_url, scan_id)
|
||||
command_status = command_complete(url, params, headers, section)
|
||||
if command_status:
|
||||
logger.debug('The Scan command return status: {0}'.format(command_status), section)
|
||||
if command_status in ['completed']:
|
||||
logger.debug('The Scan command has completed successfully. Renaming was successful.', section)
|
||||
return ProcessResult(
|
||||
message='{0}: Successfully post-processed {1}'.format(section, input_name),
|
||||
status_code=0,
|
||||
)
|
||||
elif command_status in ['failed']:
|
||||
logger.debug('The Scan command has failed. Renaming was not successful.', section)
|
||||
# return ProcessResult(
|
||||
# message='{0}: Failed to post-process {1}'.format(section, input_name),
|
||||
# status_code=1,
|
||||
# )
|
||||
|
||||
if not os.path.isdir(dir_name):
|
||||
logger.postprocess('SUCCESS: Input Directory [{0}] has been processed and removed'.format(
|
||||
|
@ -504,7 +511,7 @@ def get_release(base_url, imdb_id=None, download_id=None, release_id=None):
|
|||
# Narrow results by removing old releases by comparing their last_edit field
|
||||
if len(results) > 1:
|
||||
for id1, x1 in results.items():
|
||||
for id2, x2 in results.items():
|
||||
for x2 in results.values():
|
||||
try:
|
||||
if x2['last_edit'] > x1['last_edit']:
|
||||
results.pop(id1)
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import json
|
||||
import os
|
||||
import time
|
||||
|
@ -73,7 +80,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
params = {
|
||||
'apikey': apikey,
|
||||
'cmd': 'forceProcess',
|
||||
'dir': remote_dir(dir_name) if remote_path else dir_name
|
||||
'dir': remote_dir(dir_name) if remote_path else dir_name,
|
||||
}
|
||||
|
||||
res = force_process(params, url, apikey, input_name, dir_name, section, wait_for)
|
||||
|
@ -83,7 +90,7 @@ def process(section, dir_name, input_name=None, status=0, client_agent='manual',
|
|||
params = {
|
||||
'apikey': apikey,
|
||||
'cmd': 'forceProcess',
|
||||
'dir': os.path.split(remote_dir(dir_name))[0] if remote_path else os.path.split(dir_name)[0]
|
||||
'dir': os.path.split(remote_dir(dir_name))[0] if remote_path else os.path.split(dir_name)[0],
|
||||
}
|
||||
|
||||
res = force_process(params, url, apikey, input_name, dir_name, section, wait_for)
|
||||
|
@ -187,7 +194,7 @@ def get_status(url, apikey, dir_name):
|
|||
|
||||
params = {
|
||||
'apikey': apikey,
|
||||
'cmd': 'getHistory'
|
||||
'cmd': 'getHistory',
|
||||
}
|
||||
|
||||
logger.debug('Opening URL: {0} with PARAMS: {1}'.format(url, params))
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import copy
|
||||
import errno
|
||||
import json
|
||||
|
@ -266,7 +273,7 @@ def process(section, dir_name, input_name=None, failed=False, client_agent='manu
|
|||
if apikey:
|
||||
url = '{0}{1}:{2}{3}/api/{4}/?cmd=postprocess'.format(protocol, host, port, web_root, apikey)
|
||||
elif fork == 'Stheno':
|
||||
url = "{0}{1}:{2}{3}/home/postprocess/process_episode".format(protocol, host, port, web_root)
|
||||
url = '{0}{1}:{2}{3}/home/postprocess/process_episode'.format(protocol, host, port, web_root)
|
||||
else:
|
||||
url = '{0}{1}:{2}{3}/home/postprocess/processEpisode'.format(protocol, host, port, web_root)
|
||||
elif section == 'NzbDrone':
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import copy
|
||||
import os
|
||||
import shutil
|
||||
|
@ -13,17 +20,17 @@ from core import logger
|
|||
|
||||
|
||||
class Section(configobj.Section, object):
|
||||
def isenabled(section):
|
||||
def isenabled(self):
|
||||
# checks if subsection enabled, returns true/false if subsection specified otherwise returns true/false in {}
|
||||
if not section.sections:
|
||||
if not self.sections:
|
||||
try:
|
||||
value = list(ConfigObj.find_key(section, 'enabled'))[0]
|
||||
value = list(ConfigObj.find_key(self, 'enabled'))[0]
|
||||
except Exception:
|
||||
value = 0
|
||||
if int(value) == 1:
|
||||
return section
|
||||
return self
|
||||
else:
|
||||
to_return = copy.deepcopy(section)
|
||||
to_return = copy.deepcopy(self)
|
||||
for section_name, subsections in to_return.items():
|
||||
for subsection in subsections:
|
||||
try:
|
||||
|
@ -40,8 +47,8 @@ class Section(configobj.Section, object):
|
|||
|
||||
return to_return
|
||||
|
||||
def findsection(section, key):
|
||||
to_return = copy.deepcopy(section)
|
||||
def findsection(self, key):
|
||||
to_return = copy.deepcopy(self)
|
||||
for subsection in to_return:
|
||||
try:
|
||||
value = list(ConfigObj.find_key(to_return[subsection], key))[0]
|
||||
|
@ -136,10 +143,10 @@ class ConfigObj(configobj.ConfigObj, Section):
|
|||
|
||||
subsections = {}
|
||||
# gather all new-style and old-style sub-sections
|
||||
for newsection, newitems in CFG_NEW.items():
|
||||
for newsection in CFG_NEW:
|
||||
if CFG_NEW[newsection].sections:
|
||||
subsections.update({newsection: CFG_NEW[newsection].sections})
|
||||
for section, items in CFG_OLD.items():
|
||||
for section in CFG_OLD:
|
||||
if CFG_OLD[section].sections:
|
||||
subsections.update({section: CFG_OLD[section].sections})
|
||||
for option, value in CFG_OLD[section].items():
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from core import logger, main_db
|
||||
from core.utils import backup_versioned_file
|
||||
|
||||
|
@ -33,7 +40,7 @@ class InitialSchema(main_db.SchemaUpgrade):
|
|||
queries = [
|
||||
'CREATE TABLE db_version (db_version INTEGER);',
|
||||
'CREATE TABLE downloads (input_directory TEXT, input_name TEXT, input_hash TEXT, input_id TEXT, client_agent TEXT, status INTEGER, last_update NUMERIC, CONSTRAINT pk_downloadID PRIMARY KEY (input_directory, input_name));',
|
||||
'INSERT INTO db_version (db_version) VALUES (2);'
|
||||
'INSERT INTO db_version (db_version) VALUES (2);',
|
||||
]
|
||||
for query in queries:
|
||||
self.connection.action(query)
|
||||
|
@ -59,7 +66,7 @@ class InitialSchema(main_db.SchemaUpgrade):
|
|||
'INSERT INTO downloads2 SELECT * FROM downloads;',
|
||||
'DROP TABLE IF EXISTS downloads;',
|
||||
'ALTER TABLE downloads2 RENAME TO downloads;',
|
||||
'INSERT INTO db_version (db_version) VALUES (2);'
|
||||
'INSERT INTO db_version (db_version) VALUES (2);',
|
||||
]
|
||||
for query in queries:
|
||||
self.connection.action(query)
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import platform
|
||||
import shutil
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import requests
|
||||
from six import iteritems
|
||||
|
||||
|
@ -42,7 +49,8 @@ def auto_fork(section, input_category):
|
|||
logger.info('Attempting to verify {category} fork'.format
|
||||
(category=input_category))
|
||||
url = '{protocol}{host}:{port}{root}/api/rootfolder'.format(
|
||||
protocol=protocol, host=host, port=port, root=web_root)
|
||||
protocol=protocol, host=host, port=port, root=web_root,
|
||||
)
|
||||
headers = {'X-Api-Key': apikey}
|
||||
try:
|
||||
r = requests.get(url, headers=headers, stream=True, verify=False)
|
||||
|
@ -65,10 +73,12 @@ def auto_fork(section, input_category):
|
|||
|
||||
if apikey:
|
||||
url = '{protocol}{host}:{port}{root}/api/{apikey}/?cmd=help&subject=postprocess'.format(
|
||||
protocol=protocol, host=host, port=port, root=web_root, apikey=apikey)
|
||||
protocol=protocol, host=host, port=port, root=web_root, apikey=apikey,
|
||||
)
|
||||
else:
|
||||
url = '{protocol}{host}:{port}{root}/home/postprocess/'.format(
|
||||
protocol=protocol, host=host, port=port, root=web_root)
|
||||
protocol=protocol, host=host, port=port, root=web_root,
|
||||
)
|
||||
|
||||
# attempting to auto-detect fork
|
||||
try:
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import requests
|
||||
|
||||
|
||||
class GitHub(object):
|
||||
"""
|
||||
Simple api wrapper for the Github API v3.
|
||||
"""
|
||||
"""Simple api wrapper for the Github API v3."""
|
||||
|
||||
def __init__(self, github_repo_user, github_repo, branch='master'):
|
||||
|
||||
|
@ -15,16 +20,14 @@ class GitHub(object):
|
|||
self.branch = branch
|
||||
|
||||
def _access_api(self, path, params=None):
|
||||
"""
|
||||
Access the API at the path given and with the optional params given.
|
||||
"""
|
||||
"""Access API at given an API path and optional parameters."""
|
||||
url = 'https://api.github.com/{path}'.format(path='/'.join(path))
|
||||
data = requests.get(url, params=params, verify=False)
|
||||
return data.json() if data.ok else []
|
||||
|
||||
def commits(self):
|
||||
"""
|
||||
Uses the API to get a list of the 100 most recent commits from the specified user/repo/branch, starting from HEAD.
|
||||
Get the 100 most recent commits from the specified user/repo/branch, starting from HEAD.
|
||||
|
||||
user: The github username of the person whose repo you're querying
|
||||
repo: The repo name to query
|
||||
|
@ -39,7 +42,7 @@ class GitHub(object):
|
|||
|
||||
def compare(self, base, head, per_page=1):
|
||||
"""
|
||||
Uses the API to get a list of compares between base and head.
|
||||
Get compares between base and head.
|
||||
|
||||
user: The github username of the person whose repo you're querying
|
||||
repo: The repo name to query
|
||||
|
|
|
@ -1,11 +1,19 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
|
||||
import core
|
||||
import functools
|
||||
|
||||
# number of log files to keep
|
||||
NUM_LOGS = 3
|
||||
|
@ -85,9 +93,9 @@ class NTMRotatingLogHandler(object):
|
|||
console.setFormatter(DispatchingFormatter(
|
||||
{'nzbtomedia': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'),
|
||||
'postprocess': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'),
|
||||
'db': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S')
|
||||
'db': logging.Formatter('[%(asctime)s] [%(levelname)s]::%(message)s', '%H:%M:%S'),
|
||||
},
|
||||
logging.Formatter('%(message)s'), ))
|
||||
logging.Formatter('%(message)s')))
|
||||
|
||||
# add the handler to the root logger
|
||||
logging.getLogger('nzbtomedia').addHandler(console)
|
||||
|
@ -111,10 +119,7 @@ class NTMRotatingLogHandler(object):
|
|||
self.close_log(old_handler)
|
||||
|
||||
def _config_handler(self):
|
||||
"""
|
||||
Configure a file handler to log at file_name and return it.
|
||||
"""
|
||||
|
||||
"""Configure a file handler to log at file_name and return it."""
|
||||
file_handler = logging.FileHandler(self.log_file_path, encoding='utf-8')
|
||||
|
||||
file_handler.setLevel(DB)
|
||||
|
@ -122,29 +127,29 @@ class NTMRotatingLogHandler(object):
|
|||
file_handler.setFormatter(DispatchingFormatter(
|
||||
{'nzbtomedia': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'),
|
||||
'postprocess': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'),
|
||||
'db': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S')
|
||||
'db': logging.Formatter('%(asctime)s %(levelname)-8s::%(message)s', '%Y-%m-%d %H:%M:%S'),
|
||||
},
|
||||
logging.Formatter('%(message)s'), ))
|
||||
logging.Formatter('%(message)s')))
|
||||
|
||||
return file_handler
|
||||
|
||||
def _log_file_name(self, i):
|
||||
"""
|
||||
Returns a numbered log file name depending on i. If i==0 it just uses logName, if not it appends
|
||||
it to the extension (blah.log.3 for i == 3)
|
||||
|
||||
Return a numbered log file name depending on i.
|
||||
|
||||
If i==0 it just uses logName, if not it appends it to the extension
|
||||
e.g. (blah.log.3 for i == 3)
|
||||
|
||||
i: Log number to ues
|
||||
"""
|
||||
|
||||
return self.log_file_path + ('.{0}'.format(i) if i else '')
|
||||
|
||||
def _num_logs(self):
|
||||
"""
|
||||
Scans the log folder and figures out how many log files there are already on disk
|
||||
Scan the log folder and figure out how many log files there are already on disk.
|
||||
|
||||
Returns: The number of the last used file (eg. mylog.log.3 would return 3). If there are no logs it returns -1
|
||||
"""
|
||||
|
||||
cur_log = 0
|
||||
while os.path.isfile(self._log_file_name(cur_log)):
|
||||
cur_log += 1
|
||||
|
@ -202,9 +207,8 @@ class NTMRotatingLogHandler(object):
|
|||
ntm_logger = logging.getLogger('nzbtomedia')
|
||||
pp_logger = logging.getLogger('postprocess')
|
||||
db_logger = logging.getLogger('db')
|
||||
setattr(pp_logger, 'postprocess', lambda *args: pp_logger.log(POSTPROCESS, *args))
|
||||
setattr(db_logger, 'db', lambda *args: db_logger.log(DB, *args))
|
||||
|
||||
pp_logger.postprocess = functools.partial(pp_logger.log, POSTPROCESS)
|
||||
db_logger.db = functools.partial(db_logger.log, DB)
|
||||
try:
|
||||
if log_level == DEBUG:
|
||||
if core.LOG_DEBUG == 1:
|
||||
|
|
|
@ -1,19 +1,52 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import re
|
||||
import sqlite3
|
||||
import time
|
||||
|
||||
from six import text_type
|
||||
from six import text_type, PY2
|
||||
|
||||
import core
|
||||
from core import logger
|
||||
|
||||
if PY2:
|
||||
class Row(sqlite3.Row, object):
|
||||
"""
|
||||
Row factory that uses Byte Strings for keys.
|
||||
|
||||
The sqlite3.Row in Python 2 does not support unicode keys.
|
||||
This overrides __getitem__ to attempt to encode the key to bytes first.
|
||||
"""
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""
|
||||
Get an item from the row by index or key.
|
||||
|
||||
:param item: Index or Key of item to return.
|
||||
:return: An item from the sqlite3.Row.
|
||||
"""
|
||||
try:
|
||||
# sqlite3.Row column names should be Bytes in Python 2
|
||||
item = item.encode()
|
||||
except AttributeError:
|
||||
pass # assume item is a numeric index
|
||||
|
||||
return super(Row, self).__getitem__(item)
|
||||
else:
|
||||
from sqlite3 import Row
|
||||
|
||||
|
||||
def db_filename(filename='nzbtomedia.db', suffix=None):
|
||||
"""
|
||||
Return the correct location of the database file.
|
||||
|
||||
@param filename: The sqlite database filename to use. If not specified,
|
||||
will be made to be nzbtomedia.db
|
||||
@param suffix: The suffix to append to the filename. A '.' will be added
|
||||
|
@ -30,10 +63,7 @@ class DBConnection(object):
|
|||
|
||||
self.filename = filename
|
||||
self.connection = sqlite3.connect(db_filename(filename), 20)
|
||||
if row_type == 'dict':
|
||||
self.connection.row_factory = self._dict_factory
|
||||
else:
|
||||
self.connection.row_factory = sqlite3.Row
|
||||
self.connection.row_factory = Row
|
||||
|
||||
def check_db_version(self):
|
||||
result = None
|
||||
|
@ -183,9 +213,9 @@ class DBConnection(object):
|
|||
'WHERE {conditions}'.format(
|
||||
table=table_name,
|
||||
params=', '.join(gen_params(value_dict)),
|
||||
conditions=' AND '.join(gen_params(key_dict))
|
||||
conditions=' AND '.join(gen_params(key_dict)),
|
||||
),
|
||||
items
|
||||
items,
|
||||
)
|
||||
|
||||
if self.connection.total_changes == changes_before:
|
||||
|
@ -194,9 +224,9 @@ class DBConnection(object):
|
|||
'VALUES ({values})'.format(
|
||||
table=table_name,
|
||||
columns=', '.join(map(text_type, value_dict.keys())),
|
||||
values=', '.join(['?'] * len(value_dict.values()))
|
||||
values=', '.join(['?'] * len(value_dict.values())),
|
||||
),
|
||||
list(value_dict.values())
|
||||
list(value_dict.values()),
|
||||
)
|
||||
|
||||
def table_info(self, table_name):
|
||||
|
@ -207,13 +237,6 @@ class DBConnection(object):
|
|||
for column in cursor
|
||||
}
|
||||
|
||||
# http://stackoverflow.com/questions/3300464/how-can-i-get-dict-from-sqlite-query
|
||||
def _dict_factory(self, cursor, row):
|
||||
return {
|
||||
col[0]: row[idx]
|
||||
for idx, col in enumerate(cursor.description)
|
||||
}
|
||||
|
||||
|
||||
def sanity_check_database(connection, sanity_check):
|
||||
sanity_check(connection).check()
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import core
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import core
|
||||
from core.plugins.downloaders.torrent.utils import create_torrent_class
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from synchronousdeluge.client import DelugeClient
|
||||
|
||||
import core
|
||||
|
|
|
@ -1,4 +1,10 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
|
||||
from qbittorrent import Client as qBittorrentClient
|
||||
|
||||
|
@ -14,7 +20,7 @@ def configure_client():
|
|||
password = core.QBITTORRENT_PASSWORD
|
||||
|
||||
logger.debug(
|
||||
'Connecting to {0}: http://{1}:{2}'.format(agent, host, port)
|
||||
'Connecting to {0}: http://{1}:{2}'.format(agent, host, port),
|
||||
)
|
||||
client = qBittorrentClient('http://{0}:{1}/'.format(host, port))
|
||||
try:
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from transmissionrpc.client import Client as TransmissionClient
|
||||
|
||||
import core
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import time
|
||||
|
||||
import core
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from utorrent.client import UTorrentClient
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import requests
|
||||
|
||||
import core
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from babelfish import Language
|
||||
import subliminal
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
|
@ -25,7 +32,7 @@ media_list = [r'\.s\d{2}e\d{2}\.', r'\.1080[pi]\.', r'\.720p\.', r'\.576[pi]', r
|
|||
r'\.internal\.', r'\bac3\b', r'\.ntsc\.', r'\.pal\.', r'\.secam\.', r'\bdivx\b', r'\bxvid\b']
|
||||
media_pattern = re.compile('|'.join(media_list), flags=re.IGNORECASE)
|
||||
garbage_name = re.compile(r'^[a-zA-Z0-9]*$')
|
||||
char_replace = [[r'(\w)1\.(\w)', r'\1i\2']
|
||||
char_replace = [[r'(\w)1\.(\w)', r'\1i\2'],
|
||||
]
|
||||
|
||||
|
||||
|
@ -121,7 +128,7 @@ def reverse_filename(filename, dirname, name):
|
|||
|
||||
def rename_script(dirname):
|
||||
rename_file = ''
|
||||
for directory, directories, files in os.walk(dirname):
|
||||
for directory, _, files in os.walk(dirname):
|
||||
for file in files:
|
||||
if re.search(r'(rename\S*\.(sh|bat)$)', file, re.IGNORECASE):
|
||||
rename_file = os.path.join(directory, file)
|
||||
|
@ -171,7 +178,7 @@ def par2(dirname):
|
|||
cmd = ''
|
||||
for item in command:
|
||||
cmd = '{cmd} {item}'.format(cmd=cmd, item=item)
|
||||
logger.debug('calling command:{0}'.format(cmd), 'PAR2')
|
||||
logger.debug('calling command:{0}'.format(cmd), 'PAR2')
|
||||
try:
|
||||
proc = subprocess.Popen(command, stdout=bitbucket, stderr=bitbucket)
|
||||
proc.communicate()
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import errno
|
||||
import json
|
||||
import sys
|
||||
|
@ -548,7 +555,7 @@ def get_subs(file):
|
|||
sub_ext = ['.srt', '.sub', '.idx']
|
||||
name = os.path.splitext(os.path.split(file)[1])[0]
|
||||
path = os.path.split(file)[0]
|
||||
for directory, directories, filenames in os.walk(path):
|
||||
for directory, _, filenames in os.walk(path):
|
||||
for filename in filenames:
|
||||
filepaths.extend([os.path.join(directory, filename)])
|
||||
subfiles = [item for item in filepaths if os.path.splitext(item)[1] in sub_ext and name in item]
|
||||
|
@ -854,7 +861,7 @@ def combine_mts(mts_path):
|
|||
|
||||
def combine_cd(combine):
|
||||
new_files = []
|
||||
for item in set([re.match('(.+)[cC][dD][0-9].', item).groups()[0] for item in combine]):
|
||||
for item in {re.match('(.+)[cC][dD][0-9].', item).groups()[0] for item in combine}:
|
||||
concat = ''
|
||||
for n in range(99):
|
||||
files = [file for file in combine if
|
||||
|
@ -920,7 +927,7 @@ def transcode_directory(dir_name):
|
|||
logger.info('Transcoding video: {0}'.format(newfile_path))
|
||||
print_cmd(command)
|
||||
result = 1 # set result to failed in case call fails.
|
||||
if True:
|
||||
try:
|
||||
if isinstance(file, string_types):
|
||||
proc = subprocess.Popen(command, stdout=bitbucket, stderr=bitbucket)
|
||||
else:
|
||||
|
@ -934,8 +941,8 @@ def transcode_directory(dir_name):
|
|||
procin.stdout.close()
|
||||
proc.communicate()
|
||||
result = proc.returncode
|
||||
#except Exception:
|
||||
# logger.error('Transcoding of video {0} has failed'.format(newfile_path))
|
||||
except Exception:
|
||||
logger.error('Transcoding of video {0} has failed'.format(newfile_path))
|
||||
|
||||
if core.SUBSDIR and result == 0 and isinstance(file, string_types):
|
||||
for sub in get_subs(file):
|
||||
|
@ -979,7 +986,7 @@ def transcode_directory(dir_name):
|
|||
if not os.listdir(text_type(new_dir)): # this is an empty directory and we didn't transcode into it.
|
||||
os.rmdir(new_dir)
|
||||
new_dir = dir_name
|
||||
if not core.PROCESSOUTPUT and core.DUPLICATE: # We postprocess the original files to CP/SB
|
||||
if not core.PROCESSOUTPUT and core.DUPLICATE: # We postprocess the original files to CP/SB
|
||||
new_dir = dir_name
|
||||
bitbucket.close()
|
||||
return final_result, new_dir
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
from subprocess import Popen
|
||||
|
||||
|
@ -47,7 +54,7 @@ def external_script(output_destination, torrent_name, torrent_label, settings):
|
|||
logger.info('Corrupt video file found {0}. Deleting.'.format(video), 'USERSCRIPT')
|
||||
os.unlink(video)
|
||||
|
||||
for dirpath, dirnames, filenames in os.walk(output_destination):
|
||||
for dirpath, _, filenames in os.walk(output_destination):
|
||||
for file in filenames:
|
||||
|
||||
file_path = core.os.path.join(dirpath, file)
|
||||
|
@ -102,7 +109,7 @@ def external_script(output_destination, torrent_name, torrent_label, settings):
|
|||
final_result += result
|
||||
|
||||
num_files_new = 0
|
||||
for dirpath, dirnames, filenames in os.walk(output_destination):
|
||||
for _, _, filenames in os.walk(output_destination):
|
||||
for file in filenames:
|
||||
file_name, file_extension = os.path.splitext(file)
|
||||
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import requests
|
||||
|
||||
from core.utils import shutil_custom
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os.path
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import datetime
|
||||
|
||||
from six import text_type
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
|
||||
from six import text_type
|
||||
|
@ -68,14 +75,14 @@ def convert_to_ascii(input_name, dir_name):
|
|||
if 'NZBOP_SCRIPTDIR' in os.environ:
|
||||
print('[NZB] DIRECTORY={0}'.format(dir_name))
|
||||
|
||||
for dirname, dirnames, filenames in os.walk(dir_name, topdown=False):
|
||||
for dirname, dirnames, _ in os.walk(dir_name, topdown=False):
|
||||
for subdirname in dirnames:
|
||||
encoded, subdirname2 = char_replace(subdirname)
|
||||
if encoded:
|
||||
logger.info('Renaming directory to: {0}.'.format(subdirname2), 'ENCODER')
|
||||
os.rename(os.path.join(dirname, subdirname), os.path.join(dirname, subdirname2))
|
||||
|
||||
for dirname, dirnames, filenames in os.walk(dir_name):
|
||||
for dirname, _, filenames in os.walk(dir_name):
|
||||
for filename in filenames:
|
||||
encoded, filename2 = char_replace(filename)
|
||||
if encoded:
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
@ -88,7 +95,7 @@ def is_min_size(input_name, min_size):
|
|||
|
||||
|
||||
def is_archive_file(filename):
|
||||
"""Check if the filename is allowed for the Archive"""
|
||||
"""Check if the filename is allowed for the Archive."""
|
||||
for regext in core.COMPRESSED_CONTAINER:
|
||||
if regext.search(filename):
|
||||
return regext.split(filename)[0]
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import re
|
||||
|
||||
|
@ -5,7 +12,6 @@ import guessit
|
|||
import requests
|
||||
from six import text_type
|
||||
|
||||
import core
|
||||
from core import logger
|
||||
from core.utils.naming import sanitize_name
|
||||
|
||||
|
@ -90,13 +96,13 @@ def find_imdbid(dir_name, input_name, omdb_api_key):
|
|||
def category_search(input_directory, input_name, input_category, root, categories):
|
||||
tordir = False
|
||||
|
||||
#try:
|
||||
# try:
|
||||
# input_name = input_name.encode(core.SYS_ENCODING)
|
||||
#except Exception:
|
||||
# except Exception:
|
||||
# pass
|
||||
#try:
|
||||
# try:
|
||||
# input_directory = input_directory.encode(core.SYS_ENCODING)
|
||||
#except Exception:
|
||||
# except Exception:
|
||||
# pass
|
||||
|
||||
if input_directory is None: # =Nothing to process here.
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
|
|
|
@ -1,9 +1,17 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import re
|
||||
import core
|
||||
|
||||
|
||||
def sanitize_name(name):
|
||||
"""
|
||||
Remove bad chars from the filename.
|
||||
|
||||
>>> sanitize_name('a/b/c')
|
||||
'a-b-c'
|
||||
>>> sanitize_name('abc')
|
||||
|
@ -13,29 +21,26 @@ def sanitize_name(name):
|
|||
>>> sanitize_name('.a.b..')
|
||||
'a.b'
|
||||
"""
|
||||
|
||||
# remove bad chars from the filename
|
||||
name = re.sub(r'[\\/*]', '-', name)
|
||||
name = re.sub(r'[:\'<>|?]', '', name)
|
||||
|
||||
# remove leading/trailing periods and spaces
|
||||
name = name.strip(' .')
|
||||
#try:
|
||||
# try:
|
||||
# name = name.encode(core.SYS_ENCODING)
|
||||
#except Exception:
|
||||
# except Exception:
|
||||
# pass
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def clean_file_name(filename):
|
||||
"""Cleans up nzb name by removing any . and _
|
||||
characters, along with any trailing hyphens.
|
||||
"""
|
||||
Clean up nzb name by removing any . and _ characters and trailing hyphens.
|
||||
|
||||
Is basically equivalent to replacing all _ and . with a
|
||||
space, but handles decimal numbers in string, for example:
|
||||
"""
|
||||
|
||||
filename = re.sub(r'(\D)\.(?!\s)(\D)', r'\1 \2', filename)
|
||||
filename = re.sub(r'(\d)\.(\d{4})', r'\1 \2', filename) # if it ends in a year then don't keep the dot
|
||||
filename = re.sub(r'(\D)\.(?!\s)', r'\1 ', filename)
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import socket
|
||||
import struct
|
||||
import time
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
|
||||
import core
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from functools import partial
|
||||
import os
|
||||
|
@ -67,14 +73,14 @@ def remote_dir(path):
|
|||
|
||||
def get_dir_size(input_path):
|
||||
prepend = partial(os.path.join, input_path)
|
||||
return sum([
|
||||
return sum(
|
||||
(os.path.getsize(f) if os.path.isfile(f) else get_dir_size(f))
|
||||
for f in map(prepend, os.listdir(text_type(input_path)))
|
||||
])
|
||||
)
|
||||
|
||||
|
||||
def remove_empty_folders(path, remove_root=True):
|
||||
"""Function to remove empty folders"""
|
||||
"""Remove empty folders."""
|
||||
if not os.path.isdir(path):
|
||||
return
|
||||
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import socket
|
||||
import subprocess
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from functools import partial
|
||||
import shutil
|
||||
from six import PY2
|
||||
|
|
|
@ -2,6 +2,13 @@
|
|||
# Author: Nic Wolfe <nic@wolfeden.ca>
|
||||
# Modified by: echel0n
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
|
@ -19,9 +26,7 @@ from core import github_api as github, logger
|
|||
|
||||
|
||||
class CheckVersion(object):
|
||||
"""
|
||||
Version check class meant to run as a thread object with the SB scheduler.
|
||||
"""
|
||||
"""Version checker that runs in a thread with the SB scheduler."""
|
||||
|
||||
def __init__(self):
|
||||
self.install_type = self.find_install_type()
|
||||
|
@ -40,14 +45,13 @@ class CheckVersion(object):
|
|||
|
||||
def find_install_type(self):
|
||||
"""
|
||||
Determines how this copy of SB was installed.
|
||||
Determine how this copy of SB was installed.
|
||||
|
||||
returns: type of installation. Possible values are:
|
||||
'win': any compiled windows build
|
||||
'git': running from source using git
|
||||
'source': running from source without git
|
||||
"""
|
||||
|
||||
# check if we're a windows build
|
||||
if os.path.isdir(os.path.join(core.APP_ROOT, u'.git')):
|
||||
install_type = 'git'
|
||||
|
@ -58,13 +62,12 @@ class CheckVersion(object):
|
|||
|
||||
def check_for_new_version(self, force=False):
|
||||
"""
|
||||
Checks the internet for a newer version.
|
||||
Check the internet for a newer version.
|
||||
|
||||
returns: bool, True for new version or False for no new version.
|
||||
|
||||
force: if true the VERSION_NOTIFY setting will be ignored and a check will be forced
|
||||
"""
|
||||
|
||||
if not core.VERSION_NOTIFY and not force:
|
||||
logger.log(u'Version checking is disabled, not checking for the newest version')
|
||||
return False
|
||||
|
@ -199,8 +202,8 @@ class GitUpdateManager(UpdateManager):
|
|||
logger.log(u'{cmd} : returned successful'.format(cmd=cmd), logger.DEBUG)
|
||||
exit_status = 0
|
||||
elif core.LOG_GIT and exit_status in (1, 128):
|
||||
logger.log(u'{cmd} returned : {output}'.format
|
||||
(cmd=cmd, output=output), logger.DEBUG)
|
||||
logger.log(u'{cmd} returned : {output}'.format
|
||||
(cmd=cmd, output=output), logger.DEBUG)
|
||||
else:
|
||||
if core.LOG_GIT:
|
||||
logger.log(u'{cmd} returned : {output}, treat as error for now'.format
|
||||
|
@ -211,13 +214,12 @@ class GitUpdateManager(UpdateManager):
|
|||
|
||||
def _find_installed_version(self):
|
||||
"""
|
||||
Attempts to find the currently installed version of Sick Beard.
|
||||
Attempt to find the currently installed version of Sick Beard.
|
||||
|
||||
Uses git show to get commit version.
|
||||
|
||||
Returns: True for success or False for failure
|
||||
"""
|
||||
|
||||
output, err, exit_status = self._run_git(self._git_path, 'rev-parse HEAD') # @UnusedVariable
|
||||
|
||||
if exit_status == 0 and output:
|
||||
|
@ -244,10 +246,12 @@ class GitUpdateManager(UpdateManager):
|
|||
|
||||
def _check_github_for_update(self):
|
||||
"""
|
||||
Uses git commands to check if there is a newer version that the provided
|
||||
commit hash. If there is a newer version it sets _num_commits_behind.
|
||||
"""
|
||||
Check Github for a new version.
|
||||
|
||||
Uses git commands to check if there is a newer version than
|
||||
the provided commit hash. If there is a newer version it
|
||||
sets _num_commits_behind.
|
||||
"""
|
||||
self._newest_commit_hash = None
|
||||
self._num_commits_behind = 0
|
||||
self._num_commits_ahead = 0
|
||||
|
@ -324,10 +328,11 @@ class GitUpdateManager(UpdateManager):
|
|||
|
||||
def update(self):
|
||||
"""
|
||||
Calls git pull origin <branch> in order to update Sick Beard. Returns a bool depending
|
||||
on the call's success.
|
||||
"""
|
||||
Check git for a new version.
|
||||
|
||||
Calls git pull origin <branch> in order to update Sick Beard.
|
||||
Returns a bool depending on the call's success.
|
||||
"""
|
||||
output, err, exit_status = self._run_git(self._git_path, 'pull origin {branch}'.format(branch=self.branch)) # @UnusedVariable
|
||||
|
||||
if exit_status == 0:
|
||||
|
@ -382,12 +387,14 @@ class SourceUpdateManager(UpdateManager):
|
|||
|
||||
def _check_github_for_update(self):
|
||||
"""
|
||||
Uses pygithub to ask github if there is a newer version that the provided
|
||||
commit hash. If there is a newer version it sets Sick Beard's version text.
|
||||
Check Github for a new version.
|
||||
|
||||
Uses pygithub to ask github if there is a newer version than
|
||||
the provided commit hash. If there is a newer version it sets
|
||||
Sick Beard's version text.
|
||||
|
||||
commit_hash: hash that we're checking against
|
||||
"""
|
||||
|
||||
self._num_commits_behind = 0
|
||||
self._newest_commit_hash = None
|
||||
|
||||
|
@ -435,9 +442,7 @@ class SourceUpdateManager(UpdateManager):
|
|||
return
|
||||
|
||||
def update(self):
|
||||
"""
|
||||
Downloads the latest source tarball from github and installs it over the existing version.
|
||||
"""
|
||||
"""Download and install latest source tarball from github."""
|
||||
tar_download_url = 'https://github.com/{org}/{repo}/tarball/{branch}'.format(
|
||||
org=self.github_repo_user, repo=self.github_repo, branch=self.branch)
|
||||
version_path = os.path.join(core.APP_ROOT, u'version.txt')
|
||||
|
@ -489,7 +494,7 @@ class SourceUpdateManager(UpdateManager):
|
|||
# walk temp folder and move files to main folder
|
||||
logger.log(u'Moving files from {source} to {destination}'.format
|
||||
(source=content_dir, destination=core.APP_ROOT))
|
||||
for dirname, dirnames, filenames in os.walk(content_dir): # @UnusedVariable
|
||||
for dirname, _, filenames in os.walk(content_dir): # @UnusedVariable
|
||||
dirname = dirname[len(content_dir) + 1:]
|
||||
for curfile in filenames:
|
||||
old_path = os.path.join(content_dir, dirname, curfile)
|
||||
|
|
11
eol.py
11
eol.py
|
@ -1,5 +1,12 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import datetime
|
||||
import sys
|
||||
import warnings
|
||||
|
@ -157,7 +164,7 @@ def print_statuses(show_expired=False):
|
|||
major=python_version[0],
|
||||
minor=python_version[1],
|
||||
remaining=days_left,
|
||||
)
|
||||
),
|
||||
)
|
||||
if not show_expired:
|
||||
return
|
||||
|
@ -171,7 +178,7 @@ def print_statuses(show_expired=False):
|
|||
major=python_version[0],
|
||||
minor=python_version[1],
|
||||
remaining=-days_left,
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import site
|
||||
import sys
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import shutil
|
||||
import os
|
||||
import time
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import libs
|
||||
|
||||
__all__ = ['completed']
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# coding=utf-8
|
||||
"""A synchronous implementation of the Deluge RPC protocol
|
||||
based on gevent-deluge by Christopher Rosell.
|
||||
|
||||
"""
|
||||
A synchronous implementation of the Deluge RPC protocol.
|
||||
|
||||
Based on gevent-deluge by Christopher Rosell:
|
||||
https://github.com/chrippa/gevent-deluge
|
||||
|
||||
Example usage:
|
||||
|
@ -15,9 +16,16 @@ Example usage:
|
|||
download_location = client.core.get_config_value("download_location").get()
|
||||
"""
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
from .exceptions import DelugeRPCError
|
||||
|
||||
|
||||
__title__ = "synchronous-deluge"
|
||||
__version__ = "0.1"
|
||||
__author__ = "Christian Dale"
|
||||
__title__ = 'synchronous-deluge'
|
||||
__version__ = '0.1'
|
||||
__author__ = 'Christian Dale'
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import os
|
||||
import platform
|
||||
from collections import defaultdict
|
||||
|
@ -9,7 +17,7 @@ from .exceptions import DelugeRPCError
|
|||
from .protocol import DelugeRPCRequest, DelugeRPCResponse
|
||||
from .transfer import DelugeTransfer
|
||||
|
||||
__all__ = ["DelugeClient"]
|
||||
__all__ = ['DelugeClient']
|
||||
|
||||
RPC_RESPONSE = 1
|
||||
RPC_ERROR = 2
|
||||
|
@ -18,41 +26,41 @@ RPC_EVENT = 3
|
|||
|
||||
class DelugeClient(object):
|
||||
def __init__(self):
|
||||
"""A deluge client session."""
|
||||
"""Create a deluge client session."""
|
||||
self.transfer = DelugeTransfer()
|
||||
self.modules = []
|
||||
self._request_counter = 0
|
||||
|
||||
def _get_local_auth(self):
|
||||
username = password = ""
|
||||
username = password = ''
|
||||
if platform.system() in ('Windows', 'Microsoft'):
|
||||
app_data_path = os.environ.get("APPDATA")
|
||||
app_data_path = os.environ.get('APPDATA')
|
||||
if not app_data_path:
|
||||
from six.moves import winreg
|
||||
hkey = winreg.OpenKey(
|
||||
winreg.HKEY_CURRENT_USER,
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
|
||||
'Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders',
|
||||
)
|
||||
app_data_reg = winreg.QueryValueEx(hkey, "AppData")
|
||||
app_data_reg = winreg.QueryValueEx(hkey, 'AppData')
|
||||
app_data_path = app_data_reg[0]
|
||||
winreg.CloseKey(hkey)
|
||||
|
||||
auth_file = os.path.join(app_data_path, "deluge", "auth")
|
||||
auth_file = os.path.join(app_data_path, 'deluge', 'auth')
|
||||
else:
|
||||
from xdg.BaseDirectory import save_config_path
|
||||
try:
|
||||
auth_file = os.path.join(save_config_path("deluge"), "auth")
|
||||
auth_file = os.path.join(save_config_path('deluge'), 'auth')
|
||||
except OSError:
|
||||
return username, password
|
||||
|
||||
if os.path.exists(auth_file):
|
||||
for line in open(auth_file):
|
||||
if line.startswith("#"):
|
||||
if line.startswith('#'):
|
||||
# This is a comment line
|
||||
continue
|
||||
line = line.strip()
|
||||
try:
|
||||
lsplit = line.split(":")
|
||||
lsplit = line.split(':')
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
|
@ -63,13 +71,13 @@ class DelugeClient(object):
|
|||
else:
|
||||
continue
|
||||
|
||||
if username == "localclient":
|
||||
if username == 'localclient':
|
||||
return username, password
|
||||
|
||||
return "", ""
|
||||
return '', ''
|
||||
|
||||
def _create_module_method(self, module, method):
|
||||
fullname = "{0}.{1}".format(module, method)
|
||||
fullname = '{0}.{1}'.format(module, method)
|
||||
|
||||
def func(obj, *args, **kwargs):
|
||||
return self.remote_call(fullname, *args, **kwargs)
|
||||
|
@ -80,18 +88,18 @@ class DelugeClient(object):
|
|||
|
||||
def _introspect(self):
|
||||
def splitter(value):
|
||||
return value.split(".")
|
||||
return value.split('.')
|
||||
|
||||
self.modules = []
|
||||
|
||||
methods = self.remote_call("daemon.get_method_list").get()
|
||||
methods = self.remote_call('daemon.get_method_list').get()
|
||||
methodmap = defaultdict(dict)
|
||||
|
||||
for module, method in imap(splitter, methods):
|
||||
methodmap[module][method] = self._create_module_method(module, method)
|
||||
|
||||
for module, methods in methodmap.items():
|
||||
clsname = "DelugeModule{0}".format(module.capitalize())
|
||||
clsname = 'DelugeModule{0}'.format(module.capitalize())
|
||||
cls = type(clsname, (), methods)
|
||||
setattr(self, module, cls())
|
||||
self.modules.append(module)
|
||||
|
@ -133,24 +141,23 @@ class DelugeClient(object):
|
|||
self._request_counter += 1
|
||||
return response
|
||||
|
||||
def connect(self, host="127.0.0.1", port=58846, username="", password=""):
|
||||
"""Connects to a daemon process.
|
||||
def connect(self, host='127.0.0.1', port=58846, username='', password=''):
|
||||
"""Connect to a daemon process.
|
||||
|
||||
:param host: str, the hostname of the daemon
|
||||
:param port: int, the port of the daemon
|
||||
:param username: str, the username to login with
|
||||
:param password: str, the password to login with
|
||||
"""
|
||||
|
||||
# Connect transport
|
||||
self.transfer.connect((host, port))
|
||||
|
||||
# Attempt to fetch local auth info if needed
|
||||
if not username and host in ("127.0.0.1", "localhost"):
|
||||
if not username and host in ('127.0.0.1', 'localhost'):
|
||||
username, password = self._get_local_auth()
|
||||
|
||||
# Authenticate
|
||||
self.remote_call("daemon.login", username, password).get()
|
||||
self.remote_call('daemon.login', username, password).get()
|
||||
|
||||
# Introspect available methods
|
||||
self._introspect()
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
|
||||
class DelugeRPCError(Exception):
|
||||
def __init__(self, name, msg, traceback):
|
||||
|
@ -8,4 +15,4 @@ class DelugeRPCError(Exception):
|
|||
self.traceback = traceback
|
||||
|
||||
def __str__(self):
|
||||
return "{0}: {1}: {2}".format(self.__class__.__name__, self.name, self.msg)
|
||||
return '{0}: {1}: {2}'.format(self.__class__.__name__, self.name, self.msg)
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
|
||||
class DelugeRPCRequest(object):
|
||||
def __init__(self, request_id, method, *args, **kwargs):
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
# coding=utf-8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import socket
|
||||
import ssl
|
||||
import struct
|
||||
|
@ -6,7 +14,7 @@ import zlib
|
|||
|
||||
import rencode
|
||||
|
||||
__all__ = ["DelugeTransfer"]
|
||||
__all__ = ['DelugeTransfer']
|
||||
|
||||
|
||||
class DelugeTransfer(object):
|
||||
|
@ -33,7 +41,7 @@ class DelugeTransfer(object):
|
|||
payload = zlib.compress(rencode.dumps(data))
|
||||
self.conn.sendall(payload)
|
||||
|
||||
buf = b""
|
||||
buf = b''
|
||||
|
||||
while True:
|
||||
data = self.conn.recv(1024)
|
||||
|
|
|
@ -1,4 +1,12 @@
|
|||
# coding=utf8
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import re
|
||||
|
||||
from six import StringIO, iteritems
|
||||
|
@ -31,8 +39,7 @@ class UTorrentClient(object):
|
|||
# TODO refresh token, when necessary
|
||||
|
||||
def _make_opener(self, realm, base_url, username, password):
|
||||
"""uTorrent API need HTTP Basic Auth and cookie support for token verify."""
|
||||
|
||||
"""HTTP Basic Auth and cookie support for token verification."""
|
||||
auth_handler = HTTPBasicAuthHandler()
|
||||
auth_handler.add_password(realm=realm,
|
||||
uri=base_url,
|
||||
|
@ -61,25 +68,25 @@ class UTorrentClient(object):
|
|||
return self._action(params)
|
||||
|
||||
def start(self, *hashes):
|
||||
params = [('action', 'start'), ]
|
||||
params = [('action', 'start')]
|
||||
for cur_hash in hashes:
|
||||
params.append(('hash', cur_hash))
|
||||
return self._action(params)
|
||||
|
||||
def stop(self, *hashes):
|
||||
params = [('action', 'stop'), ]
|
||||
params = [('action', 'stop')]
|
||||
for cur_hash in hashes:
|
||||
params.append(('hash', cur_hash))
|
||||
return self._action(params)
|
||||
|
||||
def pause(self, *hashes):
|
||||
params = [('action', 'pause'), ]
|
||||
params = [('action', 'pause')]
|
||||
for cur_hash in hashes:
|
||||
params.append(('hash', cur_hash))
|
||||
return self._action(params)
|
||||
|
||||
def forcestart(self, *hashes):
|
||||
params = [('action', 'forcestart'), ]
|
||||
params = [('action', 'forcestart')]
|
||||
for cur_hash in hashes:
|
||||
params.append(('hash', cur_hash))
|
||||
return self._action(params)
|
||||
|
@ -95,8 +102,8 @@ class UTorrentClient(object):
|
|||
def setprops(self, cur_hash, **kvpairs):
|
||||
params = [('action', 'setprops'), ('hash', cur_hash)]
|
||||
for k, v in iteritems(kvpairs):
|
||||
params.append(("s", k))
|
||||
params.append(("v", v))
|
||||
params.append(('s', k))
|
||||
params.append(('v', v))
|
||||
|
||||
return self._action(params)
|
||||
|
||||
|
@ -125,13 +132,13 @@ class UTorrentClient(object):
|
|||
self._action(params)
|
||||
|
||||
def remove(self, *hashes):
|
||||
params = [('action', 'remove'), ]
|
||||
params = [('action', 'remove')]
|
||||
for cur_hash in hashes:
|
||||
params.append(('hash', cur_hash))
|
||||
return self._action(params)
|
||||
|
||||
def removedata(self, *hashes):
|
||||
params = [('action', 'removedata'), ]
|
||||
params = [('action', 'removedata')]
|
||||
for cur_hash in hashes:
|
||||
params.append(('hash', cur_hash))
|
||||
return self._action(params)
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
# coding=utf-8
|
||||
# code copied from http://www.doughellmann.com/PyMOTW/urllib2/
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import itertools
|
||||
import mimetypes
|
||||
from email.generator import _make_boundary as choose_boundary
|
||||
|
@ -36,7 +43,7 @@ class MultiPartForm(object):
|
|||
# Build a list of lists, each containing "lines" of the
|
||||
# request. Each part is separated by a boundary string.
|
||||
# Once the list is built, return a string where each
|
||||
# line is separated by '\r\n'.
|
||||
# line is separated by '\r\n'.
|
||||
parts = []
|
||||
part_boundary = '--' + self.boundary
|
||||
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## Extensions
|
||||
|
||||
|
@ -134,7 +134,7 @@
|
|||
|
||||
# subLanguages.
|
||||
#
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
#subLanguages=eng,spa,fra
|
||||
|
||||
# Transcode (0, 1).
|
||||
|
@ -216,7 +216,7 @@
|
|||
# ffmpeg output settings.
|
||||
#outputVideoExtension=.mp4
|
||||
#outputVideoCodec=libx264
|
||||
#VideoCodecAllow=
|
||||
#VideoCodecAllow=
|
||||
#outputVideoResolution=720:-1
|
||||
#outputVideoPreset=medium
|
||||
#outputVideoFramerate=24
|
||||
|
@ -227,7 +227,7 @@
|
|||
#outputAudioBitrate=640k
|
||||
#outputQualityPercent=
|
||||
#outputAudioTrack2Codec=libfaac
|
||||
#AudioCodec2Allow=
|
||||
#AudioCodec2Allow=
|
||||
#outputAudioTrack2Channels=2
|
||||
#outputAudioTrack2Bitrate=160k
|
||||
#outputAudioOtherCodec=libmp3lame
|
||||
|
@ -255,6 +255,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -100,6 +100,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## WakeOnLan
|
||||
|
||||
|
@ -122,6 +122,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -59,6 +59,19 @@
|
|||
# set this to where your LazyLibrarian completed downloads are.
|
||||
#llwatch_dir=
|
||||
|
||||
# LazyLibrarian and NZBGet are a different system (0, 1).
|
||||
#
|
||||
# Enable to replace local path with the path as per the mountPoints below.
|
||||
#llremote_path=0
|
||||
|
||||
## Network
|
||||
|
||||
# Network Mount Points (Needed for remote path above)
|
||||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
|
||||
## Posix
|
||||
|
||||
# Niceness for external tasks Extractor and Transcoder.
|
||||
|
@ -95,6 +108,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## Extensions
|
||||
|
||||
|
@ -119,7 +119,7 @@
|
|||
|
||||
# subLanguages.
|
||||
#
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
#subLanguages = eng,spa,fra
|
||||
|
||||
# Transcode (0, 1).
|
||||
|
@ -145,7 +145,7 @@
|
|||
# outputVideoPath.
|
||||
#
|
||||
# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable.
|
||||
#outputVideoPath =
|
||||
#outputVideoPath =
|
||||
|
||||
# processOutput (0,1).
|
||||
#
|
||||
|
@ -201,20 +201,20 @@
|
|||
# ffmpeg output settings.
|
||||
#outputVideoExtension=.mp4
|
||||
#outputVideoCodec=libx264
|
||||
#VideoCodecAllow =
|
||||
#VideoCodecAllow =
|
||||
#outputVideoResolution=720:-1
|
||||
#outputVideoPreset=medium
|
||||
#outputVideoFramerate=24
|
||||
#outputVideoBitrate=800k
|
||||
#outputAudioCodec=libmp3lame
|
||||
#AudioCodecAllow =
|
||||
#AudioCodecAllow =
|
||||
#outputAudioBitrate=128k
|
||||
#outputQualityPercent = 0
|
||||
#outputAudioTrack2Codec = libfaac
|
||||
#AudioCodec2Allow =
|
||||
#AudioCodec2Allow =
|
||||
#outputAudioTrack2Bitrate = 128k
|
||||
#outputAudioOtherCodec = libmp3lame
|
||||
#AudioOtherCodecAllow =
|
||||
#AudioOtherCodecAllow =
|
||||
#outputAudioOtherBitrate = 128k
|
||||
#outputSubtitleCodec =
|
||||
|
||||
|
@ -237,6 +237,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -444,13 +444,18 @@
|
|||
# set this to where your LazyLibrarian completed downloads are.
|
||||
#llwatch_dir=
|
||||
|
||||
# LazyLibrarian and NZBGet are a different system (0, 1).
|
||||
#
|
||||
# Enable to replace local path with the path as per the mountPoints below.
|
||||
#llremote_path=0
|
||||
|
||||
## Network
|
||||
|
||||
# Network Mount Points (Needed for remote path above)
|
||||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## Extensions
|
||||
|
||||
|
@ -485,7 +490,7 @@
|
|||
|
||||
# subLanguages.
|
||||
#
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
#subLanguages=eng,spa,fra
|
||||
|
||||
# Transcode (0, 1).
|
||||
|
@ -567,7 +572,7 @@
|
|||
# ffmpeg output settings.
|
||||
#outputVideoExtension=.mp4
|
||||
#outputVideoCodec=libx264
|
||||
#VideoCodecAllow=
|
||||
#VideoCodecAllow=
|
||||
#outputVideoResolution=720:-1
|
||||
#outputVideoPreset=medium
|
||||
#outputVideoFramerate=24
|
||||
|
@ -578,7 +583,7 @@
|
|||
#outputAudioBitrate=640k
|
||||
#outputQualityPercent=
|
||||
#outputAudioTrack2Codec=libfaac
|
||||
#AudioCodec2Allow=
|
||||
#AudioCodec2Allow=
|
||||
#outputAudioTrack2Channels=2
|
||||
#outputAudioTrack2Bitrate=160k
|
||||
#outputAudioOtherCodec=libmp3lame
|
||||
|
@ -655,18 +660,23 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import eol
|
||||
eol.check()
|
||||
|
||||
import cleanup
|
||||
cleanup.clean(cleanup.FOLDER_STRUCTURE)
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
|
||||
import eol
|
||||
import cleanup
|
||||
|
||||
eol.check()
|
||||
cleanup.clean(cleanup.FOLDER_STRUCTURE)
|
||||
|
||||
import core
|
||||
from core import logger, main_db
|
||||
from core.auto_process import comics, games, movies, music, tv, books
|
||||
|
@ -777,11 +787,11 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d
|
|||
)
|
||||
except Exception:
|
||||
logger.error('Remote Path {0} is not valid for {1}:{2} Please set this to either 0 to disable or 1 to enable!'.format(
|
||||
core.get('remote_path'), section_name, input_category))
|
||||
cfg.get('remote_path'), section_name, input_category))
|
||||
|
||||
input_name, input_directory = convert_to_ascii(input_name, input_directory)
|
||||
|
||||
if extract == 1:
|
||||
if extract == 1 and not (status > 0 and core.NOEXTRACTFAILED):
|
||||
logger.debug('Checking for archives to extract in directory: {0}'.format(input_directory))
|
||||
extract_files(input_directory)
|
||||
|
||||
|
|
|
@ -92,7 +92,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## WakeOnLan
|
||||
|
||||
|
@ -113,6 +113,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## Extensions
|
||||
|
||||
|
@ -124,7 +124,7 @@
|
|||
|
||||
# subLanguages.
|
||||
#
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
#subLanguages = eng,spa,fra
|
||||
|
||||
# Transcode (0, 1).
|
||||
|
@ -150,7 +150,7 @@
|
|||
# outputVideoPath.
|
||||
#
|
||||
# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable.
|
||||
#outputVideoPath =
|
||||
#outputVideoPath =
|
||||
|
||||
# processOutput (0,1).
|
||||
#
|
||||
|
@ -206,20 +206,20 @@
|
|||
# ffmpeg output settings.
|
||||
#outputVideoExtension=.mp4
|
||||
#outputVideoCodec=libx264
|
||||
#VideoCodecAllow =
|
||||
#VideoCodecAllow =
|
||||
#outputVideoResolution=720:-1
|
||||
#outputVideoPreset=medium
|
||||
#outputVideoFramerate=24
|
||||
#outputVideoBitrate=800k
|
||||
#outputAudioCodec=libmp3lame
|
||||
#AudioCodecAllow =
|
||||
#AudioCodecAllow =
|
||||
#outputAudioBitrate=128k
|
||||
#outputQualityPercent = 0
|
||||
#outputAudioTrack2Codec = libfaac
|
||||
#AudioCodec2Allow =
|
||||
#AudioCodec2Allow =
|
||||
#outputAudioTrack2Bitrate = 128k
|
||||
#outputAudioOtherCodec = libmp3lame
|
||||
#AudioOtherCodecAllow =
|
||||
#AudioOtherCodecAllow =
|
||||
#outputAudioOtherBitrate = 128k
|
||||
#outputSubtitleCodec =
|
||||
|
||||
|
@ -242,6 +242,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -94,7 +94,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## Extensions
|
||||
|
||||
|
@ -129,7 +129,7 @@
|
|||
|
||||
# subLanguages.
|
||||
#
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
#subLanguages = eng,spa,fra
|
||||
|
||||
# Transcode (0, 1).
|
||||
|
@ -155,7 +155,7 @@
|
|||
# outputVideoPath.
|
||||
#
|
||||
# outputVideoPath. Set path you want transcoded videos moved to. Leave blank to disable.
|
||||
#outputVideoPath =
|
||||
#outputVideoPath =
|
||||
|
||||
# processOutput (0,1).
|
||||
#
|
||||
|
@ -211,20 +211,20 @@
|
|||
# ffmpeg output settings.
|
||||
#outputVideoExtension=.mp4
|
||||
#outputVideoCodec=libx264
|
||||
#VideoCodecAllow =
|
||||
#VideoCodecAllow =
|
||||
#outputVideoResolution=720:-1
|
||||
#outputVideoPreset=medium
|
||||
#outputVideoFramerate=24
|
||||
#outputVideoBitrate=800k
|
||||
#outputAudioCodec=libmp3lame
|
||||
#AudioCodecAllow =
|
||||
#AudioCodecAllow =
|
||||
#outputAudioBitrate=128k
|
||||
#outputQualityPercent = 0
|
||||
#outputAudioTrack2Codec = libfaac
|
||||
#AudioCodec2Allow =
|
||||
#AudioCodec2Allow =
|
||||
#outputAudioTrack2Bitrate = 128k
|
||||
#outputAudioOtherCodec = libmp3lame
|
||||
#AudioOtherCodecAllow =
|
||||
#AudioOtherCodecAllow =
|
||||
#outputAudioOtherBitrate = 128k
|
||||
#outputSubtitleCodec =
|
||||
|
||||
|
@ -247,6 +247,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
#
|
||||
# Enter Mount points as LocalPath,RemotePath and separate each pair with '|'
|
||||
# e.g. mountPoints=/volume1/Public/,E:\|/volume2/share/,\\NAS\
|
||||
#mountPoints=
|
||||
#mountPoints=
|
||||
|
||||
## Extensions
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
|||
|
||||
# subLanguages.
|
||||
#
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
# subLanguages. create a list of languages in the order you want them in your subtitles.
|
||||
#subLanguages=eng,spa,fra
|
||||
|
||||
# Transcode (0, 1).
|
||||
|
@ -217,7 +217,7 @@
|
|||
# ffmpeg output settings.
|
||||
#outputVideoExtension=.mp4
|
||||
#outputVideoCodec=libx264
|
||||
#VideoCodecAllow=
|
||||
#VideoCodecAllow=
|
||||
#outputVideoResolution=720:-1
|
||||
#outputVideoPreset=medium
|
||||
#outputVideoFramerate=24
|
||||
|
@ -228,7 +228,7 @@
|
|||
#outputAudioBitrate=640k
|
||||
#outputQualityPercent=
|
||||
#outputAudioTrack2Codec=libfaac
|
||||
#AudioCodec2Allow=
|
||||
#AudioCodec2Allow=
|
||||
#outputAudioTrack2Channels=2
|
||||
#outputAudioTrack2Bitrate=160k
|
||||
#outputAudioOtherCodec=libmp3lame
|
||||
|
@ -256,6 +256,13 @@
|
|||
### NZBGET POST-PROCESSING SCRIPT ###
|
||||
##############################################################################
|
||||
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
import nzbToMedia
|
||||
|
|
25
setup.py
25
setup.py
|
@ -1,6 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- encoding: utf-8 -*-
|
||||
from __future__ import absolute_import, print_function
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import io
|
||||
import os.path
|
||||
|
@ -11,7 +16,7 @@ from setuptools import setup
|
|||
def read(*names, **kwargs):
|
||||
with io.open(
|
||||
os.path.join(os.path.dirname(__file__), *names),
|
||||
encoding=kwargs.get('encoding', 'utf8')
|
||||
encoding=kwargs.get('encoding', 'utf8'),
|
||||
) as fh:
|
||||
return fh.read()
|
||||
|
||||
|
@ -21,21 +26,21 @@ setup(
|
|||
version='12.0.10',
|
||||
license='GPLv3',
|
||||
description='Efficient on demand post processing',
|
||||
long_description="""
|
||||
long_description="""
|
||||
nzbToMedia
|
||||
==========
|
||||
|
||||
|
||||
Efficient on demand post processing
|
||||
-----------------------------------
|
||||
|
||||
|
||||
A PVR app needs to know when a download is ready for post-processing. There are two methods:
|
||||
|
||||
|
||||
1. On-demand post-processing script (e.g. sabToSickBeard.py or nzbToMedia.py): A script in the downloader runs once at the end of the download job and notifies the PVR app that the download is complete.
|
||||
|
||||
|
||||
2. Continuous folder scanning: The PVR app frequently polls download folder(s) for completed downloads.
|
||||
|
||||
|
||||
On-demand is superior, for several reasons:
|
||||
|
||||
|
||||
1. The PVR app is notified only once, exactly when the download is ready for post-processing
|
||||
2. The PVR app does not have to wait for the next poll interval before it starts processing
|
||||
3. Continuous polling is not as efficient and is more stressful on low performance hardware
|
||||
|
@ -46,7 +51,7 @@ setup(
|
|||
8. On-demand scripts can be tweaked to allow for delays with slow hardware
|
||||
|
||||
nzbToMedia is an on-demand post-processing script and was created out of a demand for more efficient post-processing on low-performance hardware. Many features have been added so higher performance hardware can benefit too.
|
||||
|
||||
|
||||
Many issues that users have with folder scanning can be fixed by switching to on-demand. A whole class of support issues can be eliminated by using nzbToMedia.
|
||||
""",
|
||||
author='Clinton Hall',
|
||||
|
|
|
@ -1 +1,8 @@
|
|||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
__author__ = 'Justin'
|
||||
|
|
|
@ -1,48 +1,52 @@
|
|||
#! /usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import core
|
||||
|
||||
|
||||
def test_eol():
|
||||
import eol
|
||||
eol.check()
|
||||
|
||||
|
||||
def test_cleanup():
|
||||
import cleanup
|
||||
cleanup.clean(cleanup.FOLDER_STRUCTURE)
|
||||
|
||||
|
||||
def test_import_core():
|
||||
import core
|
||||
from core import logger, main_db
|
||||
pass
|
||||
|
||||
|
||||
def test_import_core_auto_process():
|
||||
from core.auto_process import comics, games, movies, music, tv
|
||||
from core.auto_process.common import ProcessResult
|
||||
pass
|
||||
|
||||
|
||||
def test_import_core_plugins():
|
||||
from core.plugins.downloaders.nzb.utils import get_nzoid
|
||||
from core.plugins.plex import plex_update
|
||||
pass
|
||||
|
||||
|
||||
def test_import_core_user_scripts():
|
||||
from core.user_scripts import external_script
|
||||
pass
|
||||
|
||||
|
||||
def test_import_six():
|
||||
from six import text_type
|
||||
pass
|
||||
|
||||
|
||||
def test_import_core_utils():
|
||||
from core.utils import (
|
||||
char_replace, clean_dir, convert_to_ascii,
|
||||
extract_files, get_dirs, get_download_info,
|
||||
update_download_info_status, replace_links,
|
||||
)
|
||||
pass
|
||||
|
||||
import core
|
||||
from core import logger, main_db
|
||||
|
||||
def test_initial():
|
||||
core.initialize()
|
||||
del core.MYAPP
|
||||
|
||||
|
||||
def test_core_parameters():
|
||||
assert core.CHECK_MEDIA == 1
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
#! /usr/bin/env python
|
||||
from __future__ import print_function
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import time
|
||||
import requests
|
||||
from __future__ import (
|
||||
absolute_import,
|
||||
division,
|
||||
print_function,
|
||||
unicode_literals,
|
||||
)
|
||||
|
||||
import core
|
||||
from core import logger, transcoder
|
||||
from core import transcoder
|
||||
|
||||
|
||||
def test_transcoder_check():
|
||||
assert transcoder.is_video_good(core.TEST_FILE, 0) == True
|
||||
assert transcoder.is_video_good(core.TEST_FILE, 0) is True
|
||||
|
|
146
tox.ini
Normal file
146
tox.ini
Normal file
|
@ -0,0 +1,146 @@
|
|||
; a generative tox configuration, see: https://tox.readthedocs.io/en/latest/config.html#generative-envlist
|
||||
|
||||
[tox]
|
||||
envlist =
|
||||
clean,
|
||||
check,
|
||||
{py27, py35, py36, py37},
|
||||
report
|
||||
|
||||
[testenv]
|
||||
basepython =
|
||||
py27: {env:TOXPYTHON:python2.7}
|
||||
py35: {env:TOXPYTHON:python3.5}
|
||||
py36: {env:TOXPYTHON:python3.6}
|
||||
py37: {env:TOXPYTHON:python3.7}
|
||||
{clean,check,report,codecov}: {env:TOXPYTHON:python3}
|
||||
setenv =
|
||||
PYTHONPATH={toxinidir}/tests
|
||||
PYTHONUNBUFFERED=yes
|
||||
passenv =
|
||||
*
|
||||
usedevelop = false
|
||||
skip_install = true
|
||||
deps =
|
||||
pytest
|
||||
pytest-travis-fold
|
||||
pytest-cov
|
||||
pywin32 ; sys.platform == 'win32'
|
||||
commands =
|
||||
{posargs:pytest --cov --cov-report=term-missing tests}
|
||||
|
||||
[flake8]
|
||||
max-line-length = 79
|
||||
max-doc-length = 79
|
||||
verbose = 2
|
||||
statistics = True
|
||||
min-version = 2.7
|
||||
require-code = True
|
||||
exclude =
|
||||
.github/
|
||||
.tox/
|
||||
.pytest_cache/
|
||||
htmlcov/
|
||||
logs/
|
||||
libs/common
|
||||
libs/win
|
||||
libs/py2
|
||||
ignore =
|
||||
; -- flake8 --
|
||||
; E501 line too long
|
||||
; W505 doc line too long
|
||||
E501, W505
|
||||
|
||||
; -- flake8-docstrings --
|
||||
; D100 Missing docstring in public module
|
||||
; D101 Missing docstring in public class
|
||||
; D102 Missing docstring in public method
|
||||
; D103 Missing docstring in public function
|
||||
; D104 Missing docstring in public package
|
||||
; D105 Missing docstring in magic method
|
||||
; D107 Missing docstring in __init__
|
||||
; D200 One-line docstring should fit on one line with quotes
|
||||
; D202 No blank lines allowed after function docstring
|
||||
; D205 1 blank line required between summary line and description
|
||||
; D400 First line should end with a period
|
||||
; D401 First line should be in imperative mood
|
||||
; D402 First line should not be the function's "signature"
|
||||
D100, D101, D102, D103, D104, D105, D107
|
||||
|
||||
; -- flake8-future-import --
|
||||
; x = 1 for missing, 5 for present
|
||||
; FIx6 nested_scopes 2.2
|
||||
; FIx7 generators 2.3
|
||||
; FIx2 with_statement 2.6
|
||||
; FIx1 absolute_import 3.0
|
||||
; FIx0 division 3.0
|
||||
; FIx3 print_function 3.0
|
||||
; FIx4 unicode_literals 3.0
|
||||
; FIx5 generator_stop 3.7
|
||||
; ???? annotations 4.0
|
||||
; FI90 __future__ import does not exist
|
||||
FI50, FI51, FI53, FI54
|
||||
|
||||
per-file-ignores =
|
||||
; F401 imported but unused
|
||||
; E402 module level import not at top of file
|
||||
nzbTo*.py: E265, E266, E402
|
||||
TorrentToMedia.py: E402
|
||||
core/__init__.py: E402, F401
|
||||
core/utils/__init__.py: F401
|
||||
core/plugins/downloaders/configuration.py: F401
|
||||
core/plugins/downloaders/utils.py: F401
|
||||
libs/custom/synchronousdeluge/__init__.py: F401
|
||||
|
||||
[testenv:check]
|
||||
deps =
|
||||
flake8
|
||||
flake8-bugbear
|
||||
flake8-commas
|
||||
flake8-comprehensions
|
||||
flake8-docstrings
|
||||
flake8-future-import
|
||||
flake8-quotes
|
||||
skip_install = true
|
||||
commands =
|
||||
; ** PRIMARY TESTS **
|
||||
; Run flake8 tests (with plugins) using default test selections
|
||||
flake8
|
||||
; ** SELECTIVE TESTS **
|
||||
; Run flake8 tests (with plugins) for specific optional codes defined below
|
||||
; -- flake8 --
|
||||
; E123 closing bracket does not match indentation of opening bracket’s line
|
||||
; E226 missing whitespace around arithmetic operator
|
||||
; E241 multiple spaces after ‘,’
|
||||
; E242 tab after ‘,’
|
||||
; E704 multiple statements on one line
|
||||
; W504 line break after binary operator
|
||||
; W505 doc line too long
|
||||
; -- flake8-bugbear --
|
||||
; B902 Invalid first argument used for instance method.
|
||||
; B903 Data class should be immutable or use __slots__ to save memory.
|
||||
flake8 --select=B902,B903,E123,E226,E241,E242,E704,W504,W505
|
||||
|
||||
[coverage:run]
|
||||
omit =
|
||||
libs/*
|
||||
|
||||
[testenv:codecov]
|
||||
deps =
|
||||
codecov
|
||||
skip_install = true
|
||||
commands =
|
||||
coverage xml --ignore-errors
|
||||
codecov []
|
||||
|
||||
[testenv:report]
|
||||
deps = coverage
|
||||
skip_install = true
|
||||
commands =
|
||||
coverage report
|
||||
coverage html
|
||||
|
||||
[testenv:clean]
|
||||
commands = coverage erase
|
||||
skip_install = true
|
||||
deps = coverage
|
Loading…
Add table
Add a link
Reference in a new issue