Skip to content

Commit

Permalink
Merge pull request #3522 from pymedusa/release/release-0.1.21
Browse files Browse the repository at this point in the history
Release/release 0.1.21.
Merry Christmas! ;-)
  • Loading branch information
p0psicles authored Dec 26, 2017
2 parents 1a8dc66 + b06e093 commit b6f1814
Show file tree
Hide file tree
Showing 56 changed files with 1,442 additions and 457 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ LABEL build_version="Version:- ${VERSION} Build-date:- ${BUILD_DATE}"
RUN \
apk add --no-cache \
--repository http://nl.alpinelinux.org/alpine/edge/community \
mediainfo gdbm
mediainfo gdbm py-gdbm

# install app
COPY . /app/medusa/
Expand Down
35 changes: 30 additions & 5 deletions ext/subliminal/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
import itertools
import logging
import operator
import os.path
import os
import socket

from babelfish import Language, LanguageReverseError
from guessit import guessit
from six.moves.xmlrpc_client import ProtocolError
from rarfile import BadRarFile, NotRarFile, RarCannotExec, RarFile
from zipfile import BadZipfile
from ssl import SSLError
import requests

from .exceptions import ServiceUnavailable
Expand Down Expand Up @@ -89,6 +90,11 @@ def __delitem__(self, name):
logger.error('Provider %r unavailable, improperly terminated', name)
else:
logger.exception('Provider %r http error %r, improperly terminated', name, e.response.status_code)
except SSLError as e:
if e.args[0] == 'The read operation timed out':
logger.error('Provider %r unavailable, improperly terminated', name)
else:
logger.exception('Provider %r SSL error %r, improperly terminated', name, e.args[0])
except:
logger.exception('Provider %r terminated unexpectedly', name)

Expand Down Expand Up @@ -135,6 +141,11 @@ def list_subtitles_provider(self, provider, video, languages):
logger.error('Provider %r unavailable', provider)
else:
logger.exception('Provider %r http error %r', provider, e.response.status_code)
except SSLError as e:
if e.args[0] == 'The read operation timed out':
logger.error('Provider %r unavailable', provider)
else:
logger.exception('Provider %r SSL error %r', provider, e.args[0])
except:
logger.exception('Unexpected error in provider %r', provider)

Expand Down Expand Up @@ -196,10 +207,18 @@ def download_subtitle(self, subtitle):
return False
except requests.exceptions.HTTPError as e:
if e.response.status_code in range(500, 600):
logger.error('Provider %r unavailable, improperly terminated', subtitle.provider_name)
logger.error('Provider %r unavailable, discarding it', subtitle.provider_name)
else:
logger.exception('Provider %r http error %r, improperly terminated', subtitle.provider_name,
logger.exception('Provider %r http error %r, discarding it', subtitle.provider_name,
e.response.status_code)
self.discarded_providers.add(subtitle.provider_name)
return False
except SSLError as e:
if e.args[0] == 'The read operation timed out':
logger.error('Provider %r unavailable, discarding it', subtitle.provider_name)
else:
logger.exception('Provider %r SSL error %r, discarding it', subtitle.provider_name, e.args[0])
self.discarded_providers.add(subtitle.provider_name)
return False
except (BadRarFile, BadZipfile):
logger.error('Bad archive for %r', subtitle)
Expand Down Expand Up @@ -523,9 +542,15 @@ def scan_videos(path, age=None, archives=True):
continue

# skip old files
if age and datetime.utcnow() - datetime.utcfromtimestamp(os.path.getmtime(filepath)) > age:
logger.debug('Skipping old file %r in %r', filename, dirpath)
try:
file_age = datetime.utcfromtimestamp(os.path.getmtime(filepath))
except ValueError:
logger.warning('Could not get age of file %r in %r', filename, dirpath)
continue
else:
if age and datetime.utcnow() - file_age > age:
logger.debug('Skipping old file %r in %r', filename, dirpath)
continue

# scan
if filename.endswith(VIDEO_EXTENSIONS): # video
Expand Down
2 changes: 1 addition & 1 deletion ext/subliminal/score.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
'format': 7, 'audio_codec': 3, 'resolution': 2, 'video_codec': 2, 'hearing_impaired': 1}

#: Equivalent release groups
equivalent_release_groups = ({'LOL', 'DIMENSION'}, {'ASAP', 'IMMERSE', 'FLEET'})
equivalent_release_groups = ({'LOL', 'DIMENSION'}, {'ASAP', 'IMMERSE', 'FLEET'}, {'AVS', 'SVA'})


def get_equivalent_release_groups(release_group):
Expand Down
5 changes: 5 additions & 0 deletions medusa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,7 @@ def initialize(self, console_logging=True):
app.BACKLOG_PERIOD = check_setting_str(app.CFG, 'GUI', 'backlog_period', 'all')
app.BACKLOG_STATUS = check_setting_str(app.CFG, 'GUI', 'backlog_status', 'all')
app.LAYOUT_WIDE = check_setting_bool(app.CFG, 'GUI', 'layout_wide', 0)
app.SHOW_LIST_ORDER = check_setting_list(app.CFG, 'GUI', 'show_list_order', app.SHOW_LIST_ORDER)

