Merge pull request #1439 from clinton-hall/quality/refactor

Major code refactoring
This commit is contained in:
Labrys of Knossos 2018-12-19 17:43:30 -05:00 committed by GitHub
commit aea6e12639
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 516 additions and 537 deletions

View file

@ -5,9 +5,9 @@ import os
import sys
import core
from core import logger, nzbToMediaDB
from core.nzbToMediaUserScript import external_script
from core.nzbToMediaUtil import char_replace, convert_to_ascii, plex_update, replace_links
from core import logger, main_db
from core.user_scripts import external_script
from core.utils import char_replace, convert_to_ascii, plex_update, replace_links
from six import text_type
@ -19,7 +19,7 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
if client_agent != 'manual' and not core.DOWNLOADINFO:
logger.debug('Adding TORRENT download info for directory {0} to database'.format(input_directory))
my_db = nzbToMediaDB.DBConnection()
my_db = main_db.DBConnection()
input_directory1 = input_directory
input_name1 = input_name
@ -237,14 +237,14 @@ def process_torrent(input_directory, input_name, input_category, input_hash, inp
elif section_name in ['SickBeard', 'NzbDrone', 'Sonarr']:
if input_hash:
input_hash = input_hash.upper()
result = core.TV().process_episode(section_name, output_destination, input_name,
status, client_agent, input_hash, input_category)
result = core.TV().process(section_name, output_destination, input_name,
status, client_agent, input_hash, input_category)
elif section_name in ['HeadPhones', 'Lidarr']:
result = core.Music().process(section_name, output_destination, input_name,
status, client_agent, input_category)
elif section_name == 'Mylar':
result = core.Comic().process_episode(section_name, output_destination, input_name,
status, client_agent, input_category)
result = core.Comic().process(section_name, output_destination, input_name,
status, client_agent, input_category)
elif section_name == 'Gamez':
result = core.Game().process(section_name, output_destination, input_name,
status, client_agent, input_category)

View file

@ -42,22 +42,15 @@ MYAPP = None
import six
from six.moves import reload_module
from core import logger, nzbToMediaDB, versionCheck
from core.autoProcess.autoProcessComics import Comic
from core.autoProcess.autoProcessGames import Game
from core.autoProcess.autoProcessMovie import Movie
from core.autoProcess.autoProcessMusic import Music
from core.autoProcess.autoProcessTV import TV
from core.databases import mainDB
from core.nzbToMediaConfig import config
from core.nzbToMediaUtil import (
from core import logger, main_db, version_check, databases, transcoder
from core.auto_process import Comic, Game, Movie, Music, TV
from core.configuration import config
from core.utils import (
RunningProcess, wake_up, category_search, clean_dir, clean_dir, copy_link,
create_torrent_class, extract_files, flatten, get_dirs, get_download_info,
list_media_files, make_dir, parse_args, pause_torrent, remove_torrent,
resume_torrent, remove_dir, remove_read_only, sanitize_name, update_download_info_status,
)
from core.transcoder import transcoder
# Client Agents
NZB_CLIENTS = ['sabnzbd', 'nzbget', 'manual']
@ -326,7 +319,7 @@ def initialize(section=None):
logger.info("{0}: {1}".format(item, os.environ[item]), "ENVIRONMENT")
# initialize the main SB database
nzbToMediaDB.upgrade_database(nzbToMediaDB.DBConnection(), mainDB.InitialSchema)
main_db.upgrade_database(main_db.DBConnection(), databases.InitialSchema)
# Set Version and GIT variables
NZBTOMEDIA_VERSION = '11.06'
@ -343,10 +336,10 @@ def initialize(section=None):
NOEXTRACTFAILED = int(CFG["General"]["no_extract_failed"])
# Check for updates via GitHUB
if versionCheck.CheckVersion().check_for_new_version():
if version_check.CheckVersion().check_for_new_version():
if AUTO_UPDATE == 1:
logger.info("Auto-Updating nzbToMedia, Please wait ...")
updated = versionCheck.CheckVersion().update()
updated = version_check.CheckVersion().update()
if updated:
# restart nzbToMedia
try:
@ -852,7 +845,7 @@ def initialize(section=None):
def restart():
install_type = versionCheck.CheckVersion().install_type
install_type = version_check.CheckVersion().install_type
status = 0
popen_list = []

View file

@ -1 +0,0 @@
# coding=utf-8

View file

@ -0,0 +1,7 @@
# coding=utf-8
from core.auto_process.comics import Comic
from core.auto_process.games import Game
from core.auto_process.movies import Movie
from core.auto_process.music import Music
from core.auto_process.tv import TV

View file

@ -6,13 +6,13 @@ import requests
import core
from core import logger
from core.nzbToMediaUtil import convert_to_ascii, remote_dir, server_responding
from core.utils import convert_to_ascii, remote_dir, server_responding
requests.packages.urllib3.disable_warnings()
class Comic(object):
def process_episode(self, section, dir_name, input_name=None, status=0, client_agent='manual', input_category=None):
def process(self, section, dir_name, input_name=None, status=0, client_agent='manual', input_category=None):
apc_version = "2.04"
comicrn_version = "1.01"

View file

@ -7,7 +7,7 @@ import requests
import core
from core import logger
from core.nzbToMediaUtil import convert_to_ascii, server_responding
from core.utils import convert_to_ascii, server_responding
requests.packages.urllib3.disable_warnings()

View file

@ -7,144 +7,14 @@ import time
import requests
import core
from core import logger
from core.nzbToMediaSceneExceptions import process_all_exceptions
from core.nzbToMediaUtil import convert_to_ascii, find_download, find_imdbid, import_subs, list_media_files, remote_dir, report_nzb, remove_dir, server_responding
from core.transcoder import transcoder
from core import logger, transcoder
from core.scene_exceptions import process_all_exceptions
from core.utils import convert_to_ascii, find_download, find_imdbid, import_subs, list_media_files, remote_dir, remove_dir, report_nzb, server_responding
requests.packages.urllib3.disable_warnings()
class Movie(object):
def get_release(self, base_url, imdb_id=None, download_id=None, release_id=None):
results = {}
params = {}
# determine cmd and params to send to CouchPotato to get our results
section = 'movies'
cmd = "media.list"
if release_id or imdb_id:
section = 'media'
cmd = "media.get"
params['id'] = release_id or imdb_id
if not (release_id or imdb_id or download_id):
logger.debug("No information available to filter CP results")
return results
url = "{0}{1}".format(base_url, cmd)
logger.debug("Opening URL: {0} with PARAMS: {1}".format(url, params))
try:
r = requests.get(url, params=params, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL {0}".format(url))
return results
try:
result = r.json()
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("CouchPotato returned the following non-json data")
for line in r.iter_lines():
logger.error("{0}".format(line))
return results
if not result['success']:
if 'error' in result:
logger.error('{0}'.format(result['error']))
else:
logger.error("no media found for id {0}".format(params['id']))
return results
# Gather release info and return it back, no need to narrow results
if release_id:
try:
id = result[section]['_id']
results[id] = result[section]
return results
except:
pass
# Gather release info and proceed with trying to narrow results to one release choice
movies = result[section]
if not isinstance(movies, list):
movies = [movies]
for movie in movies:
if movie['status'] not in ['active', 'done']:
continue
releases = movie['releases']
if not releases:
continue
for release in releases:
try:
if release['status'] not in ['snatched', 'downloaded', 'done']:
continue
if download_id:
if download_id.lower() != release['download_info']['id'].lower():
continue
id = release['_id']
results[id] = release
results[id]['title'] = movie['title']
except:
continue
# 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():
try:
if x2["last_edit"] > x1["last_edit"]:
results.pop(id1)
except:
continue
# Search downloads on clients for a match to try and narrow our results down to 1
if len(results) > 1:
for id, x in results.items():
try:
if not find_download(str(x['download_info']['downloader']).lower(), x['download_info']['id']):
results.pop(id)
except:
continue
return results
def command_complete(self, url, params, headers, section):
try:
r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url), section)
return None
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 None
else:
try:
return r.json()['state']
except (ValueError, KeyError):
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("{0} did not return expected json data.".format(section), section)
return None
def completed_download_handling(self, url2, headers, section="MAIN"):
try:
r = requests.get(url2, params={}, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url2), section)
return False
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 False
else:
try:
return r.json().get("enableCompletedDownloadHandling", False)
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
return False
def process(self, section, dir_name, input_name=None, status=0, client_agent="manual", download_id="", input_category=None, failure_link=None):
cfg = dict(core.CFG[section][input_category])
@ -465,3 +335,132 @@ class Movie(object):
"{0} does not appear to have changed status after {1} minutes, Please check your logs.".format(input_name, wait_for),
section)
return [1, "{0}: Failed to post-process - No change in status".format(section)]
def command_complete(self, url, params, headers, section):
try:
r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url), section)
return None
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 None
else:
try:
return r.json()['state']
except (ValueError, KeyError):
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("{0} did not return expected json data.".format(section), section)
return None
def completed_download_handling(self, url2, headers, section="MAIN"):
try:
r = requests.get(url2, params={}, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url2), section)
return False
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 False
else:
try:
return r.json().get("enableCompletedDownloadHandling", False)
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
return False
def get_release(self, base_url, imdb_id=None, download_id=None, release_id=None):
results = {}
params = {}
# determine cmd and params to send to CouchPotato to get our results
section = 'movies'
cmd = "media.list"
if release_id or imdb_id:
section = 'media'
cmd = "media.get"
params['id'] = release_id or imdb_id
if not (release_id or imdb_id or download_id):
logger.debug("No information available to filter CP results")
return results
url = "{0}{1}".format(base_url, cmd)
logger.debug("Opening URL: {0} with PARAMS: {1}".format(url, params))
try:
r = requests.get(url, params=params, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL {0}".format(url))
return results
try:
result = r.json()
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("CouchPotato returned the following non-json data")
for line in r.iter_lines():
logger.error("{0}".format(line))
return results
if not result['success']:
if 'error' in result:
logger.error('{0}'.format(result['error']))
else:
logger.error("no media found for id {0}".format(params['id']))
return results
# Gather release info and return it back, no need to narrow results
if release_id:
try:
id = result[section]['_id']
results[id] = result[section]
return results
except:
pass
# Gather release info and proceed with trying to narrow results to one release choice
movies = result[section]
if not isinstance(movies, list):
movies = [movies]
for movie in movies:
if movie['status'] not in ['active', 'done']:
continue
releases = movie['releases']
if not releases:
continue
for release in releases:
try:
if release['status'] not in ['snatched', 'downloaded', 'done']:
continue
if download_id:
if download_id.lower() != release['download_info']['id'].lower():
continue
id = release['_id']
results[id] = release
results[id]['title'] = movie['title']
except:
continue
# 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():
try:
if x2["last_edit"] > x1["last_edit"]:
results.pop(id1)
except:
continue
# Search downloads on clients for a match to try and narrow our results down to 1
if len(results) > 1:
for id, x in results.items():
try:
if not find_download(str(x['download_info']['downloader']).lower(), x['download_info']['id']):
results.pop(id)
except:
continue
return results

View file

@ -8,94 +8,13 @@ import requests
import core
from core import logger
from core.nzbToMediaSceneExceptions import process_all_exceptions
from core.nzbToMediaUtil import convert_to_ascii, list_media_files, remote_dir, remove_dir, server_responding
from core.scene_exceptions import process_all_exceptions
from core.utils import convert_to_ascii, list_media_files, remote_dir, remove_dir, server_responding
requests.packages.urllib3.disable_warnings()
class Music(object):
def command_complete(self, url, params, headers, section):
try:
r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url), section)
return None
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 None
else:
try:
return r.json()['state']
except (ValueError, KeyError):
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("{0} did not return expected json data.".format(section), section)
return None
def get_status(self, url, apikey, dir_name):
logger.debug("Attempting to get current status for release:{0}".format(os.path.basename(dir_name)))
params = {
'apikey': apikey,
'cmd': "getHistory"
}
logger.debug("Opening URL: {0} with PARAMS: {1}".format(url, params))
try:
r = requests.get(url, params=params, verify=False, timeout=(30, 120))
except requests.RequestException:
logger.error("Unable to open URL")
return None
try:
result = r.json()
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
return None
for album in result:
if os.path.basename(dir_name) == album['FolderName']:
return album["Status"].lower()
def force_process(self, params, url, apikey, input_name, dir_name, section, wait_for):
release_status = self.get_status(url, apikey, dir_name)
if not release_status:
logger.error("Could not find a status for {0}, is it in the wanted list ?".format(input_name), section)
logger.debug("Opening URL: {0} with PARAMS: {1}".format(url, params), section)
try:
r = requests.get(url, params=params, verify=False, timeout=(30, 300))
except requests.ConnectionError:
logger.error("Unable to open URL {0}".format(url), section)
return [1, "{0}: Failed to post-process - Unable to connect to {1}".format(section, section)]
logger.debug("Result: {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 [1, "{0}: Failed to post-process - Server returned status {1}".format(section, r.status_code)]
elif r.text == "OK":
logger.postprocess("SUCCESS: Post-Processing started for {0} in folder {1} ...".format(input_name, dir_name), section)
else:
logger.error("FAILED: Post-Processing has NOT started for {0} in folder {1}. exiting!".format(input_name, dir_name), section)
return [1, "{0}: Failed to post-process - Returned log from {1} was not as expected.".format(section, section)]
# we will now wait for this album to be processed before returning to TorrentToMedia and unpausing.
timeout = time.time() + 60 * wait_for
while time.time() < timeout:
current_status = self.get_status(url, apikey, dir_name)
if current_status is not None and current_status != release_status: # Something has changed. CPS must have processed this movie.
logger.postprocess("SUCCESS: This release is now marked as status [{0}]".format(current_status), section)
return [0, "{0}: Successfully post-processed {1}".format(section, input_name)]
if not os.path.isdir(dir_name):
logger.postprocess("SUCCESS: The input directory {0} has been removed Processing must have finished.".format(dir_name), section)
return [0, "{0}: Successfully post-processed {1}".format(section, input_name)]
time.sleep(10 * wait_for)
# The status hasn't changed.
return [2, "no change"]
def process(self, section, dir_name, input_name=None, status=0, client_agent="manual", input_category=None):
status = int(status)
@ -236,4 +155,85 @@ class Music(object):
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)
remove_dir(dir_name)
return [1, "{0}: Failed to post-process. {1} does not support failed downloads".format(section, section)] # Return as failed to flag this in the downloader.
return [1, "{0}: Failed to post-process. {1} does not support failed downloads".format(section, section)] # Return as failed to flag this in the downloader.
def command_complete(self, url, params, headers, section):
try:
r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url), section)
return None
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 None
else:
try:
return r.json()['state']
except (ValueError, KeyError):
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("{0} did not return expected json data.".format(section), section)
return None
def get_status(self, url, apikey, dir_name):
logger.debug("Attempting to get current status for release:{0}".format(os.path.basename(dir_name)))
params = {
'apikey': apikey,
'cmd': "getHistory"
}
logger.debug("Opening URL: {0} with PARAMS: {1}".format(url, params))
try:
r = requests.get(url, params=params, verify=False, timeout=(30, 120))
except requests.RequestException:
logger.error("Unable to open URL")
return None
try:
result = r.json()
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
return None
for album in result:
if os.path.basename(dir_name) == album['FolderName']:
return album["Status"].lower()
def force_process(self, params, url, apikey, input_name, dir_name, section, wait_for):
release_status = self.get_status(url, apikey, dir_name)
if not release_status:
logger.error("Could not find a status for {0}, is it in the wanted list ?".format(input_name), section)
logger.debug("Opening URL: {0} with PARAMS: {1}".format(url, params), section)
try:
r = requests.get(url, params=params, verify=False, timeout=(30, 300))
except requests.ConnectionError:
logger.error("Unable to open URL {0}".format(url), section)
return [1, "{0}: Failed to post-process - Unable to connect to {1}".format(section, section)]
logger.debug("Result: {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 [1, "{0}: Failed to post-process - Server returned status {1}".format(section, r.status_code)]
elif r.text == "OK":
logger.postprocess("SUCCESS: Post-Processing started for {0} in folder {1} ...".format(input_name, dir_name), section)
else:
logger.error("FAILED: Post-Processing has NOT started for {0} in folder {1}. exiting!".format(input_name, dir_name), section)
return [1, "{0}: Failed to post-process - Returned log from {1} was not as expected.".format(section, section)]
# we will now wait for this album to be processed before returning to TorrentToMedia and unpausing.
timeout = time.time() + 60 * wait_for
while time.time() < timeout:
current_status = self.get_status(url, apikey, dir_name)
if current_status is not None and current_status != release_status: # Something has changed. CPS must have processed this movie.
logger.postprocess("SUCCESS: This release is now marked as status [{0}]".format(current_status), section)
return [0, "{0}: Successfully post-processed {1}".format(section, input_name)]
if not os.path.isdir(dir_name):
logger.postprocess("SUCCESS: The input directory {0} has been removed Processing must have finished.".format(dir_name), section)
return [0, "{0}: Successfully post-processed {1}".format(section, input_name)]
time.sleep(10 * wait_for)
# The status hasn't changed.
return [2, "no change"]

View file

@ -9,50 +9,16 @@ import time
import requests
import core
from core import logger
from core.nzbToMediaAutoFork import auto_fork
from core.nzbToMediaSceneExceptions import process_all_exceptions
from core.nzbToMediaUtil import convert_to_ascii, flatten, import_subs, list_media_files, remote_dir, report_nzb, remove_dir, server_responding
from core.transcoder import transcoder
from core import logger, transcoder
from core.forks import auto_fork
from core.scene_exceptions import process_all_exceptions
from core.utils import convert_to_ascii, flatten, import_subs, list_media_files, remote_dir, remove_dir, report_nzb, server_responding
requests.packages.urllib3.disable_warnings()
class TV(object):
def command_complete(self, url, params, headers, section):
try:
r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url), section)
return None
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 None
else:
try:
return r.json()['state']
except (ValueError, KeyError):
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("{0} did not return expected json data.".format(section), section)
return None
def completed_download_handling(self, url2, headers, section="MAIN"):
try:
r = requests.get(url2, params={}, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url2), section)
return False
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 False
else:
try:
return r.json().get("enableCompletedDownloadHandling", False)
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
return False
def process_episode(self, section, dir_name, input_name=None, failed=False, client_agent="manual", download_id=None, input_category=None, failure_link=None):
def process(self, section, dir_name, input_name=None, failed=False, client_agent="manual", download_id=None, input_category=None, failure_link=None):
cfg = dict(core.CFG[section][input_category])
@ -373,3 +339,36 @@ class TV(object):
return [1, "{0}: Failed to post-process {1}".format(section, input_name)]
else:
return [1, "{0}: Failed to post-process - Returned log from {1} was not as expected.".format(section, section)] # We did not receive Success confirmation.
def command_complete(self, url, params, headers, section):
try:
r = requests.get(url, params=params, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url), section)
return None
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 None
else:
try:
return r.json()['state']
except (ValueError, KeyError):
# ValueError catches simplejson's JSONDecodeError and json's ValueError
logger.error("{0} did not return expected json data.".format(section), section)
return None
def completed_download_handling(self, url2, headers, section="MAIN"):
try:
r = requests.get(url2, params={}, headers=headers, stream=True, verify=False, timeout=(30, 60))
except requests.ConnectionError:
logger.error("Unable to open URL: {0}".format(url2), section)
return False
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 False
else:
try:
return r.json().get("enableCompletedDownloadHandling", False)
except ValueError:
# ValueError catches simplejson's JSONDecodeError and json's ValueError
return False

