Browse Source

[TV][Provider] Added Episode and Season providers for KickassTorrents

pull/4940/head
Jeroen Koekkoek 10 years ago
parent
commit
728e96a44d
  1. 152
      couchpotato/core/media/_base/providers/torrent/kickasstorrents.py
  2. 73
      couchpotato/core/media/movie/providers/torrent/kickasstorrents.py
  3. 34
      couchpotato/core/media/show/providers/torrent/kickasstorrents.py

152
couchpotato/core/media/_base/providers/torrent/kickasstorrents.py

@ -2,9 +2,11 @@ import re
import traceback import traceback
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
from couchpotato.core.helpers.variable import tryInt, getIdentifier from couchpotato.core.helpers.variable import tryInt
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.event import fireEvent
from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider from couchpotato.core.media._base.providers.torrent.base import TorrentMagnetProvider
from couchpotato.core.helpers.encoding import tryUrlencode
log = CPLog(__name__) log = CPLog(__name__)
@ -12,9 +14,20 @@ log = CPLog(__name__)
class Base(TorrentMagnetProvider): class Base(TorrentMagnetProvider):
COLUMN_NAME = 0
COLUMN_SIZE = 1
COLUMN_FILES = 2 # Unused
COLUMN_AGE = 3
COLUMN_SEEDS = 4
COLUMN_LEECHERS = 5
MAX_PAGES = 2
# The url for the first page containing search results is not postfixed
# with a page number, but providing it is allowed.
urls = { urls = {
'detail': '%s/%s', 'detail': '%s/%%s',
'search': '%s/%s-i%s/', 'search': '%s/usearch/%s/%d/',
} }
cat_ids = [ cat_ids = [
@ -24,6 +37,7 @@ class Base(TorrentMagnetProvider):
(['x264', '720p', '1080p', 'blu-ray', 'hdrip'], ['bd50', '1080p', '720p', 'brrip']), (['x264', '720p', '1080p', 'blu-ray', 'hdrip'], ['bd50', '1080p', '720p', 'brrip']),
(['dvdrip'], ['dvdrip']), (['dvdrip'], ['dvdrip']),
(['dvd'], ['dvdr']), (['dvd'], ['dvdr']),
(['hdtv'], ['hdtv'])
] ]
http_time_between_calls = 1 # Seconds http_time_between_calls = 1 # Seconds
@ -39,64 +53,105 @@ class Base(TorrentMagnetProvider):
'http://kickassto.come.in', 'http://kickassto.come.in',
] ]
def _search(self, media, quality, results):
data = self.getHTMLData(self.urls['search'] % (self.getDomain(), 'm', getIdentifier(media).replace('tt', '')))
if data: def _searchOnTitle(self, title, media, quality, results):
# _searchOnTitle can be safely implemented here because the existence
# of a _search method on the provider is checked first, in which case
# the KickassTorrents movie provider searches for the movie using the
# IMDB identifier as a key.
cat_ids = self.getCatId(quality) cat_ids = self.getCatId(quality)
table_order = ['name', 'size', None, 'age', 'seeds', 'leechers']
base_detail_url = self.urls['detail'] % (self.getDomain())
page = 1
pages = 1
referer_url = None
while page <= pages and page <= self.MAX_PAGES:
# The use of buildUrl might be required in the future to scan
# multiple pages of show results.
url = self.buildUrl(title = title, media = media, page = page)
if url and referer_url and url == referer_url:
break
data = self.getHTMLData(url)
try: try:
html = BeautifulSoup(data) html = BeautifulSoup(data)
resultdiv = html.find('div', attrs = {'class': 'tabs'}) table = html.find('table', attrs = {'class': 'data'})
for result in resultdiv.find_all('div', recursive = False): for tr in table.find_all('tr', attrs={'class': ['odd', 'even']}):
if result.get('id').lower().strip('tab-') not in cat_ids:
continue
try: try:
for temp in result.find_all('tr'): result = { }
if temp['class'] is 'firstr' or not temp.get('id'): column = 0
continue for td in tr.find_all('td'):
if column == self.COLUMN_NAME:
new = {} link = td.find('a', 'cellMainLink')
for tag in link.findAll(True):
nr = 0 tag.unwrap()
for td in temp.find_all('td'):
column_name = table_order[nr] result['id'] = tr['id'][-7:]
if column_name: result['name'] = link.text
result['url'] = td.find('a', 'imagnet')['href']
if column_name == 'name': result['detail_url'] = base_detail_url % (link['href'][1:])
link = td.find('div', {'class': 'torrentname'}).find_all('a')[2] if td.find('a', 'iverify'):
new['id'] = temp.get('id')[-7:] result['verified'] = True
new['name'] = link.text result['score'] = 100
new['url'] = td.find('a', 'imagnet')['href'] else:
new['detail_url'] = self.urls['detail'] % (self.getDomain(), link['href'][1:]) result['verified'] = False
new['verified'] = True if td.find('a', 'iverify') else False result['score'] = 0
new['score'] = 100 if new['verified'] else 0 elif column == self.COLUMN_SIZE:
elif column_name is 'size': result['size'] = self.parseSize(td.text)
new['size'] = self.parseSize(td.text) elif column == self.COLUMN_AGE:
elif column_name is 'age': result['age'] = self.ageToDays(td.text)
new['age'] = self.ageToDays(td.text) elif column == self.COLUMN_SEEDS:
elif column_name is 'seeds': result['seeders'] = tryInt(td.text, 0)
new['seeders'] = tryInt(td.text) elif column == self.COLUMN_LEECHERS:
elif column_name is 'leechers': result['leechers'] = tryInt(td.text, 0)
new['leechers'] = tryInt(td.text)
column += 1
nr += 1
if result:
# Only store verified torrents # The name must at least contain one category identifier
if self.conf('only_verified') and not new['verified']: score = 0
continue for cat_id in cat_ids:
if cat_id.lower() in result['name'].lower():
results.append(new) score += 1
break
if result['verified'] or not self.conf('only_verified'):
score += 1
if score == 2:
results.append(result)
buttons = html.find('div', 'pages')
if buttons:
pages = len(buttons.find_all(True, recursive = False))
except: except:
log.error('Failed parsing KickAssTorrents: %s', traceback.format_exc()) log.error('Failed parsing KickAssTorrents: %s', traceback.format_exc())
page += 1
referer_url = url
except AttributeError: except AttributeError:
log.debug('No search results found.') log.debug('No search results found.')
def buildUrl(self, *args, **kwargs):
# KickassTorrents also supports the "season:X episode:Y" parameters
# which would arguably make the search more robust, but we cannot use
# this mechanism because it might break searching for daily talk shows
# and the like, e.g. Jimmy Fallon.
media = kwargs.get('media', None)
title = kwargs.get('title', None)
page = kwargs.get('page', 1)
if not title and media:
title = fireEvent('library.query', media, single = True)
if not title:
return False
assert isinstance(page, (int, long))
return self.urls['search'] % (self.getDomain(), tryUrlencode(title), page)
def ageToDays(self, age_str): def ageToDays(self, age_str):
age = 0 age = 0
age_str = age_str.replace('&nbsp;', ' ') age_str = age_str.replace('&nbsp;', ' ')
@ -123,7 +178,6 @@ class Base(TorrentMagnetProvider):
def correctProxy(self, data): def correctProxy(self, data):
return 'search query' in data.lower() return 'search query' in data.lower()
config = [{ config = [{
'name': 'kickasstorrents', 'name': 'kickasstorrents',
'groups': [ 'groups': [

73
couchpotato/core/media/movie/providers/torrent/kickasstorrents.py

@ -1,3 +1,7 @@
import traceback
from bs4 import BeautifulSoup
from couchpotato.core.helpers.variable import tryInt, getIdentifier
from couchpotato.core.logger import CPLog from couchpotato.core.logger import CPLog
from couchpotato.core.media._base.providers.torrent.kickasstorrents import Base from couchpotato.core.media._base.providers.torrent.kickasstorrents import Base
from couchpotato.core.media.movie.providers.base import MovieProvider from couchpotato.core.media.movie.providers.base import MovieProvider
@ -8,4 +12,71 @@ autoload = 'KickAssTorrents'
class KickAssTorrents(MovieProvider, Base): class KickAssTorrents(MovieProvider, Base):
pass
urls = {
'detail': '%s/%s',
'search': '%s/%s-i%s/',
}
cat_ids = [
(['cam'], ['cam']),
(['telesync'], ['ts', 'tc']),
(['screener', 'tvrip'], ['screener']),
(['x264', '720p', '1080p', 'blu-ray', 'hdrip'], ['bd50', '1080p', '720p', 'brrip']),
(['dvdrip'], ['dvdrip']),
(['dvd'], ['dvdr']),
]
def _search(self, media, quality, results):
data = self.getHTMLData(self.urls['search'] % (self.getDomain(), 'm', getIdentifier(media).replace('tt', '')))
if data:
cat_ids = self.getCatId(quality)
try:
html = BeautifulSoup(data)
resultdiv = html.find('div', attrs = {'class': 'tabs'})
for result in resultdiv.find_all('div', recursive = False):
if result.get('id').lower().strip('tab-') not in cat_ids:
continue
try:
for temp in result.find_all('tr'):
if temp['class'] is 'firstr' or not temp.get('id'):
continue
new = {}
column = 0
for td in temp.find_all('td'):
if column == self.COLUMN_NAME:
link = td.find('div', {'class': 'torrentname'}).find_all('a')[2]
new['id'] = temp.get('id')[-7:]
new['name'] = link.text
new['url'] = td.find('a', 'imagnet')['href']
new['detail_url'] = self.urls['detail'] % (self.getDomain(), link['href'][1:])
new['verified'] = True if td.find('a', 'iverify') else False
new['score'] = 100 if new['verified'] else 0
elif column == self.COLUMN_SIZE:
new['size'] = self.parseSize(td.text)
elif column == self.COLUMN_AGE:
new['age'] = self.ageToDays(td.text)
elif column == self.COLUMN_SEEDS:
new['seeders'] = tryInt(td.text)
elif column == self.COLUMN_LEECHERS:
new['leechers'] = tryInt(td.text)
column += 1
# Only store verified torrents
if self.conf('only_verified') and not new['verified']:
continue
results.append(new)
except:
log.error('Failed parsing KickAssTorrents: %s', traceback.format_exc())
except AttributeError:
log.debug('No search results found.')

34
couchpotato/core/media/show/providers/torrent/kickasstorrents.py

@ -0,0 +1,34 @@
from couchpotato.core.logger import CPLog
from couchpotato.core.media._base.providers.base import MultiProvider
from couchpotato.core.media.show.providers.base import SeasonProvider, EpisodeProvider
from couchpotato.core.media._base.providers.torrent.kickasstorrents import Base
log = CPLog(__name__)
autoload = 'KickAssTorrents'
class KickAssTorrents(MultiProvider):
def getTypes(self):
return [Season, Episode]
class Season(SeasonProvider, Base):
urls = {
'detail': '%s/%%s',
'search': '%s/usearch/%s category:tv/%d/',
}
# buildUrl does not need an override
class Episode(EpisodeProvider, Base):
urls = {
'detail': '%s/%%s',
'search': '%s/usearch/%s category:tv/%d/',
}
# buildUrl does not need an override
Loading…
Cancel
Save