app.FALLBACK_PLEX_ENABLE = check_setting_int(app.CFG, 'General', 'fallback_plex_enable', 1)
app.FALLBACK_PLEX_NOTIFICATIONS = check_setting_int(app.CFG, 'General', 'fallback_plex_notifications', 1)
Expand Down Expand Up @@ -984,6 +985,8 @@ def initialize(self, console_logging=True):
load_provider_setting(app.CFG, provider, 'bool', 'enable_daily', 1)
load_provider_setting(app.CFG, provider, 'bool', 'enable_backlog', provider.supports_backlog)
load_provider_setting(app.CFG, provider, 'bool', 'enable_manualsearch', 1)
load_provider_setting(app.CFG, provider, 'bool', 'enable_search_delay', 0)
load_provider_setting(app.CFG, provider, 'int', 'search_delay', 480)

if provider.provider_type == GenericProvider.TORRENT:
load_provider_setting(app.CFG, provider, 'string', 'custom_url', '', censor_log='low')
Expand Down Expand Up @@ -1525,6 +1528,7 @@ def save_config():
'name', 'url', 'api_key', 'username',
'search_mode', 'search_fallback',
'enable_daily', 'enable_backlog', 'enable_manualsearch',
'enable_search_delay', 'search_delay',
],
'encrypted': [
'password',
Expand Down Expand Up @@ -1822,6 +1826,7 @@ def save_config():
new_config['GUI']['poster_sortby'] = app.POSTER_SORTBY
new_config['GUI']['poster_sortdir'] = app.POSTER_SORTDIR
new_config['GUI']['layout_wide'] = app.LAYOUT_WIDE
new_config['GUI']['show_list_order'] = app.SHOW_LIST_ORDER

new_config['Subtitles'] = {}
new_config['Subtitles']['use_subtitles'] = int(app.USE_SUBTITLES)
Expand Down
2 changes: 1 addition & 1 deletion medusa/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@
DISPLAY_ALL_SEASONS = True
DEFAULT_PAGE = 'home'
SEEDERS_LEECHERS_IN_NOTIFY = True

SHOW_LIST_ORDER = ['Anime', 'Series']

USE_LISTVIEW = False
METADATA_KODI = []
Expand Down
16 changes: 8 additions & 8 deletions medusa/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def __init__(self, episodes=None, provider=None):
self.url = u''

# used by some providers to store extra info associated with the result
self.extraInfo = []
self.extra_info = []

# quality of the release
self.quality = Quality.UNKNOWN
Expand Down Expand Up @@ -93,7 +93,7 @@ def __init__(self, episodes=None, provider=None):
self.content = None

# Result type like: nzb, nzbdata, torrent
self.resultType = u''
self.result_type = u''

# Store the parse result, as it might be useful for other information later on.
self.parsed_result = None
Expand Down Expand Up @@ -157,7 +157,7 @@ def __str__(self):

my_string = u'{0} @ {1}\n'.format(self.provider.name, self.url)
my_string += u'Extra Info:\n'
for extra in self.extraInfo:
for extra in self.extra_info:
my_string += u' {0}\n'.format(extra)

my_string += u'Episodes:\n'
Expand All @@ -172,7 +172,7 @@ def __str__(self):
return my_string

def file_name(self):
return u'{0}.{1}'.format(self.episodes[0].pretty_name(), self.resultType)
return u'{0}.{1}'.format(self.episodes[0].pretty_name(), self.result_type)

def add_result_to_cache(self, cache):
"""Cache the item if needed."""
Expand Down Expand Up @@ -200,23 +200,23 @@ class NZBSearchResult(SearchResult):

def __init__(self, episodes, provider=None):
super(NZBSearchResult, self).__init__(episodes, provider=provider)
self.resultType = u'nzb'
self.result_type = u'nzb'


class NZBDataSearchResult(SearchResult):
"""NZB result where the actual NZB XML data is stored in the extraInfo."""
"""NZB result where the actual NZB XML data is stored in the extra_info."""

def __init__(self, episodes, provider=None):
super(NZBDataSearchResult, self).__init__(episodes, provider=provider)
self.resultType = u'nzbdata'
self.result_type = u'nzbdata'


class TorrentSearchResult(SearchResult):
"""Torrent result with an URL to the torrent."""

def __init__(self, episodes, provider=None):
super(TorrentSearchResult, self).__init__(episodes, provider=provider)
self.resultType = u'torrent'
self.result_type = u'torrent'


class AllShowsListUI(object): # pylint: disable=too-few-public-methods
Expand Down
6 changes: 3 additions & 3 deletions medusa/clients/nzb/nzbget.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ def sendNZB(nzb, proper=False):
dupescore += 10

nzbcontent64 = None
if nzb.resultType == 'nzbdata':
data = nzb.extraInfo[0]
if nzb.result_type == 'nzbdata':
data = nzb.extra_info[0]
nzbcontent64 = standard_b64encode(data)

log.info('Sending NZB to NZBget')
Expand All @@ -141,7 +141,7 @@ def sendNZB(nzb, proper=False):
nzbcontent64
)
else:
if nzb.resultType == 'nzb':
if nzb.result_type == 'nzb':
if not nzb.provider.login():
return False