View file

@ -1,7 +1,7 @@
# coding=utf-8
from core import logger, nzbToMediaDB
from core.nzbToMediaUtil import backup_versioned_file
from core import logger, main_db
from core.utils import backup_versioned_file
MIN_DB_VERSION = 1 # oldest db version we support migrating from
MAX_DB_VERSION = 2
@ -9,7 +9,7 @@ MAX_DB_VERSION = 2
def backup_database(version):
logger.info("Backing up database before upgrade")
if not backup_versioned_file(nzbToMediaDB.db_filename(), version):
if not backup_versioned_file(main_db.db_filename(), version):
logger.log_error_and_exit("Database backup failed, abort upgrading database")
else:
logger.info("Proceeding with upgrade")
@ -20,7 +20,7 @@ def backup_database(version):
# ======================
# Add new migrations at the bottom of the list; subclass the previous migration.
class InitialSchema(nzbToMediaDB.SchemaUpgrade):
class InitialSchema(main_db.SchemaUpgrade):
def test(self):
no_update = False
if self.has_table("db_version"):

View file

@ -1 +0,0 @@
# coding=utf-8

View file

@ -1 +1,181 @@
# coding=utf-8
import os
import platform
import shutil
import stat
import subprocess
from subprocess import Popen, call
from time import sleep
import core
def extract(file_path, output_destination):
success = 0
# Using Windows
if platform.system() == 'Windows':
if not os.path.exists(core.SEVENZIP):
core.logger.error("EXTRACTOR: Could not find 7-zip, Exiting")
return False
wscriptlocation = os.path.join(os.environ['WINDIR'], 'system32', 'wscript.exe')
invislocation = os.path.join(core.PROGRAM_DIR, 'core', 'extractor', 'bin', 'invisible.vbs')
cmd_7zip = [wscriptlocation, invislocation, str(core.SHOWEXTRACT), core.SEVENZIP, "x", "-y"]
ext_7zip = [".rar", ".zip", ".tar.gz", "tgz", ".tar.bz2", ".tbz", ".tar.lzma", ".tlz", ".7z", ".xz"]
extract_commands = dict.fromkeys(ext_7zip, cmd_7zip)
# Using unix
else:
required_cmds = ["unrar", "unzip", "tar", "unxz", "unlzma", "7zr", "bunzip2"]
# ## Possible future suport:
# gunzip: gz (cmd will delete original archive)
# ## the following do not extract to dest dir
# ".xz": ["xz", "-d --keep"],
# ".lzma": ["xz", "-d --format=lzma --keep"],
# ".bz2": ["bzip2", "-d --keep"],
extract_commands = {
".rar": ["unrar", "x", "-o+", "-y"],
".tar": ["tar", "-xf"],
".zip": ["unzip"],
".tar.gz": ["tar", "-xzf"], ".tgz": ["tar", "-xzf"],
".tar.bz2": ["tar", "-xjf"], ".tbz": ["tar", "-xjf"],
".tar.lzma": ["tar", "--lzma", "-xf"], ".tlz": ["tar", "--lzma", "-xf"],
".tar.xz": ["tar", "--xz", "-xf"], ".txz": ["tar", "--xz", "-xf"],
".7z": ["7zr", "x"],
}
# Test command exists and if not, remove
if not os.getenv('TR_TORRENT_DIR'):
devnull = open(os.devnull, 'w')
for cmd in required_cmds:
if call(['which', cmd], stdout=devnull,
stderr=devnull): # note, returns 0 if exists, or 1 if doesn't exist.
for k, v in extract_commands.items():
if cmd in v[0]:
if not call(["which", "7zr"], stdout=devnull, stderr=devnull): # we do have "7zr"
extract_commands[k] = ["7zr", "x", "-y"]
elif not call(["which", "7z"], stdout=devnull, stderr=devnull): # we do have "7z"
extract_commands[k] = ["7z", "x", "-y"]
elif not call(["which", "7za"], stdout=devnull, stderr=devnull): # we do have "7za"
extract_commands[k] = ["7za", "x", "-y"]
else:
core.logger.error("EXTRACTOR: {cmd} not found, "
"disabling support for {feature}".format
(cmd=cmd, feature=k))
del extract_commands[k]
devnull.close()
else:
core.logger.warning("EXTRACTOR: Cannot determine which tool to use when called from Transmission")
if not extract_commands:
core.logger.warning("EXTRACTOR: No archive extracting programs found, plugin will be disabled")
ext = os.path.splitext(file_path)
cmd = []
if ext[1] in (".gz", ".bz2", ".lzma"):
# Check if this is a tar
if os.path.splitext(ext[0])[1] == ".tar":
cmd = extract_commands[".tar{ext}".format(ext=ext[1])]
elif ext[1] in (".1", ".01", ".001") and os.path.splitext(ext[0])[1] in (".rar", ".zip", ".7z"):
cmd = extract_commands[os.path.splitext(ext[0])[1]]
elif ext[1] in (".cb7", ".cba", ".cbr", ".cbt", ".cbz"): # don't extract these comic book archives.
return False
else:
if ext[1] in extract_commands:
cmd = extract_commands[ext[1]]
else:
core.logger.debug("EXTRACTOR: Unknown file type: {ext}".format
(ext=ext[1]))
return False
# Create outputDestination folder
core.make_dir(output_destination)
if core.PASSWORDSFILE and os.path.isfile(os.path.normpath(core.PASSWORDSFILE)):
passwords = [line.strip() for line in open(os.path.normpath(core.PASSWORDSFILE))]
else:
passwords = []
core.logger.info("Extracting {file} to {destination}".format
(file=file_path, destination=output_destination))
core.logger.debug("Extracting {cmd} {file} {destination}".format
(cmd=cmd, file=file_path, destination=output_destination))
orig_files = []
orig_dirs = []
for dir, subdirs, files in os.walk(output_destination):
for subdir in subdirs:
orig_dirs.append(os.path.join(dir, subdir))
for file in files:
orig_files.append(os.path.join(dir, file))
pwd = os.getcwd() # Get our Present Working Directory
os.chdir(output_destination) # Not all unpack commands accept full paths, so just extract into this directory
devnull = open(os.devnull, 'w')
try: # now works same for nt and *nix
info = None
cmd.append(file_path) # add filePath to final cmd arg.
if platform.system() == 'Windows':
info = subprocess.STARTUPINFO()
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
cmd = core.NICENESS + cmd
cmd2 = cmd
cmd2.append("-p-") # don't prompt for password.
p = Popen(cmd2, stdout=devnull, stderr=devnull, startupinfo=info) # should extract files fine.
res = p.wait()
if res == 0: # Both Linux and Windows return 0 for successful.
core.logger.info("EXTRACTOR: Extraction was successful for {file} to {destination}".format
(file=file_path, destination=output_destination))
success = 1
elif len(passwords) > 0:
core.logger.info("EXTRACTOR: Attempting to extract with passwords")
for password in passwords:
if password == "": # if edited in windows or otherwise if blank lines.
continue
cmd2 = cmd
# append password here.
passcmd = "-p{pwd}".format(pwd=password)
cmd2.append(passcmd)
p = Popen(cmd2, stdout=devnull, stderr=devnull, startupinfo=info) # should extract files fine.
res = p.wait()
if (res >= 0 and platform == 'Windows') or res == 0:
core.logger.info("EXTRACTOR: Extraction was successful "
"for {file} to {destination} using password: {pwd}".format
(file=file_path, destination=output_destination, pwd=password))
success = 1
break
else:
continue
except:
core.logger.error("EXTRACTOR: Extraction failed for {file}. "
"Could not call command {cmd}".format
(file=file_path, cmd=cmd))
os.chdir(pwd)
return False
devnull.close()
os.chdir(pwd) # Go back to our Original Working Directory
if success:
# sleep to let files finish writing to disk
sleep(3)
perms = stat.S_IMODE(os.lstat(os.path.split(file_path)[0]).st_mode)
for dir, subdirs, files in os.walk(output_destination):
for subdir in subdirs:
if not os.path.join(dir, subdir) in orig_files:
try:
os.chmod(os.path.join(dir, subdir), perms)
except:
pass
for file in files:
if not os.path.join(dir, file) in orig_files:
try:
shutil.copymode(file_path, os.path.join(dir, file))
except:
pass
return True
else:
core.logger.error("EXTRACTOR: Extraction failed for {file}. "
"Result was {result}".format
(file=file_path, result=res))
return False

