diff options
Diffstat (limited to 'plugin.video.hak5/resources')
-rw-r--r-- | plugin.video.hak5/resources/__init__.py | 1 | ||||
-rw-r--r-- | plugin.video.hak5/resources/images/fanart-blur.jpg | bin | 0 -> 525847 bytes | |||
-rw-r--r-- | plugin.video.hak5/resources/images/next-page.png | bin | 0 -> 14529 bytes | |||
-rw-r--r-- | plugin.video.hak5/resources/language/resource.language.en_gb/strings.po | 80 | ||||
-rw-r--r-- | plugin.video.hak5/resources/lib/__init__.py | 1 | ||||
-rw-r--r-- | plugin.video.hak5/resources/lib/hak5_const.py | 24 | ||||
-rw-r--r-- | plugin.video.hak5/resources/lib/hak5_list_episodes.py | 305 | ||||
-rw-r--r-- | plugin.video.hak5/resources/lib/hak5_list_seasons.py | 142 | ||||
-rw-r--r-- | plugin.video.hak5/resources/lib/hak5_main.py | 115 | ||||
-rw-r--r-- | plugin.video.hak5/resources/lib/hak5_play.py | 123 | ||||
-rw-r--r-- | plugin.video.hak5/resources/settings.xml | 0 |
11 files changed, 791 insertions, 0 deletions
diff --git a/plugin.video.hak5/resources/__init__.py b/plugin.video.hak5/resources/__init__.py new file mode 100644 index 0000000..309e220 --- /dev/null +++ b/plugin.video.hak5/resources/__init__.py @@ -0,0 +1 @@ +# Enables relative imports
\ No newline at end of file diff --git a/plugin.video.hak5/resources/images/fanart-blur.jpg b/plugin.video.hak5/resources/images/fanart-blur.jpg Binary files differnew file mode 100644 index 0000000..72139d8 --- /dev/null +++ b/plugin.video.hak5/resources/images/fanart-blur.jpg diff --git a/plugin.video.hak5/resources/images/next-page.png b/plugin.video.hak5/resources/images/next-page.png Binary files differnew file mode 100644 index 0000000..b12e695 --- /dev/null +++ b/plugin.video.hak5/resources/images/next-page.png diff --git a/plugin.video.hak5/resources/language/resource.language.en_gb/strings.po b/plugin.video.hak5/resources/language/resource.language.en_gb/strings.po new file mode 100644 index 0000000..ae509ad --- /dev/null +++ b/plugin.video.hak5/resources/language/resource.language.en_gb/strings.po @@ -0,0 +1,80 @@ +# XBMC Media Center language file +# Addon Name: Hak5 +# Addon id: plugin.video.hak5 +msgid "" +msgstr "" +"Project-Id-Version: XBMC-Addons\n" +"Report-Msgid-Bugs-To: alanwww1@xbmc.org\n" +"POT-Creation-Date: 2016-05-30 03:54+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" +"Language-Team: LANGUAGE\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en\n" +"Plural-Forms: nplurals=2; plural=(n != 1)\n" + +msgctxt "Addon Summary" +msgid "Watch videos from hak5.com" +msgstr "" + +msgctxt "Addon Description" +msgid "Watch videos from hak5.com. The videos are from the shows Hak5, Haktik, Threatwire, Tekthing, Pineapple University and Metasploit" +msgstr "" + +msgctxt "Addon Disclaimer" +msgid "For bugs, requests or general questions visit the hak5.com thread on the Kodi forum" +msgstr "" + +msgctxt "#30104" +msgid "Refresh" +msgstr "" + +msgctxt "#30105" +msgid "Episode Info" +msgstr "" + +msgctxt "#30106" +msgid "Error getting page: %s" +msgstr "" + +msgctxt "#30107" +msgid "No video found." +msgstr "" + +msgctxt "#30108" +msgid "Error playing media file." +msgstr "" + +msgctxt "#30200" +msgid "Next page" +msgstr "" + +msgctxt "#30301" +msgid "Recently Added Episodes" +msgstr "" + +msgctxt "#30302" +msgid "Hak5 Seasons" +msgstr "" + +msgctxt "#30303" +msgid "Haktik Recently Added Episodes" +msgstr "" + +msgctxt "#30304" +msgid "Threatwire Recently Added Episodes" +msgstr "" + +msgctxt "#30305" +msgid "Tekthing Recently Added Episodes" +msgstr "" + +msgctxt "#30306" +msgid "Pineapple University Recently Added Episodes" +msgstr "" + +msgctxt "#30307" +msgid "Metasploit Recently Added Episodes" +msgstr ""
\ No newline at end of file diff --git a/plugin.video.hak5/resources/lib/__init__.py b/plugin.video.hak5/resources/lib/__init__.py new file mode 100644 index 0000000..309e220 --- /dev/null +++ b/plugin.video.hak5/resources/lib/__init__.py @@ -0,0 +1 @@ +# Enables relative imports
\ No newline at end of file diff --git a/plugin.video.hak5/resources/lib/hak5_const.py b/plugin.video.hak5/resources/lib/hak5_const.py new file mode 100644 index 0000000..129de87 --- /dev/null +++ b/plugin.video.hak5/resources/lib/hak5_const.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +import os +import xbmcaddon + +# +# Constants +# +ADDON = "plugin.video.hak5" +SETTINGS = xbmcaddon.Addon() +LANGUAGE = SETTINGS.getLocalizedString +IMAGES_PATH = os.path.join(xbmcaddon.Addon().getAddonInfo('path'), 'resources', 'images') +HAK5RECENTLYADDEDURL = 'http://www.hak5.org/category/episodes' +HAK5SEASONSURLHTTP = 'http://www.hak5.org/category/episodes' +HAK5SEASONSURLHTTPS = 'https://www.hak5.org/category/episodes' +HAKTIKRECENTLYADDEDURL = 'http://www.hak5.org/category/episodes/haktip/page/001' +THREATWIRERECENTLYADDEDURL = 'http://www.hak5.org/category/episodes/threatwire/page/001' +TEKTHINGRECENTLYADDEDURL = 'http://www.hak5.org/category/episodes/tekthing/page/001' +PINEAPPLEUNIVERSITYRECENTLYADDEDURL = 'http://www.hak5.org/category/episodes/pineapple-university' +METASPLOITRECENTLYADDEDURL = 'http://www.hak5.org/category/episodes/metasploit-minute/page/001' +HEADERS = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'} +DATE = "2017-07-09" +VERSION = "1.0.0"
\ No newline at end of file diff --git a/plugin.video.hak5/resources/lib/hak5_list_episodes.py b/plugin.video.hak5/resources/lib/hak5_list_episodes.py new file mode 100644 index 0000000..5979c73 --- /dev/null +++ b/plugin.video.hak5/resources/lib/hak5_list_episodes.py @@ -0,0 +1,305 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# +# Imports +# +import os +import requests +import sys +import urllib +import urlparse +import re +import HTMLParser +import xbmc +import xbmcgui +import xbmcplugin +from BeautifulSoup import BeautifulSoup + +from hak5_const import ADDON, LANGUAGE, IMAGES_PATH, HEADERS, DATE, VERSION + +# +# Main class +# +class Main: + # + # Init + # + def __init__(self): + # Get the command line arguments + # Get the plugin url in plugin:// notation + self.plugin_url = sys.argv[0] + # Get the plugin handle as an integer number + self.plugin_handle = int(sys.argv[1]) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s, %s = %s" % ( + ADDON, VERSION, DATE, "ARGV", repr(sys.argv), "File", str(__file__)), xbmc.LOGDEBUG) + + # Parse parameters + self.video_list_page_url = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['url'][0] + self.next_page_possible = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['next_page_possible'][0] + + self.video_list_page_url = str(self.video_list_page_url).replace('https', 'http') + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "self.video_list_page_url", str(self.video_list_page_url)), + xbmc.LOGDEBUG) + + if self.next_page_possible == 'True': + # Determine current item number, next item number, next_url + pos_of_page = self.video_list_page_url.rfind('page/') + if pos_of_page >= 0: + page_number_str = str( + self.video_list_page_url[pos_of_page + len('page/'):pos_of_page + len('page/') + len('000')]) + page_number = int(page_number_str) + page_number_next = page_number + 1 + if page_number_next >= 100: + page_number_next_str = str(page_number_next) + elif page_number_next >= 10: + page_number_next_str = '0' + str(page_number_next) + else: + page_number_next_str = '00' + str(page_number_next) + self.next_url = str(self.video_list_page_url).replace(page_number_str, page_number_next_str) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "self.next_url", str(urllib.unquote_plus(self.next_url))), + xbmc.LOGDEBUG) + + # + # Get the videos... + # + self.getVideos() + + # + # Get videos... + # + def getVideos(self): + # + # Init + # + previous_video_page_url = '' + after_tab_episodes = False + # Create a list for our items. + listing = [] + + # + # Get HTML page + # + response = requests.get(self.video_list_page_url, headers=HEADERS) + html_source = response.text + html_source = html_source.encode('utf-8', 'ignore') + + # Parse response + soup = BeautifulSoup(html_source) + + # xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + # ADDON, VERSION, DATE, "html_source", str(html_source)), xbmc.LOGDEBUG) + + # <div id="post-8791" class="blog-item video-item post-8791 post type-post status-publish format-standard has-post-thumbnail hentry category-haktip ... + # <div class="row "> + # <div class="col-md-6 col-sm-6"> + # <div class="item-thumbnail"> + # <a href="https://www.hak5.org/episodes/season-22/hak5-2217-bushveld-b-roll-hack-across-the-planet" title="Hak5 2217 – Bushveld B-Roll – Hack Across the Planet"> + # <img width="300" height="169" src="https://www.hak5.org/wp-content/uploads/2017/07/hak5-2217-bushveld-b-roll-hack-a-300x169.jpg" ... + # </a> + # </div> + # <div class="clearfix"></div> + # </div><!--/col6--> + # <div class="col-md-6 col-sm-6"> + # <div class="item-head row"> + # <div class="col-md-10 col-sm-10 col-xs-9"> + # <h3><a class="maincolor2hover" href="https://www.hak5.org/episodes/season-22/hak5-2217-bushveld-b-roll-hack-across-the-planet" rel="8851" + # title="Hak5 2217 – Bushveld B-Roll – Hack Across the Planet">Hak5 2217 – Bushveld B-Roll – Hack Across the Planet</a></h3> + # <div class="blog-meta"> + # <span><a href="https://www.hak5.org/author/snubs" title="Posts by Shannon Morse" rel="author">Shannon Morse</a></span> | + # <span><a href="https://www.hak5.org/category/episodes/season-22" rel="category tag">Season 22</a></span> + # | + # <span><a href="https://www.hak5.org/episodes/season-22/hak5-2217-bushveld-b-roll-hack-across-the-planet#respond">0 Comments</a></span> + # </div> + # </div> + # <div class="col-md-2 col-sm-2 col-xs-3"> + # <div class="blog-date"> + # <span>05</span> + # <span>Jul</span> + # </div> + # </div> + # </div> + # <div class="blog-excerpt"> + # <p>Happy 4th of July! Sign up for the London meetup at https://HackAcrossThePlanet.com ——————————- Shop: ... + # <a href="https://www.hak5.org/episodes/season-22/hak5-2217-bushveld-b-roll-hack-across-the-planet" class="readmore maincolor2 bordercolor2 bgcolor2hover ... + # </div> + # </div><!--/col6--> + # </div><!--/row--> + # <div class="clearfix"></div> + # </div> + + episodes = soup.findAll('div', attrs={'id': re.compile("^" + 'post')}) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "len(episodes)", str(len(episodes))), xbmc.LOGDEBUG) + + for episode in episodes: + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "episode)", str(episode)), xbmc.LOGDEBUG) + + video_page_url = episode.a['href'] + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "video_page_url", str(video_page_url)), xbmc.LOGDEBUG) + + try: + thumbnail_url = episode.img['src'] + except: + thumbnail_url = '' + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "thumbnail_url", str(thumbnail_url)), xbmc.LOGDEBUG) + + title = episode.a['title'] + + # Clean up title + try: + title = title.encode('utf-8') + except: + pass + + title = title.replace('-', ' ') + title = title.replace('/', ' ') + title = title.replace(' i ', ' I ') + title = title.replace(' ii ', ' II ') + title = title.replace(' iii ', ' III ') + title = title.replace(' iv ', ' IV ') + title = title.replace(' v ', ' V ') + title = title.replace(' vi ', ' VI ') + title = title.replace(' vii ', ' VII ') + title = title.replace(' viii ', ' VIII ') + title = title.replace(' ix ', ' IX ') + title = title.replace(' x ', ' X ') + title = title.replace(' xi ', ' XI ') + title = title.replace(' xii ', ' XII ') + title = title.replace(' xiii ', ' XIII ') + title = title.replace(' xiv ', ' XIV ') + title = title.replace(' xv ', ' XV ') + title = title.replace(' xvi ', ' XVI ') + title = title.replace(' xvii ', ' XVII ') + title = title.replace(' xviii ', ' XVIII ') + title = title.replace(' xix ', ' XIX ') + title = title.replace(' xx ', ' XXX ') + title = title.replace(' xxi ', ' XXI ') + title = title.replace(' xxii ', ' XXII ') + title = title.replace(' xxiii ', ' XXIII ') + title = title.replace(' xxiv ', ' XXIV ') + title = title.replace(' xxv ', ' XXV ') + title = title.replace(' xxvi ', ' XXVI ') + title = title.replace(' xxvii ', ' XXVII ') + title = title.replace(' xxviii ', ' XXVIII ') + title = title.replace(' xxix ', ' XXIX ') + title = title.replace(' xxx ', ' XXX ') + title = title.replace(' ', ' ') + # welcome to unescaping-hell + title = title.replace('&#039;', "'") + title = title.replace('&#39;', "'") + title = title.replace('&quot;', '"') + title = title.replace("'", "'") + title = title.replace("'", "'") + title = title.replace('&amp;', '&') + title = title.replace('&', '&') + title = title.replace('"', '"') + title = title.replace('“', '"') + title = title.replace('”', '"') + title = title.replace('’', "'") + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "title", str(title)), xbmc.LOGDEBUG) + + # lets find the blog date month and year + search_for_string = 'https://www.hak5.org/wp-content/uploads/' + blog_date = episode.findAll('img', attrs={'src': re.compile('^' + search_for_string)}) + blog_date = str(blog_date) + blog_date_year_start_pos = blog_date.find(search_for_string) + len(search_for_string) + blog_date_year_end_pos = blog_date.find('/', blog_date_year_start_pos) + blog_date_year = blog_date[blog_date_year_start_pos: blog_date_year_end_pos] + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "blog_date_year)", str(blog_date_year)), xbmc.LOGDEBUG) + + blog_date_month_start_pos = blog_date_year_end_pos + 1 + blog_date_month_end_pos = blog_date_month_start_pos + 2 + blog_date_month = blog_date[blog_date_month_start_pos:blog_date_month_end_pos] + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "blog_date_month)", str(blog_date_month)), xbmc.LOGDEBUG) + + # lets find the blog date day + blog_date = episode.findAll('div', attrs={'class': re.compile("^" + 'blog-date')}) + blog_date = str(blog_date) + blog_date_day_start_pos = blog_date.find('<span>') + blog_date_day_end_pos = blog_date.find('</span>') + blog_date_day = blog_date[blog_date_day_start_pos + len('<span>'):blog_date_day_end_pos] + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "blog_date_day)", str(blog_date_day)), xbmc.LOGDEBUG) + + video_date = blog_date_year + '-' + blog_date_month + '-' + blog_date_day + ' 00:00:01' + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "video_date)", str(video_date)), xbmc.LOGDEBUG) + + # Unescaping the plot + try: + plot = HTMLParser.HTMLParser().unescape(episode.p.text) + except: + plot = title + + add_sort_methods() + + context_menu_items = [] + # Add refresh option to context menu + context_menu_items.append((LANGUAGE(30104), 'Container.Refresh')) + # Add episode info to context menu + context_menu_items.append((LANGUAGE(30105), 'XBMC.Action(Info)')) + + list_item = xbmcgui.ListItem(label=title, thumbnailImage=thumbnail_url) + list_item.setInfo("video", + {"title": title, "studio": ADDON, "dateadded": video_date, "year": blog_date_year, + "plot": plot}) + list_item.setInfo("mediatype", "video") + list_item.setArt({'thumb': thumbnail_url, 'icon': thumbnail_url, + 'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'true') + parameters = {"action": "play", "video_page_url": video_page_url, "title": title} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + is_folder = False + # Adding context menu items to context menu + list_item.addContextMenuItems(context_menu_items, replaceItems=False) + # Add our item to the listing as a 3-element tuple. + listing.append((url, list_item, is_folder)) + + # Next page entry + if self.next_page_possible == 'True': + list_item = xbmcgui.ListItem(LANGUAGE(30200), thumbnailImage=os.path.join(IMAGES_PATH, 'next-page.png')) + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + parameters = {"action": "list-episodes", "url": str(self.next_url), + "next_page_possible": self.next_page_possible} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + is_folder = True + # Adding context menu items to context menu + list_item.addContextMenuItems(context_menu_items, replaceItems=False) + # Add our item to the listing as a 3-element tuple. + listing.append((url, list_item, is_folder)) + + # Add our listing to Kodi. + # Large lists and/or slower systems benefit from adding all items at once via addDirectoryItems + # instead of adding one by ove via addDirectoryItem. + xbmcplugin.addDirectoryItems(self.plugin_handle, listing, len(listing)) + # Disable sorting + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_NONE) + # Finish creating a virtual folder. + xbmcplugin.endOfDirectory(self.plugin_handle) + +def add_sort_methods(): + sort_methods = [xbmcplugin.SORT_METHOD_UNSORTED,xbmcplugin.SORT_METHOD_LABEL,xbmcplugin.SORT_METHOD_DATE,xbmcplugin.SORT_METHOD_DURATION,xbmcplugin.SORT_METHOD_EPISODE] + for method in sort_methods: + xbmcplugin.addSortMethod(int(sys.argv[1]), sortMethod=method) diff --git a/plugin.video.hak5/resources/lib/hak5_list_seasons.py b/plugin.video.hak5/resources/lib/hak5_list_seasons.py new file mode 100644 index 0000000..b0544aa --- /dev/null +++ b/plugin.video.hak5/resources/lib/hak5_list_seasons.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# +# Imports +# +import os +import requests +import sys +import urllib +import urlparse +import re +import xbmc +import xbmcgui +import xbmcplugin +from BeautifulSoup import BeautifulSoup + +from hak5_const import ADDON, DATE, VERSION, IMAGES_PATH, HEADERS, HAK5SEASONSURLHTTPS, LANGUAGE + +# +# Main class +# +class Main: + def __init__(self): + # Get the command line arguments + # Get the plugin url in plugin:// notation + self.plugin_url = sys.argv[0] + # Get the plugin handle as an integer number + self.plugin_handle = int(sys.argv[1]) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s, %s = %s" % ( + ADDON, VERSION, DATE, "ARGV", repr(sys.argv), "File", str(__file__)), xbmc.LOGDEBUG) + + # Parse parameters... + self.plugin_category = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['plugin_category'][0] + self.video_list_page_url = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['url'][0] + self.next_page_possible = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['next_page_possible'][0] + + self.video_list_page_url = str(self.video_list_page_url).replace('https', 'http') + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "self.video_list_page_url", str(self.video_list_page_url)), + xbmc.LOGDEBUG) + + # + # Get the videos... + # + self.getVideos() + + # + # Get videos... + # + def getVideos(self): + # + # Init + # + # Create a list for our items. + listing = [] + + # + # Get HTML page... + # + response = requests.get(self.video_list_page_url, headers=HEADERS) + html_source = response.text + html_source = html_source.encode('utf-8', 'ignore') + + # <a href="https://www.hak5.org/category/episodes/season-22" class="menu-link sub-menu-link">Season 22 </a> + + # Parse response... + soup = BeautifulSoup(html_source) + + # xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + # ADDON, VERSION, DATE, "html_source", str(html_source)), xbmc.LOGDEBUG) + + seasons = soup.findAll('a', attrs={'href': re.compile("^" + HAK5SEASONSURLHTTPS)}) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "len(seasons)", str(len(seasons))), xbmc.LOGDEBUG) + + for season in seasons: + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "season", str(season)), xbmc.LOGDEBUG) + + # let's skip these links + # <a href="https://www.hak5.org/category/episodes/season-22" class="menu-link sub-menu-link">Season 22 </a> + if str(season).find("class=") > 0: + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % (ADDON, VERSION, DATE, "skipped season that contains class=", str(season)), xbmc.LOGDEBUG) + continue + + # let's skip these links + # <a href="https://www.hak5.org/category/episodes/season-22" rel="category tag">Season 22</a> + if str(season).find("rel=") > 0: + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % (ADDON, VERSION, DATE, "skipped season that contains rel=", str(season)), xbmc.LOGDEBUG) + continue + + # let's skip links that don't contain the word season + # <a title="Pineapple Uni" href="https://www.hak5.org/category/episodes/pineapple-university">Pineapple Uni</a> + if str(season).find("season") > 0: + pass + else: + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "skipped season that does not contain the word season", str(season)), xbmc.LOGDEBUG) + continue + + url = season['href'] + thumbnail_url = '' + title = season.text + + add_sort_methods() + + context_menu_items = [] + # Add refresh option to context menu + context_menu_items.append((LANGUAGE(30104), 'Container.Refresh')) + + # Add to list... + list_item = xbmcgui.ListItem(label=title, thumbnailImage=thumbnail_url) + list_item.setArt({'thumb': thumbnail_url, 'icon': thumbnail_url, + 'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + parameters = {"action": "list-episodes", "season_name": title, "url": url, "next_page_possible": "False", + "title": title} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + is_folder = True + # Adding context menu items to context menu + list_item.addContextMenuItems(context_menu_items, replaceItems=False) + # Add our item to the listing as a 3-element tuple. + listing.append((url, list_item, is_folder)) + + # Add our listing to Kodi. + # Large lists and/or slower systems benefit from adding all items at once via addDirectoryItems + # instead of adding one by ove via addDirectoryItem. + xbmcplugin.addDirectoryItems(self.plugin_handle, listing, len(listing)) + # Disable sorting + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_NONE) + # Finish creating a virtual folder. + xbmcplugin.endOfDirectory(self.plugin_handle) + +def add_sort_methods(): + sort_methods = [xbmcplugin.SORT_METHOD_UNSORTED,xbmcplugin.SORT_METHOD_LABEL,xbmcplugin.SORT_METHOD_DATE,xbmcplugin.SORT_METHOD_DURATION,xbmcplugin.SORT_METHOD_EPISODE] + for method in sort_methods: + xbmcplugin.addSortMethod(int(sys.argv[1]), sortMethod=method)
\ No newline at end of file diff --git a/plugin.video.hak5/resources/lib/hak5_main.py b/plugin.video.hak5/resources/lib/hak5_main.py new file mode 100644 index 0000000..49575a6 --- /dev/null +++ b/plugin.video.hak5/resources/lib/hak5_main.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# +# Imports +# +import sys +import urllib +import xbmcgui +import xbmcplugin +import os + +from hak5_const import LANGUAGE, IMAGES_PATH, HAK5RECENTLYADDEDURL, HAK5SEASONSURLHTTP, \ + HAKTIKRECENTLYADDEDURL, THREATWIRERECENTLYADDEDURL, TEKTHINGRECENTLYADDEDURL, PINEAPPLEUNIVERSITYRECENTLYADDEDURL, \ + METASPLOITRECENTLYADDEDURL +# +# Main class +# +class Main: + def __init__(self): + # Get the command line arguments + # Get the plugin url in plugin:// notation + self.plugin_url = sys.argv[0] + # Get the plugin handle as an integer number + self.plugin_handle = int(sys.argv[1]) + + # + # Hak5 Recently Added Episodes + # + parameters = {"action": "list-episodes", "plugin_category": LANGUAGE(30301), "url": HAK5RECENTLYADDEDURL, + "next_page_possible": "False"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30301)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # + # Hak5 Seasons + # + parameters = {"action": "list-seasons", "plugin_category": LANGUAGE(30302), "url": HAK5SEASONSURLHTTP, + "next_page_possible": "False"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30302)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # + # Haktik Recently Added Episodes + # + parameters = {"action": "list-episodes", "plugin_category": LANGUAGE(30303), + "url": HAKTIKRECENTLYADDEDURL, + "next_page_possible": "True"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30303)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # + # Threatwire Recently Added Episodes + # + parameters = {"action": "list-episodes", "plugin_category": LANGUAGE(30304), "url": THREATWIRERECENTLYADDEDURL, + "next_page_possible": "True"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30304)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # + # Tekthing Recently Added Episodes + # + parameters = {"action": "list-episodes", "plugin_category": LANGUAGE(30305), "url": TEKTHINGRECENTLYADDEDURL, + "next_page_possible": "True"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30305)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # + # Pinapple University Recently Added Episodes + # + parameters = {"action": "list-episodes", "plugin_category": LANGUAGE(30306), "url": PINEAPPLEUNIVERSITYRECENTLYADDEDURL, + "next_page_possible": "False"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30306)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # + # Metasploit Recently Added Episodes + # + parameters = {"action": "list-episodes", "plugin_category": LANGUAGE(30307), "url": METASPLOITRECENTLYADDEDURL, + "next_page_possible": "True"} + url = self.plugin_url + '?' + urllib.urlencode(parameters) + list_item = xbmcgui.ListItem(LANGUAGE(30307)) + is_folder = True + list_item.setArt({'fanart': os.path.join(IMAGES_PATH, 'fanart-blur.jpg')}) + list_item.setProperty('IsPlayable', 'false') + xbmcplugin.addDirectoryItem(handle=self.plugin_handle, url=url, listitem=list_item, isFolder=is_folder) + + # Disable sorting + xbmcplugin.addSortMethod(handle=self.plugin_handle, sortMethod=xbmcplugin.SORT_METHOD_NONE) + # Finish creating a virtual folder. + xbmcplugin.endOfDirectory(self.plugin_handle) diff --git a/plugin.video.hak5/resources/lib/hak5_play.py b/plugin.video.hak5/resources/lib/hak5_play.py new file mode 100644 index 0000000..685a992 --- /dev/null +++ b/plugin.video.hak5/resources/lib/hak5_play.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- + +# +# Imports +# +import requests +import sys +import urlparse +import xbmc +import xbmcgui +import xbmcplugin + +from hak5_const import ADDON, LANGUAGE, HEADERS, DATE, VERSION + +# +# Main class +# +class Main: + # + # Init + # + def __init__(self): + # Get the command line arguments + # Get the plugin url in plugin:// notation + self.plugin_url = sys.argv[0] + # Get the plugin handle as an integer number + self.plugin_handle = int(sys.argv[1]) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s, %s = %s" % ( + ADDON, VERSION, DATE, "ARGV", repr(sys.argv), "File", str(__file__)), xbmc.LOGDEBUG) + + # Parse parameters... + self.video_page_url = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['video_page_url'][0] + # Get the title. + self.title = urlparse.parse_qs(urlparse.urlparse(sys.argv[2]).query)['title'][0] + self.title = str(self.title) + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "self.video_page_url", str(self.video_page_url)), xbmc.LOGDEBUG) + + # + # Play video... + # + self.playVideo() + + # + # Play video... + # + def playVideo(self): + # + # Init + # + dialog_wait = xbmcgui.DialogProgress() + + # + # Get current list item details... + # + # title = unicode(xbmc.getInfoLabel("listitem.Title"), "utf-8") + thumbnail_url = xbmc.getInfoImage("list_item.Thumb") + # studio = unicode(xbmc.getInfoLabel("list_item.Studio"), "utf-8") + plot = unicode(xbmc.getInfoLabel("list_item.Plot"), "utf-8") + genre = unicode(xbmc.getInfoLabel("list_item.Genre"), "utf-8") + + reply = '' + session = '' + + # requests is sooooo nice, respect! + session = requests.Session() + + # get the page that contains the video + self.video_page_url = str(self.video_page_url).replace('https','http') + reply = requests.get(self.video_page_url, headers=HEADERS) + + html_source = reply.text + html_source = html_source.encode('utf-8', 'ignore') + + # xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + # ADDON, VERSION, DATE, "html_source", str(html_source)), xbmc.LOGDEBUG) + + video_url = '' + no_url_found = True + have_valid_url = False + + # <meta property="og:url" content="https://youtu.be/K_EOLgX5Dqs"/> + # let's extract the youtube-id + html_source = str(html_source) + start_pos_meta_prop = html_source.find('meta property="og:url"') + if start_pos_meta_prop > 0: + search_for_string = '"/>' + end_pos_meta_prop = html_source.find(search_for_string, start_pos_meta_prop) + if end_pos_meta_prop > 0: + # the last 3 characters are removed + meta_prop = html_source[start_pos_meta_prop: end_pos_meta_prop] + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "meta_prop", str(meta_prop)), xbmc.LOGDEBUG) + + pos_of_last_slash = meta_prop.rfind('/') + youtube_id = meta_prop[pos_of_last_slash + 1:] + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "youtube_id", str(youtube_id)), xbmc.LOGDEBUG) + + video_url = makeYouTubePluginUrl(youtube_id) + no_url_found = False + have_valid_url = True + + xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % ( + ADDON, VERSION, DATE, "video_url", str(video_url)), xbmc.LOGDEBUG) + + # Play video... + if have_valid_url: + list_item = xbmcgui.ListItem(path=video_url) + xbmcplugin.setResolvedUrl(self.plugin_handle, True, list_item) + # + # Alert user + # + elif no_url_found: + xbmcgui.Dialog().ok(LANGUAGE(30000), LANGUAGE(30107)) + +def makeYouTubePluginUrl(youtube_id): + return 'plugin://plugin.video.youtube/play/?video_id=%s' % youtube_id
\ No newline at end of file diff --git a/plugin.video.hak5/resources/settings.xml b/plugin.video.hak5/resources/settings.xml new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/plugin.video.hak5/resources/settings.xml |