Expand Down
60 changes: 56 additions & 4 deletions medusa/clients/nzb/sab.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import logging

from medusa import app
from medusa.helper.common import sanitize_filename
from medusa.logger.adapters.style import BraceAdapter
from medusa.session.core import MedusaSafeSession

Expand All @@ -26,9 +27,10 @@

def send_nzb(nzb):
"""
Sends an NZB to SABnzbd via the API.
Dispatch method for sending an nzb to sabnzbd using it's api.
:param nzb: The NZBSearchResult object to send to SAB
:param nzb: nzb SearchResult object
:return: result of the communication with sabnzbd (True/False)
"""
session.params.update({
'output': 'json',
Expand All @@ -49,14 +51,28 @@ def send_nzb(nzb):
# set up a dict with the URL params in it
params = {
'cat': category,
'mode': 'addurl',
'name': nzb.url,
}

if nzb.priority:
params['priority'] = 2 if app.SAB_FORCED else 1

if nzb.result_type == 'nzbdata' and nzb.extra_info:
return send_nzb_post(params, nzb)
else:
return send_nzb_get(params, nzb)


def send_nzb_get(params, nzb):
"""
Sends an NZB to SABnzbd via the API using a get request.
:param nzb: The NZBSearchResult object to send to SAB
:return: result of the communication with sabnzbd (True/False)
"""

log.info('Sending NZB to SABnzbd')

params.update({'name': nzb.url, 'mode': 'addurl'})
url = urljoin(app.SAB_HOST, 'api')

response = session.get(url, params=params, verify=False)
Expand All @@ -72,6 +88,42 @@ def send_nzb(nzb):
return result


def send_nzb_post(params, nzb):
"""
Sends an NZB to SABnzbd via the API.
:param params: Prepared post parameters.
:param nzb: The NZBSearchResult object to send to SAB
:return: result of the communication with sabnzbd (True/False)
"""

log.info('Sending NZB to SABnzbd using the post multipart/form data.')
url = urljoin(app.SAB_HOST, 'api')
params['mode'] = 'addfile'
files = {
'name': nzb.extra_info[0]
}

data = session.params
data.update(params)
data['nzbname'] = sanitize_filename(nzb.name)

# Empty session.params, because else these are added to the url.
session.params = {}

response = session.post(url, data=data, files=files, verify=False)

try:
data = response.json()
except ValueError:
log.info('Error connecting to sab, no data returned')
else:
log.debug('Result text from SAB: {0}', data)
result, text = _check_sab_response(data)
del text
return result


def _check_sab_response(jdata):
"""
Check response from SAB
Expand Down
7 changes: 5 additions & 2 deletions medusa/clients/torrent/deluge_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
from medusa import app
from medusa.clients.torrent.generic import GenericClient
from medusa.helpers import (
get_extension,
is_already_processed_media,
is_info_hash_in_history,
is_info_hash_processed,
is_media_file,
)
from medusa.logger.adapters.style import BraceAdapter

from requests.exceptions import RequestException

log = BraceAdapter(logging.getLogger(__name__))
Expand All @@ -36,10 +38,11 @@ def read_torrent_status(torrent_data):

to_remove = False
for i in details['files']:
# Need to check only the media file or the .rar file to avoid checking all .r0* files in history
if not (is_media_file(i['path']) or get_extension(i['path']) == 'rar'):
continue
# Check if media was processed
# OR check hash in case of RARed torrents
if not is_media_file(i['path']):
continue
if is_already_processed_media(i['path']) or is_info_hash_processed(info_hash):
to_remove = True

Expand Down
6 changes: 4 additions & 2 deletions medusa/clients/torrent/transmission_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from medusa import app
from medusa.clients.torrent.generic import GenericClient
from medusa.helpers import (
get_extension,
is_already_processed_media,
is_info_hash_in_history,
is_info_hash_processed,
Expand Down Expand Up @@ -290,10 +291,11 @@ def remove_ratio_reached(self):

to_remove = False
for i in torrent['files']:
# Need to check only the media file or the .rar file to avoid checking all .r0* files in history
if not (is_media_file(i['name']) or get_extension(i['name']) == 'rar'):
continue
# Check if media was processed
# OR check hash in case of RARed torrents
if not is_media_file(i['name']):
continue
if is_already_processed_media(i['name']) or is_info_hash_processed(str(torrent['hashString'])):
to_remove = True

Expand Down
2 changes: 1 addition & 1 deletion medusa/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
# To enable, set SPOOF_USER_AGENT = True
SPOOF_USER_AGENT = False
INSTANCE_ID = str(uuid.uuid1())
VERSION = '0.1.20'
VERSION = '0.1.21'
USER_AGENT = u'Medusa/{version} ({system}; {release}; {instance})'.format(
version=VERSION, system=platform.system(), release=platform.release(),
instance=INSTANCE_ID)
Expand Down
Loading

0 comments on commit b6f1814

Please sign in to comment.