View file

@ -1,181 +0,0 @@
# coding=utf-8
import os
import platform
import shutil
import stat
import subprocess
from subprocess import Popen, call
from time import sleep
import core
def extract(file_path, output_destination):
success = 0
# Using Windows
if platform.system() == 'Windows':
if not os.path.exists(core.SEVENZIP):
core.logger.error("EXTRACTOR: Could not find 7-zip, Exiting")
return False
wscriptlocation = os.path.join(os.environ['WINDIR'], 'system32', 'wscript.exe')
invislocation = os.path.join(core.PROGRAM_DIR, 'core', 'extractor', 'bin', 'invisible.vbs')
cmd_7zip = [wscriptlocation, invislocation, str(core.SHOWEXTRACT), core.SEVENZIP, "x", "-y"]
ext_7zip = [".rar", ".zip", ".tar.gz", "tgz", ".tar.bz2", ".tbz", ".tar.lzma", ".tlz", ".7z", ".xz"]
extract_commands = dict.fromkeys(ext_7zip, cmd_7zip)
# Using unix
else:
required_cmds = ["unrar", "unzip", "tar", "unxz", "unlzma", "7zr", "bunzip2"]
# ## Possible future suport:
# gunzip: gz (cmd will delete original archive)
# ## the following do not extract to dest dir
# ".xz": ["xz", "-d --keep"],
# ".lzma": ["xz", "-d --format=lzma --keep"],
# ".bz2": ["bzip2", "-d --keep"],
extract_commands = {
".rar": ["unrar", "x", "-o+", "-y"],
".tar": ["tar", "-xf"],
".zip": ["unzip"],
".tar.gz": ["tar", "-xzf"], ".tgz": ["tar", "-xzf"],
".tar.bz2": ["tar", "-xjf"], ".tbz": ["tar", "-xjf"],
".tar.lzma": ["tar", "--lzma", "-xf"], ".tlz": ["tar", "--lzma", "-xf"],
".tar.xz": ["tar", "--xz", "-xf"], ".txz": ["tar", "--xz", "-xf"],
".7z": ["7zr", "x"],
}
# Test command exists and if not, remove
if not os.getenv('TR_TORRENT_DIR'):
devnull = open(os.devnull, 'w')
for cmd in required_cmds:
if call(['which', cmd], stdout=devnull,
stderr=devnull): # note, returns 0 if exists, or 1 if doesn't exist.
for k, v in extract_commands.items():
if cmd in v[0]:
if not call(["which", "7zr"], stdout=devnull, stderr=devnull): # we do have "7zr"
extract_commands[k] = ["7zr", "x", "-y"]
elif not call(["which", "7z"], stdout=devnull, stderr=devnull): # we do have "7z"
extract_commands[k] = ["7z", "x", "-y"]
elif not call(["which", "7za"], stdout=devnull, stderr=devnull): # we do have "7za"
extract_commands[k] = ["7za", "x", "-y"]
else:
core.logger.error("EXTRACTOR: {cmd} not found, "
"disabling support for {feature}".format
(cmd=cmd, feature=k))
del extract_commands[k]
devnull.close()
else:
core.logger.warning("EXTRACTOR: Cannot determine which tool to use when called from Transmission")
if not extract_commands:
core.logger.warning("EXTRACTOR: No archive extracting programs found, plugin will be disabled")
ext = os.path.splitext(file_path)
cmd = []
if ext[1] in (".gz", ".bz2", ".lzma"):
# Check if this is a tar
if os.path.splitext(ext[0])[1] == ".tar":
cmd = extract_commands[".tar{ext}".format(ext=ext[1])]
elif ext[1] in (".1", ".01", ".001") and os.path.splitext(ext[0])[1] in (".rar", ".zip", ".7z"):
cmd = extract_commands[os.path.splitext(ext[0])[1]]
elif ext[1] in (".cb7", ".cba", ".cbr", ".cbt", ".cbz"): # don't extract these comic book archives.
return False
else:
if ext[1] in extract_commands:
cmd = extract_commands[ext[1]]
else:
core.logger.debug("EXTRACTOR: Unknown file type: {ext}".format
(ext=ext[1]))
return False
# Create outputDestination folder
core.make_dir(output_destination)
if core.PASSWORDSFILE and os.path.isfile(os.path.normpath(core.PASSWORDSFILE)):
passwords = [line.strip() for line in open(os.path.normpath(core.PASSWORDSFILE))]
else:
passwords = []
core.logger.info("Extracting {file} to {destination}".format
(file=file_path, destination=output_destination))
core.logger.debug("Extracting {cmd} {file} {destination}".format
(cmd=cmd, file=file_path, destination=output_destination))
orig_files = []
orig_dirs = []
for dir, subdirs, files in os.walk(output_destination):
for subdir in subdirs:
orig_dirs.append(os.path.join(dir, subdir))
for file in files:
orig_files.append(os.path.join(dir, file))
pwd = os.getcwd() # Get our Present Working Directory
os.chdir(output_destination) # Not all unpack commands accept full paths, so just extract into this directory
devnull = open(os.devnull, 'w')
try: # now works same for nt and *nix
info = None
cmd.append(file_path) # add filePath to final cmd arg.
if platform.system() == 'Windows':
info = subprocess.STARTUPINFO()
info.dwFlags |= subprocess.STARTF_USESHOWWINDOW
else:
cmd = core.NICENESS + cmd
cmd2 = cmd
cmd2.append("-p-") # don't prompt for password.
p = Popen(cmd2, stdout=devnull, stderr=devnull, startupinfo=info) # should extract files fine.
res = p.wait()
if res == 0: # Both Linux and Windows return 0 for successful.
core.logger.info("EXTRACTOR: Extraction was successful for {file} to {destination}".format
(file=file_path, destination=output_destination))
success = 1
elif len(passwords) > 0:
core.logger.info("EXTRACTOR: Attempting to extract with passwords")
for password in passwords:
if password == "": # if edited in windows or otherwise if blank lines.
continue
cmd2 = cmd
# append password here.
passcmd = "-p{pwd}".format(pwd=password)
cmd2.append(passcmd)
p = Popen(cmd2, stdout=devnull, stderr=devnull, startupinfo=info) # should extract files fine.
res = p.wait()
if (res >= 0 and platform == 'Windows') or res == 0:
core.logger.info("EXTRACTOR: Extraction was successful "
"for {file} to {destination} using password: {pwd}".format
(file=file_path, destination=output_destination, pwd=password))
success = 1
break
else:
continue
except:
core.logger.error("EXTRACTOR: Extraction failed for {file}. "
"Could not call command {cmd}".format
(file=file_path, cmd=cmd))
os.chdir(pwd)
return False
devnull.close()
os.chdir(pwd) # Go back to our Original Working Directory
if success:
# sleep to let files finish writing to disk
sleep(3)
perms = stat.S_IMODE(os.lstat(os.path.split(file_path)[0]).st_mode)
for dir, subdirs, files in os.walk(output_destination):
for subdir in subdirs:
if not os.path.join(dir, subdir) in orig_files:
try:
os.chmod(os.path.join(dir, subdir), perms)
except:
pass
for file in files:
if not os.path.join(dir, file) in orig_files:
try:
shutil.copymode(file_path, os.path.join(dir, file))
except:
pass
return True
else:
core.logger.error("EXTRACTOR: Extraction failed for {file}. "
"Result was {result}".format
(file=file_path, result=res))
return False

