def Table_Convert(url, contents={}, table=0): """ Open a web page which a table and pull out the contents of that table into a list of dictionaries with your own custom keys. CODE: Table_Convert(url, contents, table) AVAILABLE PARAMS: url - The url you want to open and pull data from contents - Send through a dictionary of the keys you want to assign to each of the cells. The format would be: {my_key : position} You can pull out as many cells as you want, so if your table has 10 columns but you only wanted to pull data for cells 2,4,5,6,8 then you could do so by setting contents to the following params: contents = {"name 1":2, "name 2":4, "name 3":5, "name 4":6, "name 5":8} table - By default this is set to zero, this is to be used if there's multiple tables on the page you're accessing. Remeber to start at zero, so if you want to access the 2nd table on the page it will be table=1. EXAMPLE CODE: dialog.ok('TABLE DATA','Let\'s pull some details from the proxy list table found at:\nhttps://free-proxy-list.net.') proxies = koding.Table_Convert(url='https://free-proxy-list.net', contents={"ip":0,"port":1}, table=0) mytext = '[COLOR dodgerblue]Here are some proxies:[/COLOR]\n' for item in proxies: mytext += '\nIP: %s\nPort: %s\n[COLOR steelblue]----------------[/COLOR]'%(item['ip'],item['port']) koding.Text_Box('MASTER PROXY LIST',mytext) ~""" from web import Open_URL from BeautifulSoup import BeautifulSoup table_list=[] content = Open_URL(url) if content: rawdata = Parse_XML(content,'table',['td']) # Work out the amount of columns in the table soup = BeautifulSoup(content) my_return = [] mytable = soup.findAll('table')[table] if mytable: newsoup = BeautifulSoup(str(mytable)) newtag = str( newsoup.find('tr') ) if '<th' in newtag: count_tag = '<th' else: count_tag = '<td' cells = newtag.count(count_tag) rows = [rawdata[table]['td'][x:x+cells] for x in range(0, len(rawdata[0]['td']), cells)] for row in rows: my_dict = {} for cell_name in contents: my_dict[cell_name] = row[contents[cell_name]] table_list.append(my_dict) return table_list else: return {}
def Addon_Genre(genre='adult',custom_url=''): """ Return a dictionary of add-ons which match a specific genre. CODE: Addon_Genre([genre, custom_url]) AVAILABLE PARAMS: genre - By default this is set to 'adult' which will return a dictionary of all known adult add-ons. The genre details are pulled from the Add-on Portal at noobsandnerds.com so you can use any of the supported genre tags listed on this page: http://noobsandnerds.com/latest/?p=3762 custom_url - If you have your own custom url which returns a dictionary of genres you can enter it here and use that rather than rely on NaN categorisation. EXAMPLE CODE: dialog.ok('[COLOR gold]ADD-ON GENRES[/COLOR]','We will now list all known comedy based add-ons. If you have add-ons installed which you feel should be categorised as supplying comedy but they aren\'t then you can help tag them up correctly via the Add-on Portal at NaN.') comedy_addons = koding.Addon_Genre(genre='comedy') if comedy_addons: my_return = 'LIST OF AVAILABLE COMEDY BASED ADD-ONS:\n\n' # Convert the dictionary into a list: comedy_addons = comedy_addons.items() for item in comedy_addons: my_return += '[COLOR=gold]Name:[/COLOR] %s | [COLOR=dodgerblue]ID:[/COLOR] %s\n' % (item[0],item[1]) koding.Text_Box('[COLOR gold]COMEDY ADD-ONS[/COLOR]',my_return) ~""" import binascii from __init__ import converthex from filetools import Text_File from systemtools import Timestamp from web import Open_URL download_new = True local_path = binascii.hexlify('addons') cookie_path = xbmc.translatePath("special://profile/addon_data/script.module.python.koding.aio/cookies/") final_path = os.path.join(cookie_path,local_path) if not os.path.exists(cookie_path): os.makedirs(cookie_path) if os.path.exists(final_path): modified = os.path.getmtime(final_path) old = int(modified) now = int(Timestamp('epoch')) # Add a 24hr wait so we don't kill server if now < (modified+86400): download_new = False # Create new file if download_new: if custom_url == '': custom_url = converthex('687474703a2f2f6e6f6f6273616e646e657264732e636f6d2f6164646f6e732f6164646f6e5f6c6973742e747874') addon_list = Open_URL(custom_url) Text_File(final_path, "w", addon_list) # Grab details of the relevant genre if os.path.exists(final_path): try: addon_list = eval( Text_File(final_path, 'r') ) return addon_list[genre] except: os.remove(final_path) return False else: return False
def Show_Tutorial(url): """ internal command ~""" name, filepath = url.split('~') filepath = urllib.unquote(filepath) readfile = Text_File(filepath,'r') raw_find = Find_In_Text(content=readfile, start='# TUTORIAL #\ndef %s' % name,end='~"""')[0] # Check if an example code segment exists in the comments if 'EXAMPLE CODE:' in raw_find: code = re.findall(r'(?<=EXAMPLE CODE:)(?s)(.*$)', raw_find)[0] code = code.replace('script.module.python.koding.aio','temp_replace_string') code = code.replace('koding.','').strip() code = code.replace('temp_replace_string','script.module.python.koding.aio') else: code = None # Check if a video exists in the comments internetstate = xbmc.getInfoLabel('System.InternetState') if internetstate: video_page = Open_URL(video_base) extension = Find_In_Text(video_page, name, '"', False) if extension != '' and extension != None: video = video_base+name+extension[0] else: video = None else: video = None counter = 0 removal_string = '' final_header = '' newline = '' temp_raw = raw_find.splitlines() for line in temp_raw: if counter == 0: removal_string += line if '[' in line: replace_file = Find_In_Text(content=line,start='\[',end='\]') for item in replace_file: line = line.replace(item,'') if ',' in line: header_extension = line.split(',') for item in header_extension: if '=' in item: item = item.split('=')[0] final_header += item+',' final_header = 'koding.'+name+final_header[:-2]+')' else: final_header = 'koding.'+name+line[:-1] else: removal_string += '\n'+line counter += 1 if counter == 2: break if final_header.endswith('))'): final_header = final_header[:-1] if final_header.startswith('koding.User_Info'): final_header = 'koding.User_Info()' full_text = raw_find.replace(removal_string,'').strip() # Initialise the dialog select dialog_array = ['Documentation'] if code: dialog_array.append('Run Example Code') if video: dialog_array.append('Watch Video') # If there's more than one item we show a dialog select otherwise we just load up the text window if len(dialog_array) > 1: choice = dialog.select(name, dialog_array) if choice >= 0: choice = dialog_array[choice] if choice == 'Documentation': Text_Box(final_header,full_text .replace('AVAILABLE PARAMS:','[COLOR=dodgerblue]AVAILABLE PARAMS:[/COLOR]') .replace('EXAMPLE CODE:','[COLOR=dodgerblue]EXAMPLE CODE:[/COLOR]') .replace('IMPORTANT:','[COLOR=gold]IMPORTANT:[/COLOR]') .replace('CODE:','[COLOR=dodgerblue]CODE:[/COLOR]') .replace('AVAILABLE VALUES:','[COLOR=dodgerblue]AVAILABLE VALUES:[/COLOR]') .replace('WARNING:','[COLOR=red]WARNING:[/COLOR]')) elif choice == 'Run Example Code': codefile = filepath.split(os.sep) codefile = codefile[len(codefile)-1].replace('.py','') exec('from %s import *' % codefile) # exec('from %s import %s' % (codefile, params["name"])) exec(code) elif choice == 'Watch Video': Play_Video(video) if choice < 0: return else: Text_Box(final_header,full_text .replace('AVAILABLE PARAMS:','[COLOR=dodgerblue]AVAILABLE PARAMS:[/COLOR]') .replace('EXAMPLE CODE:','[COLOR=dodgerblue]EXAMPLE CODE:[/COLOR]') .replace('IMPORTANT:','[COLOR=gold]IMPORTANT:[/COLOR]') .replace('CODE:','[COLOR=dodgerblue]CODE:[/COLOR]') .replace('AVAILABLE VALUES:','[COLOR=dodgerblue]AVAILABLE VALUES:[/COLOR]') .replace('WARNING:','[COLOR=red]WARNING:[/COLOR]'))
def Populate_List(url, start_point=r'<li+.<a href="', end_point=r'</a+.</li>', separator=r">", skip=['..', '.', 'Parent Directory']): """ If you have a basic index web page or a webpage with a common format for displaying links (on all pages) then you can use this to populate an add-on. It's capable of cleverly working out what needs to be sent through as a directory and what's a playable item. CODE: Populate_List(url, [start_point, end_point, separator, skip]): AVAILABLE PARAMS: (*) url - The start page of where to pull the first links from start_point - Send through the code tags you want to search for in the webpage. By default it's setup for a standard indexed site so the start_point is '<li+.<a href="'. The code will then grab every instance of start_point to end_point. end_point - Send through the code tags you want to search for in the webpage. By default it's setup for a standard indexed site so the end_point is '</a+.</li>'. The code will then grab every instance of start_point to end_point. separator - This is the point in the grabbed links (from above) where you want to split the string into a url and a display name. The default is ">". skip - By default this is set to ['..', '.', 'Parent Directory']. This is a list of links you don't want to appear in your add-on listing. EXAMPLE CODE: link ='http://totalrevolution.tv/videos/' sp ='<a href="' ep ='</a>' sep = '">' koding.Populate_List(url=link, start_point=sp, end_point=ep, separator=sep) ~""" import re import urlparse from __init__ import dolog from vartools import Find_In_Text, Cleanup_String from video import Play_Video from web import Open_URL, Get_Extension, Cleanup_URL badlist = [] if '<~>' in url: params = Grab_Params(extras=url, keys='url,start,end,separator,skip') url = params['url'] start_point = params['start'] end_point = params['end'] separator = params['separator'] skip = params['skip'] raw_content = Open_URL(url).replace('\n', '').replace('\r', '').replace('\t', '') raw_list = Find_In_Text(content=raw_content, start=start_point, end=end_point, show_errors=False) if raw_list != None: for item in raw_list: cont = True try: dolog('ITEM: %s' % item) new_sep = re.search(separator, item).group() link, title = item.split(new_sep) except: dolog('^ BAD ITEM, adding to badlist') badlist.append(item) cont = False # break if cont: title = Cleanup_String(title) if title not in skip: # Make sure the link we've grabbed isn't a full web address if not '://' in link: link = urlparse.urljoin(url, link) link = Cleanup_URL(link) extension = Get_Extension(link) if not link.endswith('/') and extension == '': link = link + '/' if extension == '' and not 'mms://' in link: Add_Dir(name=title, url=link + '<~>%s<~>%s<~>%s<~>%s' % (start_point, end_point, separator, skip), mode='populate_list', folder=True) else: Add_Dir(name=title, url=link, mode='play_video', folder=False) else: Add_Dir(name='Link 1', url=params["url"], mode='play_video', folder=False) if len(badlist) > 0: dialog.ok( 'ERROR IN REGEX', 'The separator used is not working, an example raw match from the web page has now been printed to the log.' ) for item in badlist: dolog('BADLIST ITEM: %s' % item)
def Addon_Genre(genre='adult', custom_url=''): """ [COLOR=gold]PREMIUM FEATURE FOR ADDONS EXCLUSIVELY SUPPORTED AT NOOBSANDNERDS[/COLOR] If you'd like to hook into this please take a look at the README. Please Note: Although this hooks into the NaN framework to pull genres you can use this without having to hook into their framework if you have a custom url which returns results in the same format. Your url must return a dictionary of items in this format: {"addon_name":"addon_id","addon_name_2":"addon_id_2"} Return a dictionary of add-ons which match a specific genre. CODE: Addon_Genre([genre, custom_url]) AVAILABLE PARAMS: genre - By default this is set to 'adult' which will return a dictionary of all known adult add-ons. For a full list of all the available genres you can filter by take a look at the Add-on Portal link below. If you click on each of the genre links then look at the url you'll be able to see the name to use. For example if you click on "Dev Tools" you'll see the url shows as 'devtools' and that's what you'd send through to this function if you only wanted those to show. http://noobsandnerds.com/addons/category/genres/ custom_url - If you have your own custom url which returns genres you can enter it here and use that rather than rely on NaN categorisation. EXAMPLE CODE: space_addons = koding.Addon_Genre(genre='space') if space_addons: my_return = 'LIST OF AVAILABLE SPACE BASED ADD-ONS:\n\n' # Convert the dictionary into a list: space_addons = space_addons.items() for item in space_addons: my_return += '[COLOR=gold]Name:[/COLOR] %s | [COLOR=dodgerblue]ID:[/COLOR] %s\n' % (item[0],item[1]) koding.Text_Box('SPACE ADD-ONS',my_return) ~""" import binascii from __init__ import Main from filetools import Text_File from systemtools import Timestamp from web import Open_URL local_path = binascii.hexlify(genre) cookie_path = xbmc.translatePath( "special://profile/addon_data/script.module.python.koding.aio/cookies/" ) final_path = os.path.join(cookie_path, local_path) if not os.path.exists(cookie_path): os.makedirs(cookie_path) if os.path.exists(final_path): modified = os.path.getmtime(final_path) old = int(modified) now = int(Timestamp('epoch')) # Add a 24hr wait so we don't kill server if now > (modified + 86400): if custom_url == '': Main('addon_list|g:%s' % genre) else: addon_list = Open_URL(custom_url) try: addon_list = eval(addon_list) Text_File(final_path, "w", binascii.hexlify(str(addon_list))) except: pass # Create new file if it doesn't exist else: if custom_url == '': Main('addon_list|g:%s' % genre) else: addon_list = Open_URL(custom_url) try: addon_list = eval(addon_list) Text_File(final_path, "w", binascii.hexlify(str(addon_list))) except: pass if os.path.exists(final_path): try: addon_list = eval(binascii.unhexlify(Text_File(final_path, 'r'))) return addon_list except: return False else: return False
def M3U_Selector(url, post_type='get', header='Stream Selection'): """ Send through an m3u/m3u8 playlist and have the contents displayed via a dialog select. The return will be a dictionary of 'name' and 'url'. You can send through either a locally stored filepath or an online URL. This function will try it's best to pull out the relevant playlist details even if the web page isn't a correctly formatted m3u playlist (e.g. an m3u playlist embedded into a blog page). CODE: M3U_Selector(url, [post_type, header]) AVAILABLE PARAMS: (*) url - The location of your m3u file, this can be local or online post_type - If you need to use POST rather than a standard query string in your url set this to 'post', by default it's set to 'get'. header - This is the header you want to appear at the top of your dialog selection window, by default it's set to "Stream Selection" EXAMPLE CODE: # This example uses YouTube plugin paths but any playable paths will work vid = koding.M3U_Selector(url='http://totalrevolution.tv/videos/playlists/youtube.m3u') # Make sure there is a valid link returned if vid: playback = koding.Play_Video(video=vid['url'], showbusy=False) if playback: dialog.ok('SUCCESS!','Congratulations the playback was successful!') xbmc.Player().stop() else: dialog.ok('OOPS!','Looks like something went wrong there, the playback failed. Check the links are still valid.') ~""" from web import Open_URL from vartools import Cleanup_String, Find_In_Text from filetools import Text_File success = False if url.startswith('http'): content = Open_URL(url=url, post_type=post_type, timeout=10) else: try: url = xbmc.translatePath(url) except: pass content = Text_File(url, 'r') if content: newcontent = content.splitlines() name_array = [] url_array = [] name = '' for line in newcontent: line = line.strip() # Grab the name of the stream if line.startswith('#EXT'): name = line.split(',') name.pop(0) name = ''.join(name) # Grab the url(s) of the stream if name != '' and line != '' and not line.startswith('#EXT'): name_array.append(Cleanup_String(name)) line = line.replace('<br>', '').replace('<br />', '').replace('<br/>', '') line = line.replace('</p>', '').replace('</div>', '').replace('</class>', '') dolog('line: %s' % line) if 'm3u' in line or 'm3u8' in line: line = 'LIST~' + line if 'src="' in line: line = Find_In_Text(content=line, start='src="', end='"')[0] url_array.append(line) name = '' line = '' # If there is only one entry with no names/comments just return as unknown with the link if not '#EXT' in content: return {'name': 'Unknown', 'url': line} # If there's a list we show a dialog select of the available links if len(name_array) > 0: choice = xbmcgui.Dialog().select(header, name_array) if choice >= 0: # If the selection is a final url and not a list of multiple links if not url_array[choice].startswith('LIST~'): success = True return { 'name': name_array[choice], 'url': url_array[choice] } # List of multiple links detected, give option of which link to play else: clean_link = url_array[choice].replace('LIST~', '') content = Open_URL(url=clean_link, timeout=10) if content: newcontent = content.splitlines() name_array = [] url_array = [] name = '' counter = 1 for line in newcontent: # Show name as link 1,2,3,4 etc. if line.startswith('#EXT'): name = 'LINK ' + str(counter) # Grab the link(s) to the video if name != '' and line != '' and not line.startswith( '#EXT'): name_array.append(name) line = line.replace('<br>', '').replace( '<br />', '').replace('<br/>', '') line = line.replace('</p>', '').replace( '</div>', '').replace('</class>', '') url_array.append(line) name = '' line = '' counter += 1 # If there is only one entry with no names/comments just return as unknown with the link if not '#EXT' in content: return {'name': 'Unknown', 'url': line} # Give option of which link to play in case of multiple links available if len(name_array) > 0: choice = xbmcgui.Dialog().select( header, name_array) if choice >= 0: success = True return { 'name': name_array[choice], 'url': url_array[choice] } if not success: xbmcgui.Dialog().ok( 'NO LINKS FOUND', 'Sorry no valid links could be found for this stream.') return False
def Addon_Genre(genre='adult', custom_url=''): """ Return a dictionary of add-ons which match a specific genre. CODE: Addon_Genre([genre, custom_url]) AVAILABLE PARAMS: genre - By default this is set to 'adult' which will return a dictionary of all known adult add-ons. We recommend using the genre labels listed below as they are already in use by some add-on developers, however you can of course create your very own genre keys in your custom genre file if you wish. custom_url - If you have your own custom url which returns a dictionary of genres and add-ons you can enter it here. The page must adhere to the format shown below. Recommended Genre Keys: adult, anime, audiobooks, comedy, comics, documentary, food, gaming, health, howto, kids, livetv, movies, music, news, podcasts, radio, religion, space, sports, subscription, tech, trailers, tvshows, world Correct Genre Dictionary Structure: The dictionary must be a dictionary of genres with each genre dictionary containing keys for each add-on ID and the value being the name you want displayed. See below for an example: { "movies":{"plugin.video.mymovie":"My movie add-on","plugin.video.trailers":"My Trailer add-on"}, "sports":{"plugin.video.sports":"Sport Clips"} } EXAMPLE CODE: dialog.ok('ADD-ON GENRES','We will now list all known comedy based add-ons. If you have add-ons installed which you feel should be categorised as supplying comedy but they aren\'t then you can help tag them up correctly via the Add-on Portal at NaN.') comedy_addons = koding.Addon_Genre(genre='comedy') if comedy_addons: my_return = 'LIST OF AVAILABLE COMEDY BASED ADD-ONS:\n\n' # Convert the dictionary into a list: comedy_addons = comedy_addons.items() for item in comedy_addons: my_return += '[COLOR=gold]Name:[/COLOR] %s | [COLOR=dodgerblue]ID:[/COLOR] %s\n' % (item[0],item[1]) koding.Text_Box('[COLOR gold]COMEDY ADD-ONS[/COLOR]',my_return) ~""" import binascii from __init__ import converthex from filetools import Text_File from systemtools import Timestamp from vartools import Merge_Dicts from web import Open_URL download_new = True local_path = binascii.hexlify('genre_list') cookie_path = "special://profile/addon_data/script.module.python.koding.aio/cookies/" custom_genres = "special://profile/addon_data/script.module.python.koding.aio/genres.txt" final_path = os.path.join(cookie_path, local_path) if not xbmcvfs.exists(cookie_path): xbmcvfs.mkdirs(cookie_path) if xbmcvfs.exists(final_path): modified = xbmcvfs.Stat(final_path).st_mtime() old = int(modified) now = int(Timestamp('epoch')) # Add a 24hr wait so we don't kill server if now < (modified + 86400): download_new = False # Create new file if download_new and custom_url != '': addon_list = Open_URL(custom_url) Text_File(final_path, "w", addon_list) # Grab details of the relevant genre if xbmcvfs.exists(final_path): try: addon_list = eval(Text_File(final_path, 'r')) addon_list = addon_list[genre] except: xbmcvfs.delete(final_path) addon_list = {} if xbmcvfs.exists(custom_genres): try: custom_list = eval(Text_File(custom_genres, 'r')) custom_list = custom_list[genre] addon_list = Merge_Dicts(addon_list, custom_list) except: pass return addon_list
def M3U_Selector(url,post_type='get',header='Stream Selection'): """ Send through an m3u/m3u8 playlist and have the contents displayed via a dialog select. The return will be a dictionary of 'name' and 'url'. You can send through either a locally stored filepath or an online URL. This function will try it's best to pull out the relevant playlist details even if the web page isn't a correctly formatted m3u playlist (e.g. an m3u playlist embedded into a blog page). CODE: M3U_Selector(url, [post_type, header]) AVAILABLE PARAMS: (*) url - The location of your m3u file, this can be local or online post_type - If you need to use POST rather than a standard query string in your url set this to 'post', by default it's set to 'get'. header - This is the header you want to appear at the top of your dialog selection window, by default it's set to "Stream Selection" EXAMPLE CODE: dialog.ok('M3U SELECTOR','We will now call this function using the following url:','','[COLOR dodgerblue]http://totalrevolution.tv/videos/playlists/youtube.m3u[/COLOR]') # This example uses YouTube plugin paths but any playable paths will work vid = koding.M3U_Selector(url='http://totalrevolution.tv/videos/playlists/youtube.m3u') # Make sure there is a valid link returned if vid: playback = koding.Play_Video(video=vid['url'], showbusy=False) if playback: dialog.ok('SUCCESS!','Congratulations the playback was successful!') xbmc.Player().stop() else: dialog.ok('OOPS!','Looks like something went wrong there, the playback failed. Check the links are still valid.') ~""" from web import Open_URL from vartools import Cleanup_String, Find_In_Text from filetools import Text_File success = False if url.startswith('http'): content = Open_URL(url=url, post_type=post_type, timeout=10) else: try: url = xbmc.translatePath(url) except: pass content = Text_File(url,'r') if content: newcontent = content.splitlines() name_array = [] url_array = [] name = '' for line in newcontent: line = line.strip() # Grab the name of the stream if line.startswith('#EXT'): name = line.split(',') name.pop(0) name = ''.join(name) # Grab the url(s) of the stream if name != '' and line != '' and not line.startswith('#EXT'): name_array.append(Cleanup_String(name)) line = line.replace('<br>','').replace('<br />','').replace('<br/>','') line = line.replace('</p>','').replace('</div>','').replace('</class>','') xbmc.log('line: %s'%line) if 'm3u' in line or 'm3u8' in line: line = 'LIST~'+line if 'src="' in line: line = Find_In_Text(content=line, start='src="', end='"')[0] url_array.append(line) name = '' line = '' # If there is only one entry with no names/comments just return as unknown with the link if not '#EXT' in content: return {'name' : 'Unknown', 'url' : line} # If there's a list we show a dialog select of the available links if len(name_array) > 0: choice = xbmcgui.Dialog().select(header, name_array) if choice >= 0: # If the selection is a final url and not a list of multiple links if not url_array[choice].startswith('LIST~'): success = True return {'name' : name_array[choice], 'url' : url_array[choice]} # List of multiple links detected, give option of which link to play else: clean_link = url_array[choice].replace('LIST~','') content = Open_URL(url=clean_link, timeout=10) if content: newcontent = content.splitlines() name_array = [] url_array = [] name = '' counter = 1 for line in newcontent: # Show name as link 1,2,3,4 etc. if line.startswith('#EXT'): name = 'LINK '+str(counter) # Grab the link(s) to the video if name != '' and line != '' and not line.startswith('#EXT'): name_array.append(name) line = line.replace('<br>','').replace('<br />','').replace('<br/>','') line = line.replace('</p>','').replace('</div>','').replace('</class>','') url_array.append(line) name = '' line = '' counter += 1 # If there is only one entry with no names/comments just return as unknown with the link if not '#EXT' in content: return {'name' : 'Unknown', 'url' : line} # Give option of which link to play in case of multiple links available if len(name_array) > 0: choice = xbmcgui.Dialog().select(header, name_array) if choice >= 0: success = True return {'name' : name_array[choice], 'url' : url_array[choice]} if not success: xbmcgui.Dialog().ok('NO LINKS FOUND','Sorry no valid links could be found for this stream.') return False