def get_torrent_info(url): from bs4 import BeautifulSoup from xbmctorrent.utils import first, url_get response = url_get(url) soup = BeautifulSoup(response, "html5lib") movie = first(soup.select('td[itemtype="http://schema.org/Product"] div.font11px a[href="/movies/"]')) is not None serie = first(soup.select('td[itemtype="http://schema.org/Product"] div.font11px a[href="/tv/"]')) is not None def itemprop(prop, default=None): node = first(soup.select('[itemprop="%s"]' % prop)) return node and node.text or default def itemprops(prop, default=[]): nodes = soup.select('[itemprop="%s"]' % prop) return [node.text for node in nodes] or default return { "movie": movie and not serie, "serie": serie and not movie, "seeders": itemprop("seeders"), "leechers": itemprop("leechers"), "title": itemprop("name"), "quality": itemprop("quality"), "genres": itemprops("genre"), "magnet_url": first(soup.select(".magnetlinkButton"))["href"], "poster": first(soup.select('a.movieCover img'), {}).get("href"), "cast": [cast.text for cast in soup.select('[itemprop="name"] a')], "imdb_id": find_imdb_id(soup), }
def eztv_get_show_seasons(show_id): import random import re from itertools import groupby from concurrent import futures from xbmctorrent.utils import first, terminating, url_get from xbmctorrent import tvdb plugin.set_content("seasons") tvdb_id = first(plugin.request.args.get("tvdb_id")) with futures.ThreadPoolExecutor(max_workers=2) as pool: def _eztv_get_show(): plugin.log.info("Getting show") response = url_get("%s/shows/%s/" % (BASE_URL, show_id), headers=HEADERS) plugin.log.info("Got show") return response seasons_html = pool.submit(_eztv_get_show) if tvdb_id: tvdb_show = pool.submit(tvdb.get_all_meta, plugin.request.args["tvdb_id"][0]) seasons_html = seasons_html.result() fanarts = [] seasons = {} iter_list = re.findall(r'<a .*?class="epinfo".*?>(.*?)</a.*?>', seasons_html) for node_episode in iter_list: season, episode = get_episode_data_from_name(node_episode) seasons.setdefault(season, {})[episode] = True if tvdb_id: tvdb_show = tvdb_show.result() fanarts = list([ banner for banner in tvdb_show["banners"] if banner["bannertype"] == "fanart" ]) random.shuffle(fanarts) for i, season in enumerate(reversed(sorted(seasons.keys()))): item = tvdb_id and tvdb.get_season_list_item(tvdb_show, season) or {} item.update({ "label": "Season %d [%d episodes]" % (season, len(seasons[season])), "path": plugin.url_for("eztv_get_episodes_for_season", show_id=show_id, season=season, tvdb_id=tvdb_id), }) if fanarts: item.setdefault("properties", {}).update({ "fanart_image": fanarts[i % len(fanarts)]["bannerpath"], }) yield item
def find_imdb_id(soup): import re from xbmctorrent.utils import first imdb_node = first(soup.find_all("a", href=re.compile("imdb"))) if imdb_node: result = re.search(r".*(tt\d+).*", imdb_node["href"]) if result: return result.group(1)
def rutor_play(tid, pulsar): from contextlib import closing from bencode import bdecode from urlparse import urljoin from xbmctorrent.magnet import generate_magnet from xbmctorrent.utils import first, SafeDialogProgress from xbmctorrent.acestream import ace_supported with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Получение информации о раздаче...") torrent_url = urljoin(BASE_URL, "download/%s" % tid) try: metadata = bdecode(url_get(torrent_url, headers=HEADERS)) except Exception: import xbmcgui plugin.log.error("Unexpected error: %s" % sys.exc_info()[0]) xbmcgui.Dialog().ok(plugin.name, "Не удалось получить данные от сервера") return dialog.update(percent=100, line1="Готово") if "files" in metadata["info"]: # and ace_supported(): items = [] for index, info in enumerate(metadata["info"]["files"]): name = "/".join(info["path"]) if not _rutor_valid_file(name): continue if plugin.get_setting("torrent_engine", int) == 1 and ace_supported(): path = plugin.url_for("torrent_play", url=torrent_url, index=index, name=name) else: path = plugin.url_for("play_file", uri=generate_magnet(metadata, name), index=index) items.append({"label": name, "path": path}) items = sorted(items, key=lambda x: x["label"]) if len(items) == 1: # start playback if torrent contains only one file plugin.redirect(items[0]["path"]) else: # ask to select which file to play import xbmcgui select_items = [item["label"] for item in items] select = xbmcgui.Dialog().select("Выберите файл для проигрывания", select_items) if select >= 0: plugin.redirect(items[select]["path"]) else: name = metadata["info"].get("name") or " / ".join(first(metadata["info"]["files"])["path"]) or "rutor.org" if plugin.get_setting("torrent_engine", int) == 1 and ace_supported(): path = plugin.url_for("torrent_play", url=torrent_url, index=0, name=name) else: path = plugin.url_for(["play", "play_with_pulsar"][int(pulsar)], uri=generate_magnet(metadata, name)) plugin.redirect(path)
def rutracker_play(tid, pulsar): from contextlib import closing from bencode import bdecode from urlparse import urljoin from xbmctorrent.magnet import generate_magnet from xbmctorrent.utils import first, SafeDialogProgress from xbmctorrent.acestream import ace_supported with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Получение информации о раздаче...") try: data = url_get(urljoin(BASE_URL, "dl.php?t=%s" % tid)) metadata = bdecode(data) except Exception: plugin.log.error("Unexpected error: %s " % format_exc().split('\n')[-2]) xbmcgui.Dialog().ok(plugin.name, "Не удалось получить данные от сервера") return dialog.update(percent=100, line1="Готово") if "files" in metadata["info"]: # and ace_supported(): items = [] for index, info in enumerate(metadata["info"]["files"]): name = "/".join(info["path"]) decname = _rutracker_decode_try(name) if not _rutracker_valid_file(decname): continue name = uenc(decname) if plugin.get_setting("torrent_engine", int) == 1 and ace_supported(): path = plugin.url_for("play_torrent_raw", raw=data, index=index, name=name) else: path = plugin.url_for("play_file", uri=generate_magnet(metadata, name), index=index) items.append({"label": name, "path": path}) if len(items) == 1: # start playback if torrent contains only one file plugin.redirect(items[0]["path"]) else: select_items = [item["label"] for item in items] select = xbmcgui.Dialog().select("Выберите файл для проигрывания", select_items) if select >= 0: plugin.redirect(items[select]["path"]) else: name = metadata["info"].get("name") or " / ".join(first(metadata["info"]["files"])["path"]) or "rutracker.org" if plugin.get_setting("torrent_engine", int) == 1 and ace_supported(): path = plugin.url_for("play_torrent_raw", raw=data, index=0, name=name) else: path = plugin.url_for(["play", "play_with_pulsar"][int(pulsar)], uri=generate_magnet(metadata, name)) plugin.redirect(path)
def eztv_get_show_seasons(show_id): import random from bs4 import BeautifulSoup from itertools import groupby from multiprocessing.pool import ThreadPool from xbmctorrent.utils import first, terminating, url_get from xbmctorrent import tvdb # plugin.set_content("seasons") tvdb_id = first(plugin.request.args.get("tvdb_id")) with terminating(ThreadPool(2)) as pool: def _eztv_get_show(): plugin.log.info("Getting show") response = url_get("http://eztv.it/shows/%s/" % show_id, headers=HEADERS) plugin.log.info("Got show") return BeautifulSoup(response, "html5lib") soup = pool.apply_async(_eztv_get_show) if tvdb_id: tvdb_show = pool.apply_async(tvdb.get_all_meta, [plugin.request.args["tvdb_id"][0]]) soup = soup.get() fanarts = [] if tvdb_id: tvdb_show = tvdb_show.get() fanarts = list([banner for banner in tvdb_show["banners"] if banner["bannertype"] == "fanart"]) random.shuffle(fanarts) for node in soup.findAll("a", "epinfo"): if get_episode_data_from_name(node.text)[0] < 0: plugin.redirect(plugin.url_for("eztv_get_episodes_for_season", show_id=show_id, season=-1, tvdb_id=tvdb_id)) return # This is needed because we need to be able to redirect if no seasons are found. items = [] for i, (season, episodes) in enumerate(groupby(soup.findAll("a", "epinfo"), lambda node: get_episode_data_from_name(node.text)[0])): if tvdb_id: item = tvdb.get_season_list_item(tvdb_show, season) else: item = { "label": "Season %d" % season } item.update({ "path": plugin.url_for("eztv_get_episodes_for_season", show_id=show_id, season=season, tvdb_id=tvdb_id), }) # if fanarts: item.setdefault("properties", {}).update({ "fanart_image": fanarts[i % len(fanarts)]["bannerpath"], }) items.append(item) return items
def get_torrent_info(url): from bs4 import BeautifulSoup from xbmctorrent.utils import first, url_get response = url_get(url) soup = BeautifulSoup(response, "html5lib") movie = first( soup.select( 'td[itemtype="http://schema.org/Product"] div.font11px a[href="/movies/"]' )) is not None serie = first( soup.select( 'td[itemtype="http://schema.org/Product"] div.font11px a[href="/tv/"]' )) is not None def itemprop(prop, default=None): node = first(soup.select('[itemprop="%s"]' % prop)) return node and node.text or default def itemprops(prop, default=[]): nodes = soup.select('[itemprop="%s"]' % prop) return [node.text for node in nodes] or default return { "movie": movie and not serie, "serie": serie and not movie, "seeders": itemprop("seeders"), "leechers": itemprop("leechers"), "title": itemprop("name"), "quality": itemprop("quality"), "genres": itemprops("genre"), "magnet_url": first(soup.select(".magnetlinkButton"))["href"], "poster": first(soup.select('a.movieCover img'), {}).get("href"), "cast": [cast.text for cast in soup.select('[itemprop="name"] a')], "imdb_id": find_imdb_id(soup), }
def eztv_get_show_seasons(show_id): import random import re from itertools import groupby from concurrent import futures from xbmctorrent.utils import first, terminating, url_get from xbmctorrent import tvdb plugin.set_content("seasons") tvdb_id = first(plugin.request.args.get("tvdb_id")) with futures.ThreadPoolExecutor(max_workers=2) as pool: def _eztv_get_show(): plugin.log.info("Getting show") response = url_get("%s/shows/%s/" % (BASE_URL, show_id), headers=HEADERS) plugin.log.info("Got show") return response seasons_html = pool.submit(_eztv_get_show) if tvdb_id: tvdb_show = pool.submit(tvdb.get_all_meta, plugin.request.args["tvdb_id"][0]) seasons_html = seasons_html.result() fanarts = [] seasons = {} iter_list = re.findall(r'<a .*?class="epinfo".*?>(.*?)</a.*?>', seasons_html) for node_episode in iter_list: season, episode = get_episode_data_from_name(node_episode) seasons.setdefault(season, {})[episode] = True if tvdb_id: tvdb_show = tvdb_show.result() fanarts = list([banner for banner in tvdb_show["banners"] if banner["bannertype"] == "fanart"]) random.shuffle(fanarts) for i, season in enumerate(reversed(sorted(seasons.keys()))): item = tvdb_id and tvdb.get_season_list_item(tvdb_show, season) or {} item.update({ "label": "Season %d [%d episodes]" % (season, len(seasons[season])), "path": plugin.url_for("eztv_get_episodes_for_season", show_id=show_id, season=season, tvdb_id=tvdb_id), }) if fanarts: item.setdefault("properties", {}).update({ "fanart_image": fanarts[i % len(fanarts)]["bannerpath"], }) yield item
def itemprop(prop, default=None): node = first(soup.select('[itemprop="%s"]' % prop)) return node and node.text or default
def display_name(magnet_uri): import urlparse from xbmctorrent.utils import first magnet_args = urlparse.parse_qs(magnet_uri.replace("magnet:?", "")) return first(magnet_args.get("dn", []))
def rutracker_play(tid, pulsar): from copy import deepcopy from contextlib import closing from bencode import bencode, bdecode from urlparse import urljoin from xbmctorrent.magnet import generate_magnet from xbmctorrent.utils import first, SafeDialogProgress, get_quality_from_name, get_current_list_item from xbmctorrent.acestream import ace_supported with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Получение информации о раздаче...") torrent_url = urljoin("http://dl.rutracker.org/forum/", "dl.php?t=%s" % tid) try: plugin.log.debug("loading data from uri: " + torrent_url) params = {"t": tid} import os, xbmc, cookielib cookie = cookielib.Cookie(version=0, name='bb_dl', value=tid, port=None, port_specified=False, domain='.rutracker.org', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False) data = url_get(torrent_url, headers=HEADERS, post=params, cookie=cookie) metadata = bdecode(data) plugin.log.debug("Metadata received " + str(metadata)) except: import xbmcgui plugin.log.error("Unexpected error: %s " % format_exc().split('\n')[-2]) xbmcgui.Dialog().ok(plugin.name, "Не удалось получить данные от сервера") return dialog.update(percent=100, line1="Готово") # Get currently selected item current_item = get_current_list_item() current_item.setdefault("stream_info", {}).update( get_quality_from_name(current_item['label'])) if "files" in metadata["info"] and ace_supported(): items = {} for index, info in enumerate(metadata["info"]["files"]): name = "/".join(info["path"]) if not _rutracker_valid_file(name): continue items[index] = deepcopy(current_item) items[index].update({ "label": name, "path": plugin.url_for("play_torrent_raw", raw=data, index=index, name=name), "is_playable": True }) items[index].setdefault("info", {}).update({ "title": name, }) # start playback if torrent contains only one file if len(items) == 1: index, item = items.popitem() if not plugin.get_setting("force_ace", bool): item["path"] = plugin.url_for("play", uri=generate_magnet( metadata, item["label"])) plugin.play_video(item) yield item else: plugin.add_sort_method('label') for i in items.values(): yield i else: name = metadata["info"].get("name") or " / ".join( first(metadata["info"]["files"])["path"]) or "rutor.org" if plugin.get_setting("force_ace", bool) and ace_supported(): current_item["path"] = plugin.url_for("play_torrent_raw", raw=data, index=0, name=name) else: current_item["path"] = plugin.url_for( ["play", "play_with_pulsar"][int(pulsar)], uri=generate_magnet(metadata, name)) current_item["is_playable"] = True plugin.play_video(current_item) yield current_item
def get_studio(): return (first(sorted(m("production_companies") or [], key=lambda x: x["id"])) or {}).get("name") or ""
def m_crew(job): return first([crew["name"] for crew in (m("credits", default={}).get("crew") or []) if crew["job"] == job])
def eztv_get_episodes_for_season(show_id, season): import copy import random from bs4 import BeautifulSoup from itertools import izip from concurrent import futures from xbmctorrent.utils import first, terminating, url_get from xbmctorrent import tvdb plugin.set_content("episodes") season = int(season) tvdb_id = first(plugin.request.args.get("tvdb_id")) with futures.ThreadPoolExecutor(max_workers=2) as pool: def _eztv_get_show(): return BeautifulSoup(url_get("%s/shows/%s/" % (BASE_URL, show_id), headers=HEADERS), "html5lib") soup = pool.submit(_eztv_get_show) if tvdb_id: tvdb_show = pool.submit(tvdb.get_all_meta, plugin.request.args["tvdb_id"][0]) soup = soup.result() items = [] fanarts = [] if tvdb_id: tvdb_show = tvdb_show.result() fanarts = list([banner for banner in tvdb_show["banners"] if banner["bannertype"] == "fanart"]) random.shuffle(fanarts) items = list(tvdb.build_episode_list_items(tvdb_show, int(season))) text_nodes = soup.findAll("a", "epinfo") href_nodes = soup.findAll("a", "magnet") season_nodes = izip(text_nodes, href_nodes) season_nodes = filter(lambda x: get_episode_data_from_name(x[0].text)[0] == season, season_nodes) for i, (node_text, node_magnet) in enumerate(season_nodes): season, episode = get_episode_data_from_name(node_text.text) if tvdb_id and episode >= 0: item = copy.deepcopy(items[int(episode) - 1]) for pattern, suffix in (("720p", "(HD)"), ("1080p", "(FullHD)"), ("repack", "(REPACK)"), ("proper", "(PROPER)")): if pattern in node_text.text.lower(): item["label"] = "%s %s" % (item["label"], suffix) else: item = { "label": node_text.text, } item.setdefault("info", {}).update({ "tvshowtitle": node_text.text, "title": item["label"], "season": season, "episode": episode, }) stream_info = {} if "x264" in node_text.text: stream_info["codec"] = item["info"]["video_codec"] = "h264" if "xvid" in node_text.text.lower(): stream_info["codec"] = item["info"]["video_codec"] = "xvid" if "720p" in node_text.text: stream_info["width"] = 1280 stream_info["height"] = 720 if "1080p" in node_text.text: stream_info["width"] = 1920 stream_info["height"] = 1080 item.update({ "path": plugin.url_for("play", uri=node_magnet["href"]), "stream_info": {"video": stream_info}, "is_playable": True, }) if fanarts: item.setdefault("properties", {}).update({ "fanart_image": fanarts[i % len(fanarts)]["bannerpath"], }) yield item
def rutor_play(tid, pulsar): from copy import deepcopy from contextlib import closing from bencode import bencode, bdecode from urlparse import urljoin from xbmctorrent.magnet import generate_magnet from xbmctorrent.utils import first, SafeDialogProgress, get_quality_from_name, get_current_list_item from xbmctorrent.acestream import ace_supported with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Получение информации о раздаче...") torrent_url = urljoin(DOWNLOAD_URL, "download/%s" % tid) try: metadata = bdecode(url_get(torrent_url, headers=HEADERS)) except: import xbmcgui plugin.log.error("Unexpected error: %s" % sys.exc_info()[0]) xbmcgui.Dialog().ok(plugin.name, "Не удалось получить данные от сервера") return dialog.update(percent=100, line1="Готово") # Get currently selected item current_item = get_current_list_item() current_item.setdefault("stream_info", {}).update(get_quality_from_name(current_item['label'])) if "files" in metadata["info"] and ace_supported(): items = {} for index, info in enumerate(metadata["info"]["files"]): name = "/".join(info["path"]) if not _rutor_valid_file(name): continue items[index] = deepcopy(current_item) items[index].update({ "label" : name, "path" : plugin.url_for("torrent_play", url=torrent_url, index=index, name=name), "is_playable" : True }) items[index].setdefault("info",{}).update({ "title" : name, }) # start playback if torrent contains only one file if len(items) == 1: index, item = items.popitem() if not plugin.get_setting("force_ace", bool): item["path"] = plugin.url_for("play", uri=generate_magnet(metadata, item["label"])) plugin.play_video(item) yield item else: plugin.add_sort_method('label') for i in items.values(): yield i else: name = metadata["info"].get("name") or " / ".join(first(metadata["info"]["files"])["path"]) or "rutor.org" if plugin.get_setting("force_ace", bool) and ace_supported(): current_item["path"] = plugin.url_for("torrent_play", url=torrent_url, index=0, name=name) else: current_item["path"] = plugin.url_for(["play","play_with_pulsar"][int(pulsar)], uri=generate_magnet(metadata, name)) current_item["is_playable"] = True plugin.play_video(current_item) yield current_item
def rutor_play(tid, pulsar): from copy import deepcopy from contextlib import closing from bencode import bencode, bdecode from urlparse import urljoin from xbmctorrent.magnet import generate_magnet from xbmctorrent.utils import first, SafeDialogProgress, get_quality_from_name, get_current_list_item from xbmctorrent.acestream import ace_supported with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Получение информации о раздаче...") torrent_url = urljoin(DOWNLOAD_URL, "download/%s" % tid) try: metadata = bdecode(url_get(torrent_url, headers=HEADERS)) except: import xbmcgui plugin.log.error("Unexpected error: %s" % sys.exc_info()[0]) xbmcgui.Dialog().ok(plugin.name, "Не удалось получить данные от сервера") return dialog.update(percent=100, line1="Готово") # Get currently selected item current_item = get_current_list_item() current_item.setdefault("stream_info", {}).update( get_quality_from_name(current_item['label'])) if "files" in metadata["info"] and ace_supported(): items = {} for index, info in enumerate(metadata["info"]["files"]): name = "/".join(info["path"]) if not _rutor_valid_file(name): continue items[index] = deepcopy(current_item) items[index].update({ "label": name, "path": plugin.url_for("torrent_play", url=torrent_url, index=index, name=name), "is_playable": True }) items[index].setdefault("info", {}).update({ "title": name, }) # start playback if torrent contains only one file if len(items) == 1: index, item = items.popitem() if not plugin.get_setting("force_ace", bool): item["path"] = plugin.url_for("play", uri=generate_magnet( metadata, item["label"])) plugin.play_video(item) yield item else: plugin.add_sort_method('label') for i in items.values(): yield i else: name = metadata["info"].get("name") or " / ".join( first(metadata["info"]["files"])["path"]) or "rutor.org" if plugin.get_setting("force_ace", bool) and ace_supported(): current_item["path"] = plugin.url_for("torrent_play", url=torrent_url, index=0, name=name) else: current_item["path"] = plugin.url_for( ["play", "play_with_pulsar"][int(pulsar)], uri=generate_magnet(metadata, name)) current_item["is_playable"] = True plugin.play_video(current_item) yield current_item
def m_crew(job): return first([ crew["name"] for crew in (m("credits", default={}).get("crew") or []) if crew["job"] == job ])
def kickass_page(root, page): import re import xbmc import xbmcgui from bs4 import BeautifulSoup from contextlib import closing from concurrent import futures from urlparse import urljoin from xbmctorrent import tmdb from xbmctorrent.utils import first, terminating, url_get, get_quality_from_name content_type = first(plugin.request.args.get("content_type")) or None if content_type: plugin.set_content(content_type) page = int(page) page_data = url_get(urljoin(BASE_URL, "%s/%d" % (root, page))) soup = BeautifulSoup(page_data, "html5lib") torrent_nodes = [node.parent for node in soup.findAll("td", "torrentnameCell")] def _get_torrent_info_with_meta(url): torrent_info = get_torrent_info(url) if torrent_info["movie"] and torrent_info["imdb_id"]: torrent_info["tmdb"] = tmdb.get(torrent_info["imdb_id"]) return torrent_info with closing(xbmcgui.DialogProgress()) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching torrent information...", line2="", line3="") state = {"done": 0} def on_torrent(future): data = future.result() state["done"] += 1 dialog.update( percent=int(state["done"] * 100.0 / len(torrent_nodes)), line2=data.get("title") or "", ) with futures.ThreadPoolExecutor(max_workers=3) as pool: movies = [] for node in torrent_nodes: info_nodes = node.findAll("td") a_node = first(info_nodes[0].select("div.torrentname a.plain")) movies.append(pool.submit(_get_torrent_info_with_meta, urljoin(BASE_URL, a_node["href"]))) [future.add_done_callback(on_torrent) for future in movies] while not all(job.done() for job in movies): if dialog.iscanceled(): return xbmc.sleep(100) movies = [movie.result() for movie in movies] for i, movie in enumerate(movies): if movie.get("tmdb"): item = tmdb.get_list_item(movie["tmdb"]) proper_kat_title = re.sub("\s+", " ", re.sub(r"[().-]", " ", movie["title"])) item["label"] = "%s (%s)" % (item["label"], re.sub(r"(?i)%s" % item["label"], "", proper_kat_title).strip()) else: item = { "label": movie["title"], "info": { "genre": ", ".join(movie["genres"]), } } lower_title = movie["title"].lower() if "x264" in lower_title: item.setdefault("stream_info", {})["codec"] = item.setdefault("info", {})["video_codec"] = "h264" if "xvid" in lower_title: item.setdefault("stream_info", {})["codec"] = item.setdefault("info", {})["video_codec"] = "xvid" if "720p" in lower_title: item.setdefault("stream_info", {}).update({ "width": 1280, "height": 720, }) if "1080p" in lower_title: item.setdefault("stream_info", {}).update({ "width": 1920, "height": 1080, }) item.update({ "path": plugin.url_for("play", magnet=movie["magnet_url"]), "is_playable": True, }) item.setdefault("info", {}).update({ "count": i, "genre": "%s (S:%s P:%s)" % (item.get("info", {}).get("genre") or "", movie["seeders"], movie["leechers"]), }) item.setdefault("stream_info", {}).update({ "video": get_quality_from_name(movie["title"]), }) yield item yield { "label": "Next page...", "path": plugin.url_for("kickass_page", root=root, page=page + 1, content_type=content_type), }
def kickass_page(root, page): import re import xbmc import xbmcgui from bs4 import BeautifulSoup from contextlib import closing from concurrent import futures from urlparse import urljoin from xbmctorrent import tmdb from xbmctorrent.utils import first, terminating, url_get, get_quality_from_name content_type = first(plugin.request.args.get("content_type")) or None if content_type: plugin.set_content(content_type) page = int(page) page_data = url_get(urljoin(BASE_URL, "%s/%d" % (root, page))) soup = BeautifulSoup(page_data, "html5lib") torrent_nodes = [ node.parent for node in soup.findAll("td", "torrentnameCell") ] def _get_torrent_info_with_meta(url): torrent_info = get_torrent_info(url) if torrent_info["movie"] and torrent_info["imdb_id"]: torrent_info["tmdb"] = tmdb.get(torrent_info["imdb_id"]) return torrent_info with closing(xbmcgui.DialogProgress()) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching torrent information...", line2="", line3="") state = {"done": 0} def on_torrent(future): data = future.result() state["done"] += 1 dialog.update( percent=int(state["done"] * 100.0 / len(torrent_nodes)), line2=data.get("title") or "", ) with futures.ThreadPoolExecutor(max_workers=3) as pool: movies = [] for node in torrent_nodes: info_nodes = node.findAll("td") a_node = first(info_nodes[0].select("div.torrentname a.plain")) movies.append( pool.submit(_get_torrent_info_with_meta, urljoin(BASE_URL, a_node["href"]))) [future.add_done_callback(on_torrent) for future in movies] while not all(job.done() for job in movies): if dialog.iscanceled(): return xbmc.sleep(100) movies = [movie.result() for movie in movies] for i, movie in enumerate(movies): if movie.get("tmdb"): item = tmdb.get_list_item(movie["tmdb"]) proper_kat_title = re.sub("\s+", " ", re.sub(r"[().-]", " ", movie["title"])) item["label"] = "%s (%s)" % (item["label"], re.sub(r"(?i)%s" % item["label"], "", proper_kat_title).strip()) else: item = { "label": movie["title"], "info": { "genre": ", ".join(movie["genres"]), } } lower_title = movie["title"].lower() if "x264" in lower_title: item.setdefault("stream_info", {})["codec"] = item.setdefault( "info", {})["video_codec"] = "h264" if "xvid" in lower_title: item.setdefault("stream_info", {})["codec"] = item.setdefault( "info", {})["video_codec"] = "xvid" if "720p" in lower_title: item.setdefault("stream_info", {}).update({ "width": 1280, "height": 720, }) if "1080p" in lower_title: item.setdefault("stream_info", {}).update({ "width": 1920, "height": 1080, }) item.update({ "path": plugin.url_for("play", magnet=movie["magnet_url"]), "is_playable": True, }) item.setdefault("info", {}).update({ "count": i, "genre": "%s (S:%s P:%s)" % (item.get("info", {}).get("genre") or "", movie["seeders"], movie["leechers"]), }) item.setdefault("stream_info", {}).update({ "video": get_quality_from_name(movie["title"]), }) yield item yield { "label": "Next page...", "path": plugin.url_for("kickass_page", root=root, page=page + 1, content_type=content_type), }
def get_studio(): return (first( sorted(m("production_companies") or [], key=lambda x: x["id"])) or {}).get("name") or ""
def rutracker_play(tid, pulsar): from copy import deepcopy from contextlib import closing from bencode import bencode, bdecode from urlparse import urljoin from xbmctorrent.magnet import generate_magnet from xbmctorrent.utils import first, SafeDialogProgress, get_quality_from_name, get_current_list_item from xbmctorrent.acestream import ace_supported with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Получение информации о раздаче...") torrent_url = urljoin("http://dl.rutracker.org/forum/", "dl.php?t=%s" % tid) try: plugin.log.debug("loading data from uri: " + torrent_url) params = {"t": tid} import os, xbmc, cookielib cookie = cookielib.Cookie(version=0, name='bb_dl', value=tid, port=None, port_specified=False, domain='.rutracker.org', domain_specified=False, domain_initial_dot=False, path='/', path_specified=True, secure=False, expires=None, discard=True, comment=None, comment_url=None, rest={'HttpOnly': None}, rfc2109=False) data = url_get(torrent_url, headers=HEADERS, post=params, cookie=cookie) metadata = bdecode(data) plugin.log.debug("Metadata received " + str(metadata)) except: import xbmcgui plugin.log.error("Unexpected error: %s " % format_exc().split('\n')[-2]) xbmcgui.Dialog().ok(plugin.name, "Не удалось получить данные от сервера") return dialog.update(percent=100, line1="Готово") # Get currently selected item current_item = get_current_list_item() current_item.setdefault("stream_info", {}).update(get_quality_from_name(current_item['label'])) if "files" in metadata["info"] and ace_supported(): items = {} for index, info in enumerate(metadata["info"]["files"]): name = "/".join(info["path"]) if not _rutracker_valid_file(name): continue items[index] = deepcopy(current_item) items[index].update({ "label": name, "path": plugin.url_for("play_torrent_raw", raw=data, index=index, name=name), "is_playable": True }) items[index].setdefault("info", {}).update({ "title": name, }) # start playback if torrent contains only one file if len(items) == 1: index, item = items.popitem() if not plugin.get_setting("force_ace", bool): item["path"] = plugin.url_for("play", uri=generate_magnet(metadata, item["label"])) plugin.play_video(item) yield item else: plugin.add_sort_method('label') for i in items.values(): yield i else: name = metadata["info"].get("name") or " / ".join(first(metadata["info"]["files"])["path"]) or "rutor.org" if plugin.get_setting("force_ace", bool) and ace_supported(): current_item["path"] = plugin.url_for("play_torrent_raw", raw=data, index=0, name=name) else: current_item["path"] = plugin.url_for(["play","play_with_pulsar"][int(pulsar)], uri=generate_magnet(metadata, name)) current_item["is_playable"] = True plugin.play_video(current_item) yield current_item