View file

@ -8,7 +8,7 @@ import subprocess
import core
from core import logger
from core.nzbToMediaUtil import list_media_files
from core.utils import list_media_files
reverse_list = [r"\.\d{2}e\d{2}s\.", r"\.[pi]0801\.", r"\.p027\.", r"\.[pi]675\.", r"\.[pi]084\.", r"\.p063\.",
r"\b[45]62[xh]\.", r"\.yarulb\.", r"\.vtd[hp]\.",

View file

@ -9,11 +9,13 @@ import shutil
import subprocess
from babelfish import Language
from six import iteritems, text_type, string_types
from six import iteritems, string_types, text_type
import core
from core import logger
from core.nzbToMediaUtil import make_dir
from core.utils import make_dir
__author__ = 'Justin'
def is_video_good(videofile, status):

View file

@ -1,2 +0,0 @@
# coding=utf-8
__author__ = 'Justin'

View file

@ -4,9 +4,8 @@ import os
from subprocess import Popen
import core
from core import logger
from core.nzbToMediaUtil import import_subs, list_media_files, remove_dir
from core.transcoder import transcoder
from core import logger, transcoder
from core.utils import import_subs, list_media_files, remove_dir
def external_script(output_destination, torrent_name, torrent_label, settings):

View file

@ -3,31 +3,43 @@
from __future__ import print_function, unicode_literals
import datetime
from functools import partial
import os
import platform
import re
import shutil
import socket
import stat
import struct
import time
from functools import partial
from babelfish import Language
import beets
import guessit
import linktastic
import requests
import subliminal
from babelfish import Language
from qbittorrent import Client as qBittorrentClient
import requests
from six import text_type
import subliminal
from synchronousdeluge.client import DelugeClient
from transmissionrpc.client import Client as TransmissionClient
from utorrent.client import UTorrentClient
import core
from core import logger, nzbToMediaDB
from core.extractor import extractor
from core import extractor, logger, main_db
try:
from win32event import CreateMutex
from win32api import CloseHandle, GetLastError
from winerror import ERROR_ALREADY_EXISTS
except ImportError:
if os.name == 'nt':
raise
try:
import jaraco
except ImportError:
if os.name == 'nt':
raise
requests.packages.urllib3.disable_warnings()
@ -286,7 +298,6 @@ def replace_links(link):
n = 0
target = link
if os.name == 'nt':
import jaraco
if not jaraco.windows.filesystem.islink(link):
logger.debug('{0} is not a link'.format(link))
return
@ -1284,7 +1295,7 @@ def backup_versioned_file(old_file, version):
def update_download_info_status(input_name, status):
logger.db("Updating status of our download {0} in the DB to {1}".format(input_name, status))
my_db = nzbToMediaDB.DBConnection()
my_db = main_db.DBConnection()
my_db.action("UPDATE downloads SET status=?, last_update=? WHERE input_name=?",
[status, datetime.date.today().toordinal(), text_type(input_name)])
@ -1292,47 +1303,20 @@ def update_download_info_status(input_name, status):
def get_download_info(input_name, status):
logger.db("Getting download info for {0} from the DB".format(input_name))
my_db = nzbToMediaDB.DBConnection()
my_db = main_db.DBConnection()
sql_results = my_db.select("SELECT * FROM downloads WHERE input_name=? AND status=?",
[text_type(input_name), status])
return sql_results
class RunningProcess(object):
""" Limits application to single instance """
def __init__(self):
if platform.system() == 'Windows':
self.process = WindowsProcess()
else:
self.process = PosixProcess()
def alreadyrunning(self):
return self.process.alreadyrunning()
# def __del__(self):
# self.process.__del__()
class WindowsProcess(object):
def __init__(self):
self.mutex = None
self.mutexname = "nzbtomedia_{pid}".format(pid=core.PID_FILE.replace('\\', '/')) # {D0E858DF-985E-4907-B7FB-8D732C3FC3B9}"
if platform.system() == 'Windows':
try:
from win32.win32event import CreateMutex
from win32.win32api import CloseHandle, GetLastError
from win32.lib.winerror import ERROR_ALREADY_EXISTS
except ImportError:
from win32event import CreateMutex
from win32api import CloseHandle, GetLastError
from winerror import ERROR_ALREADY_EXISTS
self.CreateMutex = CreateMutex
self.CloseHandle = CloseHandle
self.GetLastError = GetLastError
self.ERROR_ALREADY_EXISTS = ERROR_ALREADY_EXISTS
self.CreateMutex = CreateMutex
self.CloseHandle = CloseHandle
self.GetLastError = GetLastError
self.ERROR_ALREADY_EXISTS = ERROR_ALREADY_EXISTS
def alreadyrunning(self):
self.mutex = self.CreateMutex(None, 0, self.mutexname)
@ -1400,3 +1384,8 @@ class PosixProcess(object):
self.lock_socket.close()
if os.path.isfile(self.pidpath):
os.unlink(self.pidpath)
if os.name == 'nt':
RunningProcess = WindowsProcess
else:
RunningProcess = PosixProcess

View file

@ -14,7 +14,7 @@ import traceback
from six.moves.urllib.request import urlretrieve
import core
from core import gh_api as github, logger
from core import github_api as github, logger
class CheckVersion(object):

View file

@ -628,14 +628,10 @@ import os
import sys
import core
from core import logger, nzbToMediaDB
from core.autoProcess.autoProcessComics import Comic
from core.autoProcess.autoProcessGames import Game
from core.autoProcess.autoProcessMovie import Movie
from core.autoProcess.autoProcessMusic import Music
from core.autoProcess.autoProcessTV import TV
from core.nzbToMediaUserScript import external_script
from core.nzbToMediaUtil import char_replace, clean_dir, convert_to_ascii, extract_files, get_dirs, get_download_info, get_nzoid, plex_update, update_download_info_status
from core import logger, main_db
from core.auto_process import Comic, Game, Movie, Music, TV
from core.user_scripts import external_script
from core.utils import char_replace, clean_dir, convert_to_ascii, extract_files, get_dirs, get_download_info, get_nzoid, plex_update, update_download_info_status
try:
text_type = unicode
@ -657,7 +653,7 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d
if client_agent != 'manual' and not core.DOWNLOADINFO:
logger.debug('Adding NZB download info for directory {0} to database'.format(input_directory))
my_db = nzbToMediaDB.DBConnection()
my_db = main_db.DBConnection()
input_directory1 = input_directory
input_name1 = input_name
@ -732,13 +728,13 @@ def process(input_directory, input_name=None, status=0, client_agent='manual', d
result = Movie().process(section_name, input_directory, input_name, status, client_agent, download_id,
input_category, failure_link)
elif section_name in ["SickBeard", "NzbDrone", "Sonarr"]:
result = TV().process_episode(section_name, input_directory, input_name, status, client_agent,
download_id, input_category, failure_link)
result = TV().process(section_name, input_directory, input_name, status, client_agent,
download_id, input_category, failure_link)
elif section_name in ["HeadPhones", "Lidarr"]:
result = Music().process(section_name, input_directory, input_name, status, client_agent, input_category)
elif section_name == "Mylar":
result = Comic().process_episode(section_name, input_directory, input_name, status, client_agent,
input_category)
result = Comic().process(section_name, input_directory, input_name, status, client_agent,
input_category)
elif section_name == "Gamez":
result = Game().process(section_name, input_directory, input_name, status, client_agent, input_category)
elif section_name == 'UserScript':

View file

@ -1,13 +1,15 @@
#! /usr/bin/env python2
from __future__ import print_function
from babelfish import Language
import guessit
import requests
import subliminal
import core
from core.nzbToMediaAutoFork import auto_fork
from core.nzbToMediaUtil import server_responding
from core.transcoder import transcoder
from core import transcoder
from core.forks import auto_fork
from core.utils import server_responding
# Initialize the config
core.initialize()
@ -38,7 +40,6 @@ if server_responding("http://127.0.0.1:8085"):
if server_responding("http://127.0.0.1:8090"):
print("Mylar Running")
from babelfish import Language
lan = 'pt'
lan = Language.fromalpha2(lan)
print(lan.alpha3)
@ -59,7 +60,6 @@ if guess:
results = r.json()
print(results)
import subliminal
subliminal.region.configure('dogpile.cache.dbm', arguments={'filename': 'cachefile.dbm'})
languages = set()
languages.add(lan)