Provider restructure

This commit is contained in:
Ruud
2014-03-11 18:45:50 +01:00
parent 28661ab11a
commit 471229216a
181 changed files with 1118 additions and 779 deletions
+1 -4
View File
@@ -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': [],
},
],
}]
@@ -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__)
@@ -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__)
@@ -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)
@@ -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,0 +1,7 @@
from .main import BinSearch
def start():
return BinSearch()
config = []
@@ -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