#!/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) #
#
# # # #
#
#

Hak5 2216 – Pseudocode for Life 2 – Hack Across the Planet #

# #
# #
#
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) pos_of_title_start = str(episode).find('title="') + len('title="') pos_of_title_end = str(episode).find('"', pos_of_title_start) title = str(episode)[pos_of_title_start:pos_of_title_end] # 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(''', "'") title = title.replace(''', "'") title = title.replace('"', '"') title = title.replace("'", "'") title = title.replace("'", "'") title = title.replace('&', '&') 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('span', attrs={'class': re.compile("^" + 'item-date')}) if len(blog_date) == 0: blog_date_day = '00' else: blog_date = str(blog_date[0].text) blog_date_day_start_pos = blog_date.find(',') - 2 blog_date_day_end_pos = blog_date_day_start_pos + 2 blog_date_day = blog_date[blog_date_day_start_pos: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 xbmc.log("[ADDON] %s v%s (%s) debug mode, %s = %s" % (ADDON, VERSION, DATE, "plot", str(plot)), xbmc.LOGDEBUG) 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)