def piratebay_record(node): import re from xbmctorrent.utils import url_get from urlparse import urljoin from xbmctorrent import tmdb node.seeds, node.peers = map(lambda x: x.text, node.parent.parent.findAll("td")[2:]) node.magnet_node = node.parent.findAll("a")[1] node.desc_node = node.parent.findAll("font", "detDesc")[0] node.size = re.search("Size (.*?),", node.desc_node.text).group(1) node.txt = "%s (%s S:%s P:%s)" % (node.a.text, node.size.replace(" ", " "), node.seeds, node.peers) node.item = {} try: node.search_result = url_get(urljoin(BASE_URL, node.parent.findAll("a")[0]["href"]), headers=HEADERS) except: pass else: if node.search_result: try: node.imdb_url = re.search("http://www.imdb.com/title/tt[0-9]*", node.search_result).group(0) except: pass else: if node.imdb_url: node.imdb_id = re.search(r"(tt\d+)", node.imdb_url).group(0) if node.imdb_id: node.release_tags = tmdb.get_list_item(tmdb.get(node.imdb_id)) if node.release_tags: node.item.update(node.release_tags) node.item.update({ "label": node.txt, "path": plugin.url_for("play", uri=node.magnet_node["href"]), "is_playable": True, }) return node.item
def yify_show_data(callback): import xbmc import xbmcgui from contextlib import nested, closing from itertools import izip, chain from concurrent import futures from xbmctorrent import tmdb from xbmctorrent.utils import url_get_json, terminating, SafeDialogProgress plugin.set_content("movies") args = dict((k, v[0]) for k, v in plugin.request.args.items()) current_page = int(args["set"]) limit = int(args["limit"]) with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching movie information...", line2="", line3="") try: search_result = url_get_json("%s/api/list.json" % BASE_URL, params=args, headers=HEADERS) except: plugin.notify("Unable to connect to %s." % BASE_URL) raise movies = search_result.get("MovieList") or [] if not movies: return state = {"done": 0} def on_movie(future): data = future.result() state["done"] += 1 dialog.update( percent=int(state["done"] * 100.0 / len(movies)), line2=data.get("title") or data.get("MovieTitleClean") or "", ) with futures.ThreadPoolExecutor(max_workers=2) as pool_tmdb: tmdb_list = [pool_tmdb.submit(tmdb.get, movie["ImdbCode"]) for movie in movies] [future.add_done_callback(on_movie) for future in tmdb_list] while not all(job.done() for job in tmdb_list): if dialog.iscanceled(): return xbmc.sleep(100) tmdb_list = map(lambda job: job.result(), tmdb_list) for movie, tmdb_meta in izip(movies, tmdb_list): if tmdb_meta: item = tmdb.get_list_item(tmdb_meta) if args.get("quality") == "all" and movie["Quality"] != "720p": item["label"] = "%s (%s)" % (item["label"], movie["Quality"]) item.update({ "path": plugin.url_for("play", uri=movie["TorrentMagnetUrl"]), "is_playable": True, }) item.setdefault("info", {}).update({ "count": movie["MovieID"], "genre": "%s (%s S:%s P:%s)" % (item["info"]["genre"], movie["Size"], movie["TorrentSeeds"], movie["TorrentPeers"]), "plot_outline": tmdb_meta["overview"], "video_codec": "h264", }) width = 1920 height = 1080 if movie["Quality"] == "720p": width = 1280 height = 720 item.setdefault("stream_info", {}).update({ "video": { "codec": "h264", "width": width, "height": height, }, "audio": { "codec": "aac", }, }) yield item if current_page < (int(search_result["MovieCount"]) / limit): next_args = args.copy() next_args["set"] = int(next_args["set"]) + 1 yield { "label": ">> Next page", "path": plugin.url_for(callback, **next_args), }
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 parse(data, content_type=None): import xbmc import xml.etree.ElementTree as ET from itertools import izip_longest from concurrent import futures from contextlib import nested, closing from xbmctorrent.utils import SafeDialogProgress, get_quality_from_name, get_show_info_from_name, normalize_release_tags from xbmctorrent import tmdb root = ET.fromstring(data) def _text(node, path): n = node.find(path) if n is not None: return n.text def _attr(node, path, attrib): n = node.find(path) if n is not None: return n.attrib.get(attrib) items = [] for node in root.getiterator("item"): item = { "title": _text(node, "title"), "description": _text(node, "description"), "category": _text(node, "category"), "pub_date": _text(node, "pubDate"), "seeds": _text(node, ".//{%(torrent)s}seeds" % NSMAP) or _text(node, "numSeeders") or _text(node, "seeders"), "peers": _text(node, ".//{%(torrent)s}peers" % NSMAP) or _text(node, "numLeechers") or _text(node, "leechers"), "content_length": _text(node, ".//{%(torrent)s}contentLength" % NSMAP) or _attr(node, ".//enclosure", "length"), "href": _text(node, ".//{%(torrent)s}magnetURI" % NSMAP) or _attr(node, ".//enclosure", "url") or _text(node, "./link"), "filename": _text(node, ".//{%(torrent)s}fileName" % NSMAP), } find_image(item) check_imdb_id(item) items.append(item) tmdb_list = [] if content_type: with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching torrent information...", line2="", line3="") with futures.ThreadPoolExecutor(max_workers=POOL_WORKERS) as pool: futures = [] for item in items: if item.get("imdb_id"): futures.append(pool.submit(tmdb.get, item["imdb_id"])) else: futures.append(None) state = {"done": 0} def on_item(future): state["done"] += 1 dialog.update( percent=int(state["done"] * 100.0 / len(filter(None, futures))), ) [future.add_done_callback(on_item) for future in futures if future] while not all(future.done() for future in futures if future): if dialog.iscanceled(): return xbmc.sleep(100) tmdb_list = [future and future.result() or None for future in futures] for item, tmdb_data in izip_longest(items, tmdb_list): if tmdb_data: list_item = tmdb.get_list_item(tmdb_data) release_tags = normalize_release_tags(item["title"], list_item["label"]) if release_tags: list_item["label"] = "%s (%s)" % (list_item["label"], release_tags) else: list_item = { "label": item["title"], "icon": item.get("img") or "", "thumbnail": item.get("img") or "", "info": { "genre": item["category"], } } list_item.update({ "path": plugin.url_for("play", uri=item["href"]), "is_playable": True, }) list_item.setdefault("info", {}).update({ "genre": "%s (S:%s P:%s)" % (list_item.get("info", {}).get("genre") or "", item["seeds"], item["peers"]), }) list_item.setdefault("stream_info", {}).update(get_quality_from_name(item["title"])) yield list_item
def yify_show_data(callback): import xbmc import xbmcgui from contextlib import nested, closing from itertools import izip, chain from concurrent import futures from xbmctorrent import tmdb from xbmctorrent.utils import url_get_json, terminating, SafeDialogProgress plugin.set_content("movies") args = dict((k, v[0]) for k, v in plugin.request.args.items()) current_page = int(args["set"]) limit = int(args["limit"]) with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching movie information...", line2="", line3="") try: search_result = url_get_json("%s/api/list.json" % BASE_URL, params=args, headers=HEADERS) except: plugin.notify("Unable to connect to %s." % BASE_URL) raise movies = search_result.get("MovieList") or [] if not movies: return state = {"done": 0} def on_movie(future): data = future.result() state["done"] += 1 dialog.update( percent=int(state["done"] * 100.0 / len(movies)), line2=data.get("title") or data.get("MovieTitleClean") or "", ) with futures.ThreadPoolExecutor(max_workers=2) as pool_tmdb: tmdb_list = [ pool_tmdb.submit(tmdb.get, movie["ImdbCode"]) for movie in movies ] [future.add_done_callback(on_movie) for future in tmdb_list] while not all(job.done() for job in tmdb_list): if dialog.iscanceled(): return xbmc.sleep(100) tmdb_list = map(lambda job: job.result(), tmdb_list) for movie, tmdb_meta in izip(movies, tmdb_list): if tmdb_meta: magnet_link = urllib.quote_plus( movie["TorrentMagnetUrl"].encode("utf-8")) item = tmdb.get_list_item(tmdb_meta) if args.get("quality") == "all" and movie["Quality"] != "720p": item["label"] = "%s (%s)" % (item["label"], movie["Quality"]) item.update({ "path": "plugin://plugin.video.pulsar/play?uri=" + magnet_link, # "path": plugin.url_for("play", uri=movie["TorrentMagnetUrl"]), "is_playable": True, }) item.setdefault("info", {}).update({ "count": movie["MovieID"], "genre": "%s (%s S:%s P:%s)" % (item["info"]["genre"], movie["Size"], movie["TorrentSeeds"], movie["TorrentPeers"]), "plot_outline": tmdb_meta["overview"], "video_codec": "h264", }) width = 1920 height = 1080 if movie["Quality"] == "720p": width = 1280 height = 720 item.setdefault("stream_info", {}).update({ "video": { "codec": "h264", "width": width, "height": height, }, "audio": { "codec": "aac", }, }) yield item if current_page < (int(search_result["MovieCount"]) / limit): next_args = args.copy() next_args["set"] = int(next_args["set"]) + 1 yield { "label": ">> Next page", "path": plugin.url_for(callback, **next_args), }
def yify_show_data(callback): import xbmc import xbmcgui from contextlib import nested, closing from itertools import izip, chain from multiprocessing.pool import ThreadPool from xbmctorrent import tmdb from xbmctorrent.utils import url_get_json, terminating plugin.set_content("movies") args = dict((k, v[0]) for k, v in plugin.request.args.items()) current_page = int(args["set"]) limit = int(args["limit"]) with closing(xbmcgui.DialogProgress()) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching movie information...", line2="", line3="") search_result = url_get_json("%s/api/list.json" % BASE_URL, params=args, headers=HEADERS) movies = search_result["MovieList"] state = {"done": 0} def on_movie(data): state["done"] += 1 dialog.update( percent=int(state["done"] * 100.0 / (len(movies) * 2)), line2=data.get("title") or data.get("MovieTitleClean") or "", ) with nested(terminating(ThreadPool(2)), terminating(ThreadPool(2))) as (pool_yify, pool_tmdb): yify_list = [pool_yify.apply_async(yify_get, [movie["MovieID"]], callback=on_movie) for movie in movies] tmdb_list = [pool_tmdb.apply_async(tmdb.get, [movie["ImdbCode"]], callback=on_movie) for movie in movies] while not all(job.ready() for job in chain(yify_list, tmdb_list)): if dialog.iscanceled(): dialog.close() return xbmc.sleep(50) yify_list = map(lambda job: job.get(), yify_list) tmdb_list = map(lambda job: job.get(), tmdb_list) for movie, tmdb_meta in izip(yify_list, tmdb_list): if tmdb_meta: item = tmdb.get_list_item(tmdb_meta) if args.get("quality") == "all" and movie["Quality"] != "720p": item["label"] = "%s (%s)" % (item["label"], movie["Quality"]) item.update({ "path": plugin.url_for("play", magnet=movie["TorrentMagnetUrl"]), "is_playable": True, }) item.setdefault("info", {}).update({ "count": movie["MovieID"], "genre": "%s (%s S:%s P:%s)" % (item["info"]["genre"], movie["Size"], movie["TorrentSeeds"], movie["TorrentPeers"]), "trailer": YOUTUBE_ACTION % movie["YoutubeTrailerID"], "plot_outline": movie["ShortDescription"], "video_codec": "h264", "mpaa": movie["AgeRating"], }) width, height = map(int, movie["Resolution"].split("*")) item.setdefault("stream_info", {}).update({ "video": { "codec": "h264", "width": width, "height": height, "aspect": float(width) / float(height), }, "audio": { "codec": "aac", "language": movie["Language"], }, }) yield item if current_page < (int(search_result["MovieCount"]) / limit): next_args = args.copy() next_args["set"] = int(next_args["set"]) + 1 yield { "label": ">> Next page", "path": plugin.url_for(callback, **next_args), }
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 parse(data, content_type=None): import xbmc import xml.etree.ElementTree as ET from itertools import izip_longest from concurrent import futures from contextlib import nested, closing from xbmctorrent.utils import SafeDialogProgress, get_quality_from_name, get_show_info_from_name, normalize_release_tags from xbmctorrent import tmdb root = ET.fromstring(data) def _text(node, path): n = node.find(path) if n is not None: return n.text def _attr(node, path, attrib): n = node.find(path) if n is not None: return n.attrib.get(attrib) items = [] for node in root.getiterator("item"): item = { "title": _text(node, "title"), "description": _text(node, "description"), "category": _text(node, "category"), "pub_date": _text(node, "pubDate"), "seeds": _text(node, ".//{%(torrent)s}seeds" % NSMAP) or _text(node, "numSeeders") or _text(node, "seeders"), "peers": _text(node, ".//{%(torrent)s}peers" % NSMAP) or _text(node, "numLeechers") or _text(node, "leechers"), "content_length": _text(node, ".//{%(torrent)s}contentLength" % NSMAP) or _attr(node, ".//enclosure", "length"), "href": _text(node, ".//{%(torrent)s}magnetURI" % NSMAP) or _attr(node, ".//enclosure", "url") or _text(node, "./link"), "filename": _text(node, ".//{%(torrent)s}fileName" % NSMAP), } find_image(item) check_imdb_id(item) items.append(item) tmdb_list = [] if content_type: with closing(SafeDialogProgress(delay_close=0)) as dialog: dialog.create(plugin.name) dialog.update(percent=0, line1="Fetching torrent information...", line2="", line3="") with futures.ThreadPoolExecutor(max_workers=POOL_WORKERS) as pool: futures = [] for item in items: if item.get("imdb_id"): futures.append(pool.submit(tmdb.get, item["imdb_id"])) else: futures.append(None) state = {"done": 0} def on_item(future): state["done"] += 1 dialog.update(percent=int(state["done"] * 100.0 / len(filter(None, futures))), ) [ future.add_done_callback(on_item) for future in futures if future ] while not all(future.done() for future in futures if future): if dialog.iscanceled(): return xbmc.sleep(100) tmdb_list = [future and future.result() or None for future in futures] for item, tmdb_data in izip_longest(items, tmdb_list): if tmdb_data: list_item = tmdb.get_list_item(tmdb_data) release_tags = normalize_release_tags(item["title"], list_item["label"]) if release_tags: list_item["label"] = "%s (%s)" % (list_item["label"], release_tags) else: list_item = { "label": item["title"], "icon": item.get("img") or "", "thumbnail": item.get("img") or "", "info": { "genre": item["category"], } } list_item.update({ "path": plugin.url_for("play", uri=item["href"]), "is_playable": True, }) list_item.setdefault("info", {}).update({ "genre": "%s (S:%s P:%s)" % (list_item.get("info", {}).get("genre") or "", item["seeds"], item["peers"]), }) list_item.setdefault("stream_info", {}).update(get_quality_from_name(item["title"])) yield list_item