Provider restructure
This commit is contained in:
@@ -24,9 +24,6 @@ class Loader(object):
|
||||
'downloaders': (20, 'couchpotato.core.downloaders', os.path.join(core, 'downloaders')),
|
||||
}
|
||||
|
||||
# Add providers to loader
|
||||
self.addPath(root, ['couchpotato', 'core', 'providers'], 25, recursive = False)
|
||||
|
||||
# Add media to loader
|
||||
self.addPath(root, ['couchpotato', 'core', 'media'], 25, recursive = True)
|
||||
|
||||
@@ -103,7 +100,7 @@ class Loader(object):
|
||||
def loadSettings(self, module, name, save = True):
|
||||
|
||||
if not hasattr(module, 'config'):
|
||||
log.debug('Skip loading settings for plugin %s as it has no config section' % module.__file__)
|
||||
#log.debug('Skip loading settings for plugin %s as it has no config section' % module.__file__)
|
||||
return False
|
||||
|
||||
try:
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
config = [{
|
||||
'name': 'automation_providers',
|
||||
'groups': [
|
||||
{
|
||||
'label': 'Watchlists',
|
||||
'description': 'Check watchlists for new movies',
|
||||
'type': 'list',
|
||||
'name': 'watchlist_providers',
|
||||
'tab': 'automation',
|
||||
'options': [],
|
||||
},
|
||||
{
|
||||
'label': 'Automated',
|
||||
'description': 'Uses minimal requirements',
|
||||
'type': 'list',
|
||||
'name': 'automation_providers',
|
||||
'tab': 'automation',
|
||||
'options': [],
|
||||
},
|
||||
],
|
||||
}]
|
||||
|
||||
@@ -1,96 +1,8 @@
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.base import Provider
|
||||
from couchpotato.environment import Env
|
||||
from couchpotato.core.helpers.variable import splitString
|
||||
import time
|
||||
from couchpotato.core.media._base.providers.base import Provider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class Automation(Provider):
|
||||
|
||||
enabled_option = 'automation_enabled'
|
||||
http_time_between_calls = 2
|
||||
|
||||
interval = 1800
|
||||
last_checked = 0
|
||||
|
||||
def __init__(self):
|
||||
addEvent('automation.get_movies', self._getMovies)
|
||||
|
||||
def _getMovies(self):
|
||||
|
||||
if self.isDisabled():
|
||||
return
|
||||
|
||||
if not self.canCheck():
|
||||
log.debug('Just checked, skipping %s', self.getName())
|
||||
return []
|
||||
|
||||
self.last_checked = time.time()
|
||||
|
||||
return self.getIMDBids()
|
||||
|
||||
def search(self, name, year = None, imdb_only = False):
|
||||
|
||||
prop_name = 'automation.cached.%s.%s' % (name, year)
|
||||
cached_imdb = Env.prop(prop_name, default = False)
|
||||
if cached_imdb and imdb_only:
|
||||
return cached_imdb
|
||||
|
||||
result = fireEvent('movie.search', q = '%s %s' % (name, year if year else ''), limit = 1, merge = True)
|
||||
|
||||
if len(result) > 0:
|
||||
if imdb_only and result[0].get('imdb'):
|
||||
Env.prop(prop_name, result[0].get('imdb'))
|
||||
|
||||
return result[0].get('imdb') if imdb_only else result[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def isMinimalMovie(self, movie):
|
||||
if not movie.get('rating'):
|
||||
log.info('ignoring %s as no rating is available for.', (movie['original_title']))
|
||||
return False
|
||||
|
||||
if movie['rating'] and movie['rating'].get('imdb'):
|
||||
movie['votes'] = movie['rating']['imdb'][1]
|
||||
movie['rating'] = movie['rating']['imdb'][0]
|
||||
|
||||
for minimal_type in ['year', 'rating', 'votes']:
|
||||
type_value = movie.get(minimal_type, 0)
|
||||
type_min = self.getMinimal(minimal_type)
|
||||
if type_value < type_min:
|
||||
log.info('%s too low for %s, need %s has %s', (minimal_type, movie['original_title'], type_min, type_value))
|
||||
return False
|
||||
|
||||
movie_genres = [genre.lower() for genre in movie['genres']]
|
||||
required_genres = splitString(self.getMinimal('required_genres').lower())
|
||||
ignored_genres = splitString(self.getMinimal('ignored_genres').lower())
|
||||
|
||||
req_match = 0
|
||||
for req_set in required_genres:
|
||||
req = splitString(req_set, '&')
|
||||
req_match += len(list(set(movie_genres) & set(req))) == len(req)
|
||||
|
||||
if self.getMinimal('required_genres') and req_match == 0:
|
||||
log.info2('Required genre(s) missing for %s', movie['original_title'])
|
||||
return False
|
||||
|
||||
for ign_set in ignored_genres:
|
||||
ign = splitString(ign_set, '&')
|
||||
if len(list(set(movie_genres) & set(ign))) == len(ign):
|
||||
log.info2('%s has blacklisted genre(s): %s', (movie['original_title'], ign))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getMinimal(self, min_type):
|
||||
return Env.setting(min_type, 'automation')
|
||||
|
||||
def getIMDBids(self):
|
||||
return []
|
||||
|
||||
def canCheck(self):
|
||||
return time.time() > self.last_checked + self.interval
|
||||
class BaseAutomation(Provider):
|
||||
pass
|
||||
|
||||
@@ -14,7 +14,6 @@ import xml.etree.ElementTree as XMLTree
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class MultiProvider(Plugin):
|
||||
|
||||
def __init__(self):
|
||||
@@ -102,7 +101,6 @@ class Provider(Plugin):
|
||||
class YarrProvider(Provider):
|
||||
|
||||
protocol = None # nzb, torrent, torrent_magnet
|
||||
type = 'movie'
|
||||
|
||||
cat_ids = {}
|
||||
cat_backup_id = None
|
||||
@@ -180,7 +178,7 @@ class YarrProvider(Provider):
|
||||
|
||||
return 'try_next'
|
||||
|
||||
def search(self, movie, quality):
|
||||
def search(self, media, quality):
|
||||
|
||||
if self.isDisabled():
|
||||
return []
|
||||
@@ -192,15 +190,17 @@ class YarrProvider(Provider):
|
||||
|
||||
# Create result container
|
||||
imdb_results = hasattr(self, '_search')
|
||||
results = ResultList(self, movie, quality, imdb_results = imdb_results)
|
||||
results = ResultList(self, media, quality, imdb_results = imdb_results)
|
||||
|
||||
# Do search based on imdb id
|
||||
if imdb_results:
|
||||
self._search(movie, quality, results)
|
||||
self._search(media, quality, results)
|
||||
# Search possible titles
|
||||
else:
|
||||
for title in possibleTitles(getTitle(movie)):
|
||||
self._searchOnTitle(title, movie, quality, results)
|
||||
media_title = fireEvent('library.query', media['library'], single = True)
|
||||
|
||||
for title in possibleTitles(media_title):
|
||||
self._searchOnTitle(title, media, quality, results)
|
||||
|
||||
return results
|
||||
|
||||
@@ -243,8 +243,7 @@ class YarrProvider(Provider):
|
||||
|
||||
def getCatId(self, identifier):
|
||||
|
||||
for cats in self.cat_ids:
|
||||
ids, qualities = cats
|
||||
for ids, qualities in self.cat_ids:
|
||||
if identifier in qualities:
|
||||
return ids
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from couchpotato.core.providers.base import Provider
|
||||
from couchpotato.core.media._base.providers.base import Provider
|
||||
|
||||
|
||||
class MovieProvider(Provider):
|
||||
type = 'movie'
|
||||
class BaseInfoProvider(Provider):
|
||||
type = 'unknown'
|
||||
|
||||
@@ -1,110 +1,8 @@
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import sp
|
||||
from couchpotato.core.helpers.variable import mergeDicts
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.plugins.base import Plugin
|
||||
from couchpotato.environment import Env
|
||||
import os
|
||||
import shutil
|
||||
import traceback
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class MetaDataBase(Plugin):
|
||||
|
||||
enabled_option = 'meta_enabled'
|
||||
|
||||
def __init__(self):
|
||||
addEvent('renamer.after', self.create)
|
||||
|
||||
def create(self, message = None, group = None):
|
||||
if self.isDisabled(): return
|
||||
if not group: group = {}
|
||||
|
||||
log.info('Creating %s metadata.', self.getName())
|
||||
|
||||
# Update library to get latest info
|
||||
try:
|
||||
group['media'] = fireEvent('movie.update_info', group['media'].get('_id'), identifier = group['media']['identifier'], extended = True, single = True)
|
||||
except:
|
||||
log.error('Failed to update movie, before creating metadata: %s', traceback.format_exc())
|
||||
|
||||
root_name = self.getRootName(group)
|
||||
meta_name = os.path.basename(root_name)
|
||||
root = os.path.dirname(root_name)
|
||||
|
||||
movie_info = group['media'].get('info')
|
||||
|
||||
for file_type in ['nfo', 'thumbnail', 'fanart']:
|
||||
try:
|
||||
# Get file path
|
||||
name = getattr(self, 'get' + file_type.capitalize() + 'Name')(meta_name, root)
|
||||
|
||||
if name and (self.conf('meta_' + file_type) or self.conf('meta_' + file_type) is None):
|
||||
|
||||
# Get file content
|
||||
content = getattr(self, 'get' + file_type.capitalize())(movie_info = movie_info, data = group)
|
||||
if content:
|
||||
log.debug('Creating %s file: %s', (file_type, name))
|
||||
if os.path.isfile(content):
|
||||
content = sp(content)
|
||||
name = sp(name)
|
||||
|
||||
shutil.copy2(content, name)
|
||||
shutil.copyfile(content, name)
|
||||
|
||||
# Try and copy stats seperately
|
||||
try: shutil.copystat(content, name)
|
||||
except: pass
|
||||
else:
|
||||
self.createFile(name, content)
|
||||
group['renamed_files'].append(name)
|
||||
|
||||
try:
|
||||
os.chmod(sp(name), Env.getPermission('file'))
|
||||
except:
|
||||
log.debug('Failed setting permissions for %s: %s', (name, traceback.format_exc()))
|
||||
|
||||
except:
|
||||
log.error('Unable to create %s file: %s', (file_type, traceback.format_exc()))
|
||||
|
||||
def getRootName(self, data = None):
|
||||
if not data: data = {}
|
||||
return os.path.join(data['destination_dir'], data['filename'])
|
||||
|
||||
def getFanartName(self, name, root):
|
||||
return
|
||||
|
||||
def getThumbnailName(self, name, root):
|
||||
return
|
||||
|
||||
def getNfoName(self, name, root):
|
||||
return
|
||||
|
||||
def getNfo(self, movie_info = None, data = None):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
def getThumbnail(self, movie_info = None, data = None, wanted_file_type = 'poster_original'):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
# See if it is in current files
|
||||
files = data['media'].get('files')
|
||||
if files.get('image_' + wanted_file_type):
|
||||
if os.path.isfile(files['image_' + wanted_file_type][0]):
|
||||
return files['image_' + wanted_file_type][0]
|
||||
|
||||
# Download using existing info
|
||||
try:
|
||||
images = movie_info['images'][wanted_file_type]
|
||||
file_path = fireEvent('file.download', url = images[0], single = True)
|
||||
return file_path
|
||||
except:
|
||||
pass
|
||||
|
||||
def getFanart(self, movie_info = None, data = None):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info = movie_info, data = data, wanted_file_type = 'backdrop_original')
|
||||
pass
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
from couchpotato.core.providers.metadata.base import MetaDataBase
|
||||
import os
|
||||
|
||||
|
||||
class WindowsMediaCenter(MetaDataBase):
|
||||
|
||||
def getThumbnailName(self, name, root):
|
||||
return os.path.join(root, 'folder.jpg')
|
||||
@@ -1,4 +1,4 @@
|
||||
from couchpotato.core.providers.base import YarrProvider
|
||||
from couchpotato.core.media._base.providers.base import YarrProvider
|
||||
import time
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import BinSearch
|
||||
|
||||
|
||||
def start():
|
||||
return BinSearch()
|
||||
|
||||
config = [{
|
||||
'name': 'binsearch',
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.nzb.base import NZBProvider
|
||||
from couchpotato.environment import Env
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.nzb.base import NZBProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class BinSearch(NZBProvider):
|
||||
class Base(NZBProvider):
|
||||
|
||||
urls = {
|
||||
'download': 'https://www.binsearch.info/fcgi/nzb.fcgi?q=%s',
|
||||
@@ -18,23 +16,11 @@ class BinSearch(NZBProvider):
|
||||
'search': 'https://www.binsearch.info/index.php?%s',
|
||||
}
|
||||
|
||||
http_time_between_calls = 4 # Seconds
|
||||
http_time_between_calls = 4 # Seconds
|
||||
|
||||
def _search(self, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
arguments = tryUrlencode({
|
||||
'q': movie['identifier'],
|
||||
'm': 'n',
|
||||
'max': 400,
|
||||
'adv_age': Env.setting('retention', 'nzb'),
|
||||
'adv_sort': 'date',
|
||||
'adv_col': 'on',
|
||||
'adv_nfo': 'on',
|
||||
'minsize': quality.get('size_min'),
|
||||
'maxsize': quality.get('size_max'),
|
||||
})
|
||||
|
||||
data = self.getHTMLData(self.urls['search'] % arguments)
|
||||
data = self.getHTMLData(self.urls['search'] % self.buildUrl(media, quality))
|
||||
|
||||
if data:
|
||||
try:
|
||||
@@ -101,4 +87,3 @@ class BinSearch(NZBProvider):
|
||||
log.error('Failed getting nzb from %s: %s', (self.getName(), traceback.format_exc()))
|
||||
|
||||
return 'try_next'
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import Newznab
|
||||
|
||||
|
||||
def start():
|
||||
return Newznab()
|
||||
|
||||
config = [{
|
||||
'name': 'newznab',
|
||||
|
||||
@@ -2,8 +2,7 @@ from couchpotato.core.helpers.encoding import tryUrlencode, toUnicode
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import cleanHost, splitString, tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.base import ResultList
|
||||
from couchpotato.core.providers.nzb.base import NZBProvider
|
||||
from couchpotato.core.media._base.providers.nzb.base import NZBProvider
|
||||
from couchpotato.environment import Env
|
||||
from dateutil.parser import parse
|
||||
from urllib2 import HTTPError
|
||||
@@ -15,39 +14,35 @@ import urllib2
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class Newznab(NZBProvider, RSS):
|
||||
class Base(NZBProvider, RSS):
|
||||
|
||||
urls = {
|
||||
'download': 'get&id=%s',
|
||||
'detail': 'details&id=%s',
|
||||
'search': 'movie',
|
||||
'download': 't=get&id=%s'
|
||||
}
|
||||
|
||||
limits_reached = {}
|
||||
|
||||
http_time_between_calls = 1 # Seconds
|
||||
|
||||
def search(self, movie, quality):
|
||||
def search(self, media, quality):
|
||||
hosts = self.getHosts()
|
||||
|
||||
results = ResultList(self, movie, quality, imdb_results = True)
|
||||
results = ResultList(self, media, quality, imdb_results = True)
|
||||
|
||||
for host in hosts:
|
||||
if self.isDisabled(host):
|
||||
continue
|
||||
|
||||
self._searchOnHost(host, movie, quality, results)
|
||||
self._searchOnHost(host, media, quality, results)
|
||||
|
||||
return results
|
||||
|
||||
def _searchOnHost(self, host, movie, quality, results):
|
||||
def _searchOnHost(self, host, media, quality, results):
|
||||
|
||||
arguments = tryUrlencode({
|
||||
'imdbid': movie['identifier'].replace('tt', ''),
|
||||
'apikey': host['api_key'],
|
||||
'extended': 1
|
||||
}) + ('&%s' % host['custom_tag'] if host.get('custom_tag') else '')
|
||||
url = '%s&%s' % (self.getUrl(host['host'], self.urls['search']), arguments)
|
||||
query = self.buildUrl(media, host['api_key'])
|
||||
|
||||
url = '%s&%s' % (self.getUrl(host['host']), query)
|
||||
|
||||
nzbs = self.getRSSData(url, cache_timeout = 1800, headers = {'User-Agent': Env.getIdentifier()})
|
||||
|
||||
@@ -136,11 +131,11 @@ class Newznab(NZBProvider, RSS):
|
||||
if result:
|
||||
return result
|
||||
|
||||
def getUrl(self, host, type):
|
||||
def getUrl(self, host):
|
||||
if '?page=newznabapi' in host:
|
||||
return cleanHost(host)[:-1] + '&t=' + type
|
||||
return cleanHost(host)[:-1] + '&'
|
||||
|
||||
return cleanHost(host) + 'api?t=' + type
|
||||
return cleanHost(host) + 'api?'
|
||||
|
||||
def isDisabled(self, host = None):
|
||||
return not self.isEnabled(host)
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import NZBClub
|
||||
|
||||
|
||||
def start():
|
||||
return NZBClub()
|
||||
|
||||
config = [{
|
||||
'name': 'nzbclub',
|
||||
|
||||
@@ -1,40 +1,26 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.nzb.base import NZBProvider
|
||||
from couchpotato.core.media._base.providers.nzb.base import NZBProvider
|
||||
from dateutil.parser import parse
|
||||
import time
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class NZBClub(NZBProvider, RSS):
|
||||
class Base(NZBProvider, RSS):
|
||||
|
||||
urls = {
|
||||
'search': 'https://www.nzbclub.com/nzbfeeds.aspx?%s',
|
||||
}
|
||||
|
||||
http_time_between_calls = 4 #seconds
|
||||
http_time_between_calls = 4 #seconds
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
q = '"%s %s"' % (title, movie['info']['year'])
|
||||
|
||||
q_param = tryUrlencode({
|
||||
'q': q,
|
||||
})
|
||||
|
||||
params = tryUrlencode({
|
||||
'ig': 1,
|
||||
'rpp': 200,
|
||||
'st': 5,
|
||||
'sp': 1,
|
||||
'ns': 1,
|
||||
})
|
||||
|
||||
nzbs = self.getRSSData(self.urls['search'] % ('%s&%s' % (q_param, params)))
|
||||
nzbs = self.getRSSData(self.urls['search'] % self.buildUrl(media))
|
||||
|
||||
for nzb in nzbs:
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import NzbIndex
|
||||
|
||||
|
||||
def start():
|
||||
return NzbIndex()
|
||||
|
||||
config = [{
|
||||
'name': 'nzbindex',
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.nzb.base import NZBProvider
|
||||
from couchpotato.environment import Env
|
||||
from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.media._base.providers.nzb.base import NZBProvider
|
||||
from dateutil.parser import parse
|
||||
import re
|
||||
import time
|
||||
@@ -12,7 +12,7 @@ import time
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class NzbIndex(NZBProvider, RSS):
|
||||
class Base(NZBProvider, RSS):
|
||||
|
||||
urls = {
|
||||
'download': 'https://www.nzbindex.com/download/',
|
||||
@@ -21,28 +21,44 @@ class NzbIndex(NZBProvider, RSS):
|
||||
|
||||
http_time_between_calls = 1 # Seconds
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
q = '"%s %s" | "%s (%s)"' % (title, movie['info']['year'], title, movie['info']['year'])
|
||||
arguments = tryUrlencode({
|
||||
'q': q,
|
||||
'age': Env.setting('retention', 'nzb'),
|
||||
'sort': 'agedesc',
|
||||
'minsize': quality.get('size_min'),
|
||||
'maxsize': quality.get('size_max'),
|
||||
'rating': 1,
|
||||
'max': 250,
|
||||
'more': 1,
|
||||
'complete': 1,
|
||||
})
|
||||
|
||||
nzbs = self.getRSSData(self.urls['search'] % arguments)
|
||||
nzbs = self.getRSSData(self.urls['search'] % self.buildUrl(media, quality))
|
||||
|
||||
for nzb in nzbs:
|
||||
|
||||
enclosure = self.getElement(nzb, 'enclosure').attrib
|
||||
nzbindex_id = int(self.getTextElement(nzb, "link").split('/')[4])
|
||||
|
||||
title = self.getTextElement(nzb, "title")
|
||||
|
||||
match = fireEvent('matcher.parse', title, parser='usenet', single = True)
|
||||
if not match.chains:
|
||||
log.info('Unable to parse release with title "%s"', title)
|
||||
continue
|
||||
|
||||
# TODO should we consider other lower-weight chains here?
|
||||
info = fireEvent('matcher.flatten_info', match.chains[0].info, single = True)
|
||||
|
||||
release_name = fireEvent('matcher.construct_from_raw', info.get('release_name'), single = True)
|
||||
|
||||
file_name = info.get('detail', {}).get('file_name')
|
||||
file_name = file_name[0] if file_name else None
|
||||
|
||||
title = release_name or file_name
|
||||
|
||||
# Strip extension from parsed title (if one exists)
|
||||
ext_pos = title.rfind('.')
|
||||
|
||||
# Assume extension if smaller than 4 characters
|
||||
# TODO this should probably be done a better way
|
||||
if len(title[ext_pos + 1:]) <= 4:
|
||||
title = title[:ext_pos]
|
||||
|
||||
if not title:
|
||||
log.info('Unable to find release name from match')
|
||||
continue
|
||||
|
||||
try:
|
||||
description = self.getTextElement(nzb, "description")
|
||||
except:
|
||||
@@ -57,7 +73,7 @@ class NzbIndex(NZBProvider, RSS):
|
||||
|
||||
results.append({
|
||||
'id': nzbindex_id,
|
||||
'name': self.getTextElement(nzb, "title"),
|
||||
'name': title,
|
||||
'age': self.calculateAge(int(time.mktime(parse(self.getTextElement(nzb, "pubDate")).timetuple()))),
|
||||
'size': tryInt(enclosure['length']) / 1024 / 1024,
|
||||
'url': enclosure['url'],
|
||||
@@ -76,4 +92,3 @@ class NzbIndex(NZBProvider, RSS):
|
||||
item['description'] = toUnicode(html.find('pre', attrs = {'id':'nfo0'}).text)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import OMGWTFNZBs
|
||||
|
||||
|
||||
def start():
|
||||
return OMGWTFNZBs()
|
||||
|
||||
config = [{
|
||||
'name': 'omgwtfnzbs',
|
||||
|
||||
@@ -3,7 +3,7 @@ from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.nzb.base import NZBProvider
|
||||
from couchpotato.core.media._base.providers.nzb.base import NZBProvider
|
||||
from dateutil.parser import parse
|
||||
from urlparse import urlparse, parse_qs
|
||||
import time
|
||||
@@ -11,7 +11,7 @@ import time
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class OMGWTFNZBs(NZBProvider, RSS):
|
||||
class Base(NZBProvider, RSS):
|
||||
|
||||
urls = {
|
||||
'search': 'https://rss.omgwtfnzbs.org/rss-search.php?%s',
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import AwesomeHD
|
||||
|
||||
|
||||
def start():
|
||||
return AwesomeHD()
|
||||
|
||||
config = [{
|
||||
'name': 'awesomehd',
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class AwesomeHD(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://awesome-hd.net/',
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import traceback
|
||||
from couchpotato.core.helpers.variable import getImdb, md5, cleanHost
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.base import YarrProvider
|
||||
from couchpotato.core.media._base.providers.base import YarrProvider
|
||||
from couchpotato.environment import Env
|
||||
import time
|
||||
|
||||
@@ -15,6 +14,22 @@ class TorrentProvider(YarrProvider):
|
||||
proxy_domain = None
|
||||
proxy_list = []
|
||||
|
||||
def imdbMatch(self, url, imdbId):
|
||||
if getImdb(url) == imdbId:
|
||||
return True
|
||||
|
||||
if url[:4] == 'http':
|
||||
try:
|
||||
cache_key = md5(url)
|
||||
data = self.getCache(cache_key, url)
|
||||
except IOError:
|
||||
log.error('Failed to open %s.', url)
|
||||
return False
|
||||
|
||||
return getImdb(data) == imdbId
|
||||
|
||||
return False
|
||||
|
||||
def getDomain(self, url = ''):
|
||||
|
||||
forced_domain = self.conf('domain')
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import BiTHDTV
|
||||
|
||||
|
||||
def start():
|
||||
return BiTHDTV()
|
||||
|
||||
config = [{
|
||||
'name': 'bithdtv',
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode, toUnicode
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class BiTHDTV(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'http://www.bit-hdtv.com/',
|
||||
@@ -19,18 +19,13 @@ class BiTHDTV(TorrentProvider):
|
||||
}
|
||||
|
||||
# Searches for movies only - BiT-HDTV's subcategory and resolution search filters appear to be broken
|
||||
cat_id_movies = 7
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
arguments = tryUrlencode({
|
||||
'search': '%s %s' % (title.replace(':', ''), movie['info']['year']),
|
||||
'cat': self.cat_id_movies
|
||||
})
|
||||
query = self.buildUrl(media)
|
||||
|
||||
url = "%s&%s" % (self.urls['search'], arguments)
|
||||
url = "%s&%s" % (self.urls['search'], query)
|
||||
|
||||
data = self.getHTMLData(url)
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import Bitsoup
|
||||
|
||||
|
||||
def start():
|
||||
return Bitsoup()
|
||||
|
||||
config = [{
|
||||
'name': 'bitsoup',
|
||||
|
||||
@@ -2,13 +2,13 @@ from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import simplifyString, tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class Bitsoup(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://www.bitsoup.me/',
|
||||
@@ -28,6 +28,7 @@ class Bitsoup(TorrentProvider):
|
||||
})
|
||||
url = "%s&%s" % (self.urls['search'], arguments)
|
||||
|
||||
url = self.urls['search'] % self.buildUrl(media, quality)
|
||||
data = self.getHTMLData(url)
|
||||
|
||||
if data:
|
||||
@@ -84,4 +85,3 @@ class Bitsoup(TorrentProvider):
|
||||
return 'logout.php' in output.lower()
|
||||
|
||||
loginCheckSuccess = loginSuccess
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import HDBits
|
||||
|
||||
|
||||
def start():
|
||||
return HDBits()
|
||||
|
||||
config = [{
|
||||
'name': 'hdbits',
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
|
||||
import re
|
||||
import json
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class HDBits(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://hdbits.org/',
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import ILoveTorrents
|
||||
|
||||
|
||||
def start():
|
||||
return ILoveTorrents()
|
||||
|
||||
config = [{
|
||||
'name': 'ilovetorrents',
|
||||
|
||||
@@ -2,14 +2,14 @@ from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class ILoveTorrents(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'download': 'https://www.ilovetorrents.me/%s',
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import IPTorrents
|
||||
|
||||
|
||||
def start():
|
||||
return IPTorrents()
|
||||
|
||||
config = [{
|
||||
'name': 'iptorrents',
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode, toSafeString
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
import six
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class IPTorrents(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://www.iptorrents.com/',
|
||||
@@ -18,26 +19,33 @@ class IPTorrents(TorrentProvider):
|
||||
'search': 'https://www.iptorrents.com/torrents/?l%d=1%s&q=%s&qf=ti&p=%d',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
([48], ['720p', '1080p', 'bd50']),
|
||||
([72], ['cam', 'ts', 'tc', 'r5', 'scr']),
|
||||
([7], ['dvdrip', 'brrip']),
|
||||
([6], ['dvdr']),
|
||||
]
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
cat_backup_id = None
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def buildUrl(self, title, media, quality):
|
||||
return self._buildUrl(title.replace(':', ''), quality['identifier'])
|
||||
|
||||
def _buildUrl(self, query, quality_identifier):
|
||||
|
||||
cat_ids = self.getCatId(quality_identifier)
|
||||
|
||||
if not cat_ids:
|
||||
log.warning('Unable to find category ids for identifier "%s"', quality_identifier)
|
||||
return None
|
||||
|
||||
return self.urls['search'] % ("&".join(("l%d=" % x) for x in cat_ids), tryUrlencode(query).replace('%', '%%'))
|
||||
|
||||
def _searchOnTitle(self, title, media, quality, results):
|
||||
|
||||
freeleech = '' if not self.conf('freeleech') else '&free=on'
|
||||
|
||||
base_url = self.buildUrl(title, media, quality)
|
||||
if not base_url: return
|
||||
|
||||
pages = 1
|
||||
current_page = 1
|
||||
while current_page <= pages and not self.shuttingDown():
|
||||
|
||||
url = self.urls['search'] % (self.getCatId(quality['identifier'])[0], freeleech, tryUrlencode('%s %s' % (title.replace(':', ''), movie['info']['year'])), current_page)
|
||||
data = self.getHTMLData(url)
|
||||
data = self.getHTMLData(base_url % (freeleech, current_page))
|
||||
|
||||
if data:
|
||||
html = BeautifulSoup(data)
|
||||
@@ -57,27 +65,21 @@ class IPTorrents(TorrentProvider):
|
||||
|
||||
entries = result_table.find_all('tr')
|
||||
|
||||
columns = self.getColumns(entries)
|
||||
|
||||
if 'seeders' not in columns or 'leechers' not in columns:
|
||||
log.warning('Unrecognized table format returned')
|
||||
return
|
||||
|
||||
for result in entries[1:]:
|
||||
|
||||
cells = result.find_all('td')
|
||||
if len(cells) <= 1:
|
||||
torrent = result.find_all('td')
|
||||
if len(torrent) <= 1:
|
||||
break
|
||||
|
||||
torrent = cells[1].find('a')
|
||||
torrent = torrent[1].find('a')
|
||||
|
||||
torrent_id = torrent['href'].replace('/details.php?id=', '')
|
||||
torrent_name = unicode(torrent.string)
|
||||
torrent_name = six.text_type(torrent.string)
|
||||
torrent_download_url = self.urls['base_url'] + (result.find_all('td')[3].find('a'))['href'].replace(' ', '.')
|
||||
torrent_details_url = self.urls['base_url'] + torrent['href']
|
||||
torrent_size = self.parseSize(result.find_all('td')[5].string)
|
||||
torrent_seeders = tryInt(cells[columns['seeders']].string)
|
||||
torrent_leechers = tryInt(cells[columns['leechers']].string)
|
||||
torrent_seeders = tryInt(result.find('td', attrs = {'class' : 'ac t_seeders'}).string)
|
||||
torrent_leechers = tryInt(result.find('td', attrs = {'class' : 'ac t_leechers'}).string)
|
||||
|
||||
results.append({
|
||||
'id': torrent_id,
|
||||
@@ -95,20 +97,6 @@ class IPTorrents(TorrentProvider):
|
||||
|
||||
current_page += 1
|
||||
|
||||
def getColumns(self, entries):
|
||||
result = {}
|
||||
|
||||
for x, col in enumerate(entries[0].find_all('th')):
|
||||
name = col.text or col.find('img')['title']
|
||||
key = toSafeString(name).strip().lower()
|
||||
|
||||
if not key:
|
||||
continue
|
||||
|
||||
result[key] = x
|
||||
|
||||
return result
|
||||
|
||||
def getLoginParams(self):
|
||||
return {
|
||||
'username': self.conf('username'),
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import KickAssTorrents
|
||||
|
||||
|
||||
def start():
|
||||
return KickAssTorrents()
|
||||
|
||||
config = [{
|
||||
'name': 'kickasstorrents',
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentMagnetProvider
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class KickAssTorrents(TorrentMagnetProvider):
|
||||
class Base(TorrentMagnetProvider):
|
||||
|
||||
urls = {
|
||||
'detail': '%s/%s',
|
||||
@@ -34,9 +34,9 @@ class KickAssTorrents(TorrentMagnetProvider):
|
||||
'http://www.kickassproxy.info',
|
||||
]
|
||||
|
||||
def _search(self, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
data = self.getHTMLData(self.urls['search'] % (self.getDomain(), 'm', movie['identifier'].replace('tt', '')))
|
||||
data = self.getHTMLData(self.urls['search'] % (self.getDomain(), 'm', media['identifier'].replace('tt', '')))
|
||||
|
||||
if data:
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import PassThePopcorn
|
||||
|
||||
|
||||
def start():
|
||||
return PassThePopcorn()
|
||||
|
||||
config = [{
|
||||
'name': 'passthepopcorn',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import getTitle, tryInt, mergeDicts
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
from dateutil.parser import parse
|
||||
import htmlentitydefs
|
||||
import json
|
||||
@@ -13,56 +13,28 @@ import six
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class PassThePopcorn(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'domain': 'https://tls.passthepopcorn.me',
|
||||
'detail': 'https://tls.passthepopcorn.me/torrents.php?torrentid=%s',
|
||||
'torrent': 'https://tls.passthepopcorn.me/torrents.php',
|
||||
'login': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
||||
'login_check': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
||||
'search': 'https://tls.passthepopcorn.me/search/%s/0/7/%d'
|
||||
'domain': 'https://tls.passthepopcorn.me',
|
||||
'detail': 'https://tls.passthepopcorn.me/torrents.php?torrentid=%s',
|
||||
'torrent': 'https://tls.passthepopcorn.me/torrents.php',
|
||||
'login': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
||||
'login_check': 'https://tls.passthepopcorn.me/ajax.php?action=login',
|
||||
'search': 'https://tls.passthepopcorn.me/search/%s/0/7/%d'
|
||||
}
|
||||
|
||||
http_time_between_calls = 2
|
||||
|
||||
quality_search_params = {
|
||||
'bd50': {'media': 'Blu-ray', 'format': 'BD50'},
|
||||
'1080p': {'resolution': '1080p'},
|
||||
'720p': {'resolution': '720p'},
|
||||
'brrip': {'media': 'Blu-ray'},
|
||||
'dvdr': {'resolution': 'anysd'},
|
||||
'dvdrip': {'media': 'DVD'},
|
||||
'scr': {'media': 'DVD-Screener'},
|
||||
'r5': {'media': 'R5'},
|
||||
'tc': {'media': 'TC'},
|
||||
'ts': {'media': 'TS'},
|
||||
'cam': {'media': 'CAM'}
|
||||
}
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
post_search_filters = {
|
||||
'bd50': {'Codec': ['BD50']},
|
||||
'1080p': {'Resolution': ['1080p']},
|
||||
'720p': {'Resolution': ['720p']},
|
||||
'brrip': {'Source': ['Blu-ray'], 'Quality': ['High Definition'], 'Container': ['!ISO']},
|
||||
'dvdr': {'Codec': ['DVD5', 'DVD9']},
|
||||
'dvdrip': {'Source': ['DVD'], 'Codec': ['!DVD5', '!DVD9']},
|
||||
'scr': {'Source': ['DVD-Screener']},
|
||||
'r5': {'Source': ['R5']},
|
||||
'tc': {'Source': ['TC']},
|
||||
'ts': {'Source': ['TS']},
|
||||
'cam': {'Source': ['CAM']}
|
||||
}
|
||||
|
||||
def _search(self, movie, quality, results):
|
||||
|
||||
movie_title = getTitle(movie)
|
||||
movie_title = getTitle(media)
|
||||
quality_id = quality['identifier']
|
||||
|
||||
params = mergeDicts(self.quality_search_params[quality_id].copy(), {
|
||||
'order_by': 'relevance',
|
||||
'order_way': 'descending',
|
||||
'searchstr': movie['identifier']
|
||||
'searchstr': media['identifier']
|
||||
})
|
||||
|
||||
url = '%s?json=noredirect&%s' % (self.urls['torrent'], tryUrlencode(params))
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import PublicHD
|
||||
|
||||
|
||||
def start():
|
||||
return PublicHD()
|
||||
|
||||
config = [{
|
||||
'name': 'publichd',
|
||||
|
||||
@@ -2,15 +2,16 @@ from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode, toUnicode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentMagnetProvider
|
||||
from urlparse import parse_qs
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider
|
||||
import six
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class PublicHD(TorrentMagnetProvider):
|
||||
class Base(TorrentMagnetProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://publichd.se',
|
||||
@@ -24,13 +25,15 @@ class PublicHD(TorrentMagnetProvider):
|
||||
if not quality.get('hd', False):
|
||||
return []
|
||||
|
||||
return super(PublicHD, self).search(movie, quality)
|
||||
return super(Base, self).search(movie, quality)
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
query = self.buildUrl(media)
|
||||
|
||||
params = tryUrlencode({
|
||||
'page':'torrents',
|
||||
'search': '%s %s' % (title, movie['info']['year']),
|
||||
'search': query,
|
||||
'active': 1,
|
||||
})
|
||||
|
||||
@@ -54,7 +57,7 @@ class PublicHD(TorrentMagnetProvider):
|
||||
|
||||
results.append({
|
||||
'id': url['id'][0],
|
||||
'name': unicode(info_url.string),
|
||||
'name': six.text_type(info_url.string),
|
||||
'url': download['href'],
|
||||
'detail_url': self.urls['detail'] % url['id'][0],
|
||||
'size': self.parseSize(result.find_all('td')[7].string),
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import SceneAccess
|
||||
|
||||
|
||||
def start():
|
||||
return SceneAccess()
|
||||
|
||||
config = [{
|
||||
'name': 'sceneaccess',
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode, toUnicode
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class SceneAccess(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://www.sceneaccess.eu/',
|
||||
@@ -16,35 +16,15 @@ class SceneAccess(TorrentProvider):
|
||||
'login_check': 'https://www.sceneaccess.eu/inbox',
|
||||
'detail': 'https://www.sceneaccess.eu/details?id=%s',
|
||||
'search': 'https://www.sceneaccess.eu/browse?c%d=%d',
|
||||
'archive': 'https://www.sceneaccess.eu/archive?&c%d=%d',
|
||||
'download': 'https://www.sceneaccess.eu/%s',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
([22], ['720p', '1080p']),
|
||||
([7], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip']),
|
||||
([8], ['dvdr']),
|
||||
]
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
|
||||
def _search(self, movie, quality, results):
|
||||
|
||||
cat = self.getCatId(quality['identifier'])
|
||||
if not cat:
|
||||
return
|
||||
|
||||
url = self.urls['search'] % (
|
||||
cat[0],
|
||||
cat[0]
|
||||
)
|
||||
|
||||
arguments = tryUrlencode({
|
||||
'search': movie['identifier'],
|
||||
'method': 3,
|
||||
})
|
||||
url = "%s&%s" % (url, arguments)
|
||||
http_time_between_calls = 1 #seconds
|
||||
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
url = self.buildUrl(media, quality)
|
||||
data = self.getHTMLData(url)
|
||||
|
||||
if data:
|
||||
@@ -77,13 +57,6 @@ class SceneAccess(TorrentProvider):
|
||||
except:
|
||||
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
|
||||
|
||||
def getLoginParams(self):
|
||||
return {
|
||||
'username': self.conf('username'),
|
||||
'password': self.conf('password'),
|
||||
'submit': 'come on in',
|
||||
}
|
||||
|
||||
def getMoreInfo(self, item):
|
||||
full_description = self.getCache('sceneaccess.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
||||
html = BeautifulSoup(full_description)
|
||||
@@ -93,6 +66,14 @@ class SceneAccess(TorrentProvider):
|
||||
item['description'] = description
|
||||
return item
|
||||
|
||||
# Login
|
||||
def getLoginParams(self):
|
||||
return {
|
||||
'username': self.conf('username'),
|
||||
'password': self.conf('password'),
|
||||
'submit': 'come on in',
|
||||
}
|
||||
|
||||
def loginSuccess(self, output):
|
||||
return '/inbox' in output.lower()
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import ThePirateBay
|
||||
|
||||
|
||||
def start():
|
||||
return ThePirateBay()
|
||||
|
||||
config = [{
|
||||
'name': 'thepiratebay',
|
||||
|
||||
@@ -1,29 +1,22 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import toUnicode, tryUrlencode
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentMagnetProvider
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider
|
||||
import six
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class ThePirateBay(TorrentMagnetProvider):
|
||||
class Base(TorrentMagnetProvider):
|
||||
|
||||
urls = {
|
||||
'detail': '%s/torrent/%s',
|
||||
'search': '%s/search/%s/%s/7/%s'
|
||||
'detail': '%s/torrent/%s',
|
||||
'search': '%s/search/%%s/%%s/7/%%s'
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
([207], ['720p', '1080p']),
|
||||
([201], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr']),
|
||||
([201, 207], ['brrip']),
|
||||
([202], ['dvdr'])
|
||||
]
|
||||
|
||||
cat_backup_id = 200
|
||||
disable_provider = False
|
||||
http_time_between_calls = 0
|
||||
@@ -37,18 +30,21 @@ class ThePirateBay(TorrentMagnetProvider):
|
||||
'http://nl.tpb.li',
|
||||
'http://proxybay.eu',
|
||||
'https://www.getpirate.com',
|
||||
'http://piratebay.io',
|
||||
'http://piratebay.io',
|
||||
]
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
page = 0
|
||||
total_pages = 1
|
||||
cats = self.getCatId(quality['identifier'])
|
||||
|
||||
search_url = self.urls['search'] % self.getDomain()
|
||||
|
||||
while page < total_pages:
|
||||
|
||||
search_url = self.urls['search'] % (self.getDomain(), tryUrlencode('"%s" %s' % (title, movie['info']['year'])), page, ','.join(str(x) for x in cats))
|
||||
search_url = search_url % self.buildUrl(media, page, cats)
|
||||
|
||||
page += 1
|
||||
|
||||
data = self.getHTMLData(search_url)
|
||||
@@ -88,7 +84,7 @@ class ThePirateBay(TorrentMagnetProvider):
|
||||
|
||||
results.append({
|
||||
'id': re.search('/(?P<id>\d+)/', link['href']).group('id'),
|
||||
'name': unicode(link.string),
|
||||
'name': six.text_type(link.string),
|
||||
'url': download['href'],
|
||||
'detail_url': self.getDomain(link['href']),
|
||||
'size': self.parseSize(size),
|
||||
@@ -102,7 +98,7 @@ class ThePirateBay(TorrentMagnetProvider):
|
||||
log.error('Failed getting results from %s: %s', (self.getName(), traceback.format_exc()))
|
||||
|
||||
def isEnabled(self):
|
||||
return super(ThePirateBay, self).isEnabled() and self.getDomain()
|
||||
return super(Base, self).isEnabled() and self.getDomain()
|
||||
|
||||
def correctProxy(self, data):
|
||||
return 'title="Pirate Search"' in data
|
||||
@@ -110,7 +106,7 @@ class ThePirateBay(TorrentMagnetProvider):
|
||||
def getMoreInfo(self, item):
|
||||
full_description = self.getCache('tpb.%s' % item['id'], item['detail_url'], cache_timeout = 25920000)
|
||||
html = BeautifulSoup(full_description)
|
||||
nfo_pre = html.find('div', attrs = {'class': 'nfo'})
|
||||
nfo_pre = html.find('div', attrs = {'class':'nfo'})
|
||||
description = toUnicode(nfo_pre.text) if nfo_pre else ''
|
||||
|
||||
item['description'] = description
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import TorrentBytes
|
||||
|
||||
|
||||
def start():
|
||||
return TorrentBytes()
|
||||
|
||||
config = [{
|
||||
'name': 'torrentbytes',
|
||||
|
||||
@@ -2,13 +2,13 @@ from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class TorrentBytes(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://www.torrentbytes.net/',
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import TorrentDay
|
||||
|
||||
|
||||
def start():
|
||||
return TorrentDay()
|
||||
|
||||
config = [{
|
||||
'name': 'torrentday',
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class TorrentDay(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'http://www.td.af/',
|
||||
@@ -16,25 +16,18 @@ class TorrentDay(TorrentProvider):
|
||||
'download': 'http://www.td.af/download.php/%s/%s',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
([11], ['720p', '1080p']),
|
||||
([1, 21, 25], ['cam', 'ts', 'dvdrip', 'tc', 'r5', 'scr', 'brrip']),
|
||||
([3], ['dvdr']),
|
||||
([5], ['bd50']),
|
||||
]
|
||||
http_time_between_calls = 1 #seconds
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
|
||||
q = '"%s %s"' % (title, movie['info']['year'])
|
||||
query = self.buildUrl(media)
|
||||
|
||||
data = {
|
||||
'/browse.php?': None,
|
||||
'cata': 'yes',
|
||||
'jxt': 8,
|
||||
'jxw': 'b',
|
||||
'search': q,
|
||||
'search': query,
|
||||
}
|
||||
|
||||
data = self.getJsonData(self.urls['search'], data = data)
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import TorrentLeech
|
||||
|
||||
|
||||
def start():
|
||||
return TorrentLeech()
|
||||
|
||||
config = [{
|
||||
'name': 'torrentleech',
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
import six
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class TorrentLeech(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'http://www.torrentleech.org/',
|
||||
@@ -20,22 +19,13 @@ class TorrentLeech(TorrentProvider):
|
||||
'download': 'http://www.torrentleech.org%s',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
([13], ['720p', '1080p']),
|
||||
([8], ['cam']),
|
||||
([9], ['ts', 'tc']),
|
||||
([10], ['r5', 'scr']),
|
||||
([11], ['dvdrip']),
|
||||
([14], ['brrip']),
|
||||
([12], ['dvdr']),
|
||||
]
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
cat_backup_id = None
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
url = self.urls['search'] % self.buildUrl(media, quality)
|
||||
|
||||
url = self.urls['search'] % (tryUrlencode('%s %s' % (title.replace(':', ''), movie['info']['year'])), self.getCatId(quality['identifier'])[0])
|
||||
data = self.getHTMLData(url)
|
||||
|
||||
if data:
|
||||
@@ -56,7 +46,7 @@ class TorrentLeech(TorrentProvider):
|
||||
|
||||
results.append({
|
||||
'id': link['href'].replace('/torrent/', ''),
|
||||
'name': unicode(link.string),
|
||||
'name': six.text_type(link.string),
|
||||
'url': self.urls['download'] % url['href'],
|
||||
'detail_url': self.urls['download'] % details['href'],
|
||||
'size': self.parseSize(result.find_all('td')[4].string),
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import TorrentPotato
|
||||
|
||||
|
||||
def start():
|
||||
return TorrentPotato()
|
||||
|
||||
config = [{
|
||||
'name': 'torrentpotato',
|
||||
|
||||
@@ -1,45 +1,37 @@
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode, toUnicode
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import splitString, tryInt, tryFloat
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.base import ResultList
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
from urlparse import urlparse
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class TorrentPotato(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {}
|
||||
limits_reached = {}
|
||||
|
||||
http_time_between_calls = 1 # Seconds
|
||||
|
||||
def search(self, movie, quality):
|
||||
def search(self, media, quality):
|
||||
hosts = self.getHosts()
|
||||
|
||||
results = ResultList(self, movie, quality, imdb_results = True)
|
||||
results = ResultList(self, media, quality, imdb_results = True)
|
||||
|
||||
for host in hosts:
|
||||
if self.isDisabled(host):
|
||||
continue
|
||||
|
||||
self._searchOnHost(host, movie, quality, results)
|
||||
self._searchOnHost(host, media, quality, results)
|
||||
|
||||
return results
|
||||
|
||||
def _searchOnHost(self, host, movie, quality, results):
|
||||
def _searchOnHost(self, host, media, quality, results):
|
||||
|
||||
arguments = tryUrlencode({
|
||||
'user': host['name'],
|
||||
'passkey': host['pass_key'],
|
||||
'imdbid': movie['identifier']
|
||||
})
|
||||
url = '%s?%s' % (host['host'], arguments)
|
||||
|
||||
torrents = self.getJsonData(url, cache_timeout = 1800)
|
||||
torrents = self.getJsonData(self.buildUrl(media, host), cache_timeout = 1800)
|
||||
|
||||
if torrents:
|
||||
try:
|
||||
@@ -110,7 +102,7 @@ class TorrentPotato(TorrentProvider):
|
||||
hosts = self.getHosts()
|
||||
|
||||
for host in hosts:
|
||||
result = super(TorrentPotato, self).belongsTo(url, host = host['host'], provider = provider)
|
||||
result = super(Base, self).belongsTo(url, host = host['host'], provider = provider)
|
||||
if result:
|
||||
return result
|
||||
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import TorrentShack
|
||||
|
||||
|
||||
def start():
|
||||
return TorrentShack()
|
||||
|
||||
config = [{
|
||||
'name': 'torrentshack',
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
import six
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class TorrentShack(TorrentProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': 'https://torrentshack.net/',
|
||||
@@ -20,21 +19,11 @@ class TorrentShack(TorrentProvider):
|
||||
'download': 'https://torrentshack.net/%s',
|
||||
}
|
||||
|
||||
cat_ids = [
|
||||
([970], ['bd50']),
|
||||
([300], ['720p', '1080p']),
|
||||
([350], ['dvdr']),
|
||||
([400], ['brrip', 'dvdrip']),
|
||||
]
|
||||
|
||||
http_time_between_calls = 1 #seconds
|
||||
cat_backup_id = 400
|
||||
|
||||
def _searchOnTitle(self, title, movie, quality, results):
|
||||
def _search(self, media, quality, results):
|
||||
|
||||
scene_only = '1' if self.conf('scene_only') else ''
|
||||
|
||||
url = self.urls['search'] % (tryUrlencode('%s %s' % (title.replace(':', ''), movie['info']['year'])), scene_only, self.getCatId(quality['identifier'])[0])
|
||||
url = self.urls['search'] % self.buildUrl(media, quality)
|
||||
data = self.getHTMLData(url)
|
||||
|
||||
if data:
|
||||
@@ -77,3 +66,6 @@ class TorrentShack(TorrentProvider):
|
||||
return 'logout.php' in output.lower()
|
||||
|
||||
loginCheckSuccess = loginSuccess
|
||||
|
||||
def getSceneOnly(self):
|
||||
return '1' if self.conf('scene_only') else ''
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
from .main import Yify
|
||||
|
||||
|
||||
def start():
|
||||
return Yify()
|
||||
|
||||
config = [{
|
||||
'name': 'yify',
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.torrent.base import TorrentMagnetProvider
|
||||
import traceback
|
||||
from couchpotato.core.media._base.providers.torrent.base import TorrentProvider
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class Yify(TorrentMagnetProvider):
|
||||
class Base(TorrentProvider):
|
||||
|
||||
urls = {
|
||||
'test': '%s/api',
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
from couchpotato.core.providers.userscript.base import UserscriptBase
|
||||
|
||||
|
||||
class MoviesIO(UserscriptBase):
|
||||
|
||||
includes = ['*://movies.io/m/*']
|
||||
@@ -0,0 +1,21 @@
|
||||
config = [{
|
||||
'name': 'automation_providers',
|
||||
'groups': [
|
||||
{
|
||||
'label': 'Watchlists',
|
||||
'description': 'Check watchlists for new movies',
|
||||
'type': 'list',
|
||||
'name': 'watchlist_providers',
|
||||
'tab': 'automation',
|
||||
'options': [],
|
||||
},
|
||||
{
|
||||
'label': 'Automated',
|
||||
'description': 'Uses minimal requirements',
|
||||
'type': 'list',
|
||||
'name': 'automation_providers',
|
||||
'tab': 'automation',
|
||||
'options': [],
|
||||
},
|
||||
],
|
||||
}]
|
||||
96
couchpotato/core/media/movie/providers/automation/base.py
Normal file
96
couchpotato/core/media/movie/providers/automation/base.py
Normal file
@@ -0,0 +1,96 @@
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.media._base.providers.automation.base import BaseAutomation
|
||||
from couchpotato.environment import Env
|
||||
from couchpotato.core.helpers.variable import splitString
|
||||
import time
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class Automation(BaseAutomation):
|
||||
|
||||
enabled_option = 'automation_enabled'
|
||||
http_time_between_calls = 2
|
||||
|
||||
interval = 1800
|
||||
last_checked = 0
|
||||
|
||||
def __init__(self):
|
||||
addEvent('automation.get_movies', self._getMovies)
|
||||
|
||||
def _getMovies(self):
|
||||
|
||||
if self.isDisabled():
|
||||
return
|
||||
|
||||
if not self.canCheck():
|
||||
log.debug('Just checked, skipping %s', self.getName())
|
||||
return []
|
||||
|
||||
self.last_checked = time.time()
|
||||
|
||||
return self.getIMDBids()
|
||||
|
||||
def search(self, name, year = None, imdb_only = False):
|
||||
|
||||
prop_name = 'automation.cached.%s.%s' % (name, year)
|
||||
cached_imdb = Env.prop(prop_name, default = False)
|
||||
if cached_imdb and imdb_only:
|
||||
return cached_imdb
|
||||
|
||||
result = fireEvent('movie.search', q = '%s %s' % (name, year if year else ''), limit = 1, merge = True)
|
||||
|
||||
if len(result) > 0:
|
||||
if imdb_only and result[0].get('imdb'):
|
||||
Env.prop(prop_name, result[0].get('imdb'))
|
||||
|
||||
return result[0].get('imdb') if imdb_only else result[0]
|
||||
else:
|
||||
return None
|
||||
|
||||
def isMinimalMovie(self, movie):
|
||||
if not movie.get('rating'):
|
||||
log.info('ignoring %s as no rating is available for.', (movie['original_title']))
|
||||
return False
|
||||
|
||||
if movie['rating'] and movie['rating'].get('imdb'):
|
||||
movie['votes'] = movie['rating']['imdb'][1]
|
||||
movie['rating'] = movie['rating']['imdb'][0]
|
||||
|
||||
for minimal_type in ['year', 'rating', 'votes']:
|
||||
type_value = movie.get(minimal_type, 0)
|
||||
type_min = self.getMinimal(minimal_type)
|
||||
if type_value < type_min:
|
||||
log.info('%s too low for %s, need %s has %s', (minimal_type, movie['original_title'], type_min, type_value))
|
||||
return False
|
||||
|
||||
movie_genres = [genre.lower() for genre in movie['genres']]
|
||||
required_genres = splitString(self.getMinimal('required_genres').lower())
|
||||
ignored_genres = splitString(self.getMinimal('ignored_genres').lower())
|
||||
|
||||
req_match = 0
|
||||
for req_set in required_genres:
|
||||
req = splitString(req_set, '&')
|
||||
req_match += len(list(set(movie_genres) & set(req))) == len(req)
|
||||
|
||||
if self.getMinimal('required_genres') and req_match == 0:
|
||||
log.info2('Required genre(s) missing for %s', movie['original_title'])
|
||||
return False
|
||||
|
||||
for ign_set in ignored_genres:
|
||||
ign = splitString(ign_set, '&')
|
||||
if len(list(set(movie_genres) & set(ign))) == len(ign):
|
||||
log.info2('%s has blacklisted genre(s): %s', (movie['original_title'], ign))
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def getMinimal(self, min_type):
|
||||
return Env.setting(min_type, 'automation')
|
||||
|
||||
def getIMDBids(self):
|
||||
return []
|
||||
|
||||
def canCheck(self):
|
||||
return time.time() > self.last_checked + self.interval
|
||||
@@ -2,7 +2,7 @@ from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from couchpotato.core.helpers.variable import tryInt, splitString
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -7,9 +7,8 @@ from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import getImdb, splitString, tryInt
|
||||
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
|
||||
from couchpotato.core.providers.base import MultiProvider
|
||||
from couchpotato.core.media._base.providers.base import MultiProvider
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
|
||||
|
||||
log = CPLog(__name__)
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import md5, splitString, tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
from xml.etree.ElementTree import QName
|
||||
import datetime
|
||||
import traceback
|
||||
@@ -1,6 +1,6 @@
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
import datetime
|
||||
|
||||
log = CPLog(__name__)
|
||||
@@ -1,7 +1,7 @@
|
||||
from bs4 import BeautifulSoup
|
||||
from couchpotato.core.helpers.variable import tryInt, splitString, removeEmpty
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
import re
|
||||
|
||||
log = CPLog(__name__)
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -2,7 +2,7 @@ from couchpotato.core.event import fireEvent
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import tryInt, splitString
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.helpers.rss import RSS
|
||||
from couchpotato.core.helpers.variable import tryInt, splitString
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
from xml.etree.ElementTree import QName
|
||||
import datetime
|
||||
import re
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.variable import sha1
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.automation.base import Automation
|
||||
from couchpotato.core.media.movie.providers.automation.base import Automation
|
||||
import base64
|
||||
|
||||
log = CPLog(__name__)
|
||||
5
couchpotato/core/media/movie/providers/base.py
Normal file
5
couchpotato/core/media/movie/providers/base.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from couchpotato.core.media._base.providers.info.base import BaseInfoProvider
|
||||
|
||||
|
||||
class MovieProvider(BaseInfoProvider):
|
||||
type = 'movie'
|
||||
@@ -1,7 +1,7 @@
|
||||
from .main import MovieResultModifier
|
||||
|
||||
|
||||
def start():
|
||||
|
||||
return MovieResultModifier()
|
||||
|
||||
config = []
|
||||
@@ -1,10 +1,12 @@
|
||||
import base64
|
||||
import time
|
||||
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.info.base import MovieProvider
|
||||
from couchpotato.core.media.movie.providers.base import MovieProvider
|
||||
from couchpotato.environment import Env
|
||||
import base64
|
||||
import time
|
||||
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import json
|
||||
import re
|
||||
import traceback
|
||||
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.helpers.variable import tryInt, tryFloat, splitString
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.info.base import MovieProvider
|
||||
import json
|
||||
import re
|
||||
import traceback
|
||||
from couchpotato.core.media.movie.providers.base import MovieProvider
|
||||
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import traceback
|
||||
|
||||
from couchpotato.core.event import addEvent
|
||||
from couchpotato.core.helpers.encoding import simplifyString, toUnicode, ss
|
||||
from couchpotato.core.helpers.variable import tryInt
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.info.base import MovieProvider
|
||||
from couchpotato.core.media.movie.providers.base import MovieProvider
|
||||
import tmdb3
|
||||
import traceback
|
||||
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
109
couchpotato/core/media/movie/providers/metadata/base.py
Normal file
109
couchpotato/core/media/movie/providers/metadata/base.py
Normal file
@@ -0,0 +1,109 @@
|
||||
from couchpotato.core.event import addEvent, fireEvent
|
||||
from couchpotato.core.helpers.encoding import sp
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.media._base.providers.metadata.base import MetaDataBase
|
||||
from couchpotato.environment import Env
|
||||
import os
|
||||
import shutil
|
||||
import traceback
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class MovieMetaData(MetaDataBase):
|
||||
|
||||
enabled_option = 'meta_enabled'
|
||||
|
||||
def __init__(self):
|
||||
addEvent('renamer.after', self.create)
|
||||
|
||||
def create(self, message = None, group = None):
|
||||
if self.isDisabled(): return
|
||||
if not group: group = {}
|
||||
|
||||
log.info('Creating %s metadata.', self.getName())
|
||||
|
||||
# Update library to get latest info
|
||||
try:
|
||||
group['media'] = fireEvent('movie.update_info', group['media'].get('_id'), identifier = group['media']['identifier'], extended = True, single = True)
|
||||
except:
|
||||
log.error('Failed to update movie, before creating metadata: %s', traceback.format_exc())
|
||||
|
||||
root_name = self.getRootName(group)
|
||||
meta_name = os.path.basename(root_name)
|
||||
root = os.path.dirname(root_name)
|
||||
|
||||
movie_info = group['media'].get('info')
|
||||
|
||||
for file_type in ['nfo', 'thumbnail', 'fanart']:
|
||||
try:
|
||||
# Get file path
|
||||
name = getattr(self, 'get' + file_type.capitalize() + 'Name')(meta_name, root)
|
||||
|
||||
if name and (self.conf('meta_' + file_type) or self.conf('meta_' + file_type) is None):
|
||||
|
||||
# Get file content
|
||||
content = getattr(self, 'get' + file_type.capitalize())(movie_info = movie_info, data = group)
|
||||
if content:
|
||||
log.debug('Creating %s file: %s', (file_type, name))
|
||||
if os.path.isfile(content):
|
||||
content = sp(content)
|
||||
name = sp(name)
|
||||
|
||||
shutil.copy2(content, name)
|
||||
shutil.copyfile(content, name)
|
||||
|
||||
# Try and copy stats seperately
|
||||
try: shutil.copystat(content, name)
|
||||
except: pass
|
||||
else:
|
||||
self.createFile(name, content)
|
||||
group['renamed_files'].append(name)
|
||||
|
||||
try:
|
||||
os.chmod(sp(name), Env.getPermission('file'))
|
||||
except:
|
||||
log.debug('Failed setting permissions for %s: %s', (name, traceback.format_exc()))
|
||||
|
||||
except:
|
||||
log.error('Unable to create %s file: %s', (file_type, traceback.format_exc()))
|
||||
|
||||
def getRootName(self, data = None):
|
||||
if not data: data = {}
|
||||
return os.path.join(data['destination_dir'], data['filename'])
|
||||
|
||||
def getFanartName(self, name, root):
|
||||
return
|
||||
|
||||
def getThumbnailName(self, name, root):
|
||||
return
|
||||
|
||||
def getNfoName(self, name, root):
|
||||
return
|
||||
|
||||
def getNfo(self, movie_info = None, data = None):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
def getThumbnail(self, movie_info = None, data = None, wanted_file_type = 'poster_original'):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
|
||||
# See if it is in current files
|
||||
files = data['media'].get('files')
|
||||
if files.get('image_' + wanted_file_type):
|
||||
if os.path.isfile(files['image_' + wanted_file_type][0]):
|
||||
return files['image_' + wanted_file_type][0]
|
||||
|
||||
# Download using existing info
|
||||
try:
|
||||
images = movie_info['images'][wanted_file_type]
|
||||
file_path = fireEvent('file.download', url = images[0], single = True)
|
||||
return file_path
|
||||
except:
|
||||
pass
|
||||
|
||||
def getFanart(self, movie_info = None, data = None):
|
||||
if not data: data = {}
|
||||
if not movie_info: movie_info = {}
|
||||
return self.getThumbnail(movie_info = movie_info, data = data, wanted_file_type = 'backdrop_original')
|
||||
@@ -0,0 +1,8 @@
|
||||
from couchpotato.core.media.movie.providers.metadata.base import MovieMetaData
|
||||
import os
|
||||
|
||||
|
||||
class WindowsMediaCenter(MovieMetaData):
|
||||
|
||||
def getThumbnailName(self, name, root):
|
||||
return os.path.join(root, 'folder.jpg')
|
||||
@@ -1,7 +1,7 @@
|
||||
from couchpotato.core.media.movie.providers.metadata.base import MovieMetaData
|
||||
from couchpotato.core.helpers.encoding import toUnicode
|
||||
from couchpotato.core.helpers.variable import getTitle
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.providers.metadata.base import MetaDataBase
|
||||
from xml.etree.ElementTree import Element, SubElement, tostring
|
||||
import os
|
||||
import re
|
||||
@@ -10,7 +10,7 @@ import xml.dom.minidom
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
class XBMC(MetaDataBase):
|
||||
class XBMC(MovieMetaData):
|
||||
|
||||
def getFanartName(self, name, root):
|
||||
return self.createMetaName(self.conf('meta_fanart_name'), name, root)
|
||||
14
couchpotato/core/media/movie/providers/nzb/__init__.py
Normal file
14
couchpotato/core/media/movie/providers/nzb/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
||||
config = [{
|
||||
'name': 'nzb_providers',
|
||||
'groups': [
|
||||
{
|
||||
'label': 'Usenet Providers',
|
||||
'description': 'Providers searching usenet for new releases',
|
||||
'wizard': True,
|
||||
'type': 'list',
|
||||
'name': 'nzb_providers',
|
||||
'tab': 'searcher',
|
||||
'options': [],
|
||||
},
|
||||
],
|
||||
}]
|
||||
0
couchpotato/core/media/movie/providers/nzb/base.py
Normal file
0
couchpotato/core/media/movie/providers/nzb/base.py
Normal file
@@ -0,0 +1,7 @@
|
||||
from .main import BinSearch
|
||||
|
||||
|
||||
def start():
|
||||
return BinSearch()
|
||||
|
||||
config = []
|
||||
24
couchpotato/core/media/movie/providers/nzb/binsearch/main.py
Normal file
24
couchpotato/core/media/movie/providers/nzb/binsearch/main.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from couchpotato.core.helpers.encoding import tryUrlencode
|
||||
from couchpotato.core.logger import CPLog
|
||||
from couchpotato.core.media._base.providers.nzb.binsearch.main import Base
|
||||
from couchpotato.core.media.movie.providers.base import MovieProvider
|
||||
from couchpotato.environment import Env
|
||||
|
||||
log = CPLog(__name__)
|
||||
|
||||
|
||||
class BinSearch(MovieProvider, Base):
|
||||
|
||||
def buildUrl(self, media, quality):
|
||||
query = tryUrlencode({
|
||||
'q': media['identifier'],
|
||||
'm': 'n',
|
||||
'max': 400,
|
||||
'adv_age': Env.setting('retention', 'nzb'),
|
||||
'adv_sort': 'date',
|
||||
'adv_col': 'on',
|
||||
'adv_nfo': 'on',
|
||||
'minsize': quality.get('size_min'),
|
||||
'maxsize': quality.get('size_max'),
|
||||
})
|
||||
return query
|
||||
@@ -0,0 +1,7 @@
|
||||
from .main import Newznab
|
||||
|
||||
|
||||
def start():
|
||||
return Newznab()
|
||||
|
||||
config = []
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user