def info(bot, mess, args): """display info about currently playing file""" # abort if nothing is playing active = bot.xbmc_active_player() if not active: return 'Nothing playing' (pid, typ) = active # get file name result = bot.xbmc('Player.GetItem', {'playerid': pid}) name = result['result']['item']['label'] # get speed, current time, and total time result = bot.xbmc('Player.GetProperties', { 'playerid': pid, 'properties': ['speed', 'time', 'totaltime'] }) current = util.time2str(result['result']['time']) total = util.time2str(result['result']['totaltime']) # translate speed: 0 = 'paused', 1 = 'playing' speed = result['result']['speed'] status = 'playing' if speed == 0: status = 'paused' return '%s %s at %s/%s - "%s"' % (typ.title(), status, current, total, name)
def info(bot,mess,args): """display info about currently playing file""" # abort if nothing is playing active = bot.xbmc_active_player() if not active: return 'Nothing playing' (pid,typ) = active # get file name result = bot.xbmc('Player.GetItem',{'playerid':pid}) name = result['result']['item']['label'] # get speed, current time, and total time result = bot.xbmc('Player.GetProperties', {'playerid':pid,'properties':['speed','time','totaltime']}) current = util.time2str(result['result']['time']) total = util.time2str(result['result']['totaltime']) # translate speed: 0 = 'paused', 1 = 'playing' speed = result['result']['speed'] status = 'playing' if speed==0: status = 'paused' return '%s %s at %s/%s - "%s"' % (typ.title(),status,current,total,name)
def note(bot, mess, args): """add a note - note (show|add|playing|remove) [body|num]""" # default behavior is "show" if not args: args = ['show'] if args[0] not in ['show', 'add', 'playing', 'remove']: args.insert(0, 'show') # set second parameter to make playing/add logic easier if len(args) < 2: args.append('') else: args[1] = ' '.join(args[1:]) # add the currently playing file to the body of the note then do "add" if args[0] == 'playing': if not bot.has_plugin('xbmc'): return 'This feature not available because plugin "xbmc" not loaded' args[0] = 'add' active = bot.xbmc_active_player() if not active: return 'Nothing playing; note not added' (pid, typ) = active params = {'playerid': pid, 'properties': ['time']} result = bot.xbmc('Player.GetProperties', params) t = str(util.time2str(result['result']['time'])) result = bot.xbmc('Player.GetItem', { 'playerid': pid, 'properties': ['file'] }) fil = os.path.basename(str(result['result']['item']['file'])) args[1] += ' --- file "' + fil + '" at ' + t # add the note to bot.notes and bot.note_file if args[0] == 'add': if args[1] == '': return 'Note body cannot be blank' bot.notes.append(args[1]) note_write(bot) return 'Added note #' + str(len(bot.notes)) + ': ' + args[1] # remove the specified note number from bot.notes and rewrite bot.note_file # notes are stored internally 0-indexed, but users see 1-indexed if args[0] == 'remove': try: num = int(args[1]) - 1 except ValueError as e: return 'Parameter to note remove must be an integer' if num < 0 or num > len(bot.notes) - 1: return 'Parameter to note remove must be in [1,' + str( len(bot.notes)) + ']' body = bot.notes[num] del bot.notes[num] note_write(bot) return 'Removed note #' + str(num + 1) + ': ' + body # otherwise show notes if they exist if len(bot.notes) == 0: return 'No notes' # if args[1] is blank then show all if args[1] == '': s = '' for (i, n) in enumerate(bot.notes): s += '(Note #' + str(i + 1) + '): ' + n + ', ' return s[:-2] # if args[1] is a valid integer show that note try: num = int(args[1]) - 1 except ValueError as e: num = None if num is not None: if num < 0 or num > len(bot.notes) - 1: return 'Parameter to note show must be in [1,' + str(len( bot.notes)) + ']' return 'Note #' + str(num + 1) + ': ' + bot.notes[num] # if args[1] is text, show matching notes search = args[1].lower() matches = [ i for i in range(0, len(bot.notes)) if search in bot.notes[i].lower() ] s = 'Found ' + str(len(matches)) + ' matches: ' for i in matches: s += '(Note #' + str(i + 1) + '): ' + bot.notes[i] + ', ' return s[:-2]
def stream(bot, mess, args): """stream from [YouTube, Twitch (Live)] - stream url""" if not args: return 'You must specify a URL' agent = { 'User-agent': 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) ' + 'Gecko/20100101 Firefox/46.0' } msg = args[0] # remove http:// https:// www. from start msg = msg.replace('http://', '').replace('https://', '').replace('www.', '') # account for mobile links from youtu.be and custom start times if msg.lower().startswith('youtu.be'): tim = None if '?t=' in msg: tim = msg[msg.find('?t=') + 3:] msg = msg[:msg.find('?t=')] msg = 'youtube.com/watch?v=' + msg[msg.rfind('/') + 1:] if tim: msg += ('&t=' + tim) # account for "&start=" custom start times msg = msg.replace('&start=', '&t=') s = 'Unsupported URL' # parse youtube links if msg.lower().startswith('youtube'): #check for custom start time tim = None if '&t=' in msg: start = msg.find('&t=') + 3 end = msg.find('&', start + 1) if end == -1: end = len(msg) tim = msg[start:end] # get raw seconds from start time sec = 0 if 'h' in tim: sec += 3600 * int(tim[:tim.find('h')]) tim = tim[tim.find('h') + 1:] if 'm' in tim: sec += 60 * int(tim[:tim.find('m')]) tim = tim[tim.find('m') + 1:] if 's' in tim: sec += int(tim[:tim.find('s')]) tim = '' if len(tim) > 0: sec = int(tim) # parse seconds to 'h:mm:ss' tim = {'hours': 0, 'minutes': 0, 'seconds': 0} if int(sec / 3600) > 0: tim['hours'] = int(sec / 3600) sec -= 3600 * tim['hours'] if int(sec / 60) > 0: tim['minutes'] = int(sec / 60) sec -= 60 * tim['minutes'] tim['seconds'] = sec tim = util.time2str(tim) # remove feature, playlist, etc info from end and get vid if '&' in msg: msg = msg[:msg.find('&')] vid = msg[msg.find('watch?v=') + 8:] # send xbmc request and seek if given custom start time result = bot.xbmc( 'Player.Open', { 'item': { 'file': 'plugin://plugin.video.youtube/play/?video_id=' + vid } }) if tim: bot.run_cmd('seek', [tim]) try: # retrieve video info from webpage api = 'https://youtube.com/oembed?url=https://www.youtube.com/watch?v=%s&format=json' j = json.loads(requests.get(api % vid, headers=agent).text) title = util.cleanhtml(j['title']) channel = util.cleanhtml(j['author_name']) # respond to the user with video info s = 'Streaming "' + title + '" by "' + channel + '" from YouTube' except: s = 'Streaming (unable to retrieve title) from YouTube' if tim: s += (' at ' + tim) elif 'twitch' in msg.lower(): # get the webpage if 'channel=' in msg: vid = msg.split('channel=')[-1].split('&')[0] else: vid = msg.split('twitch.tv/')[-1].split('/')[0] html = requests.get('http://twitch.tv/' + vid, headers=agent).text # find the stream title stream = html.find("property='og:title'") stop = html.rfind("'", 0, stream) start = html.rfind("'", 0, stop) + 1 stream = html[start:stop] # find the stream description title = html.find("property='og:description'") stop = html.rfind("'", 0, title) start = html.rfind("'", 0, stop) + 1 title = html[start:stop] response = bot.xbmc( 'Player.Open', {'item': { 'file': 'plugin://plugin.video.twitch/playLive/' + vid }}) s = 'Streaming "' + title + '" by "' + stream + '" from Twitch Live' bot.last_played = None if bot.has_plugin('bookmark'): bot.last_resume = None return s
def bookmark(bot, mess, args): """manage bookmarks - bookmark [show|set|remove|update] [name]""" if not args: args = ['show'] if args[0] == 'set': # check if last_played is set if bot.last_played is None: return 'No active audios or videos playlist to bookmark' # check if anything is actually playing if bot.xbmc_active_player() is None: return 'Nothing playing' # check if a name was passed name = bot.last_played[1] args = args[1:] if len(args) > 0: name = str(args[0]) # get info for bookmark pid = bot.last_played[0] path = bot.last_played[1] params = {'playerid': pid, 'properties': ['position', 'time']} result = bot.xbmc('Player.GetProperties', params) pos = result['result']['position'] t = str(util.time2str(result['result']['time'])) add = time.time() result = bot.xbmc('Player.GetItem', { 'playerid': pid, 'properties': ['file'] }) fil = os.path.basename(str(result['result']['item']['file'])) # note that the position is stored 0-indexed bot.bm_store[name] = { 'path': path, 'add': add, 'time': t, 'pid': pid, 'pos': pos, 'file': fil } bm_update(bot, name, bot.bm_store[name]) return 'Bookmark added for "' + name + '" item ' + str(pos + 1) + ' at ' + t elif args[0] == 'remove': if len(args) == 1: return 'To remove all bookmarks use "bookmarks remove *"' if not bm_remove(bot, args[1]): return 'Bookmark "' + name + '" not found' return 'Removed bookmark "%s"' % args[1] elif args[0] == 'update': if not bot.last_resume: return 'No active bookmark' return bot.run_cmd('bookmark', ['set', bot.last_resume]) elif args[0] == 'show': args = args[1:] # actual code for show function because this is default behavior if len(bot.bm_store) == 0: return 'No bookmarks' # if no args are passed return all bookmark names matches = bot.bm_store.keys() if len(args) == 0 or args[0] == '': return 'There are ' + str( len(matches)) + ' bookmarks: ' + ', '.join(matches) # if a search term was passed find matches and display them search = ' '.join(args).lower() matches = [m for m in matches if search in m.lower()] entries = [] for m in matches: item = bot.bm_store[m] pos = item['pos'] t = item['time'] f = item['file'] entries.append('"%s" at item %s and time %s which is "%s"' % (m, pos + 1, t, f)) if len(entries) == 0: return 'Found 0 bookmarks' if len(entries) == 1: return 'Found 1 bookmark: ' + str(entries[0]) return 'Found ' + str( len(entries)) + ' bookmarks: ' + util.list2str(entries)
def note(bot,mess,args): """add a note - note (show|add|playing|remove) [body|num]""" # default behavior is "show" if not args: args = ['show'] if args[0] not in ['show','add','playing','remove']: args.insert(0,'show') # set second parameter to make playing/add logic easier if len(args)<2: args.append('') else: args[1] = ' '.join(args[1:]) # add the currently playing file to the body of the note then do "add" if args[0]=='playing': if not bot.has_plugin('xbmc'): return 'This feature not available because plugin "xbmc" not loaded' args[0] = 'add' active = bot.xbmc_active_player() if not active: return 'Nothing playing; note not added' (pid,typ) = active params = {'playerid':pid,'properties':['time']} result = bot.xbmc('Player.GetProperties',params) t = str(util.time2str(result['result']['time'])) result = bot.xbmc('Player.GetItem',{'playerid':pid,'properties':['file']}) fil = os.path.basename(str(result['result']['item']['file'])) args[1] += ' --- file "'+fil+'" at '+t # add the note to bot.notes and bot.note_file if args[0]=='add': if args[1]=='': return 'Note body cannot be blank' bot.notes.append(args[1]) note_write(bot) return 'Added note #'+str(len(bot.notes))+': '+args[1] # remove the specified note number from bot.notes and rewrite bot.note_file # notes are stored internally 0-indexed, but users see 1-indexed if args[0]=='remove': try: num = int(args[1])-1 except ValueError as e: return 'Parameter to note remove must be an integer' if num<0 or num>len(bot.notes)-1: return 'Parameter to note remove must be in [1,'+str(len(bot.notes))+']' body = bot.notes[num] del bot.notes[num] note_write(bot) return 'Removed note #'+str(num+1)+': '+body # otherwise show notes if they exist if len(bot.notes)==0: return 'No notes' # if args[1] is blank then show all if args[1]=='': s = '' for (i,n) in enumerate(bot.notes): s += '(Note #'+str(i+1)+'): '+n+', ' return s[:-2] # if args[1] is a valid integer show that note try: num = int(args[1])-1 except ValueError as e: num = None if num is not None: if num<0 or num>len(bot.notes)-1: return 'Parameter to note show must be in [1,'+str(len(bot.notes))+']' return 'Note #'+str(num+1)+': '+bot.notes[num] # if args[1] is text, show matching notes search = args[1].lower() matches = [i for i in range(0,len(bot.notes)) if search in bot.notes[i].lower()] s = 'Found '+str(len(matches))+' matches: ' for i in matches: s += '(Note #'+str(i+1)+'): '+bot.notes[i]+', ' return s[:-2]
def bookmark(bot,mess,args): """manage bookmarks - bookmark [show|set|remove|update] [name]""" if not args: args = ['show'] if args[0]=='set': # check if last_played is set if bot.last_played is None: return 'No active audios or videos playlist to bookmark' # check if anything is actually playing if bot.xbmc_active_player() is None: return 'Nothing playing' # check if a name was passed name = bot.last_played[1] args = args[1:] if len(args)>0: name = str(args[0]) # get info for bookmark pid = bot.last_played[0] path = bot.last_played[1] params = {'playerid':pid,'properties':['position','time']} result = bot.xbmc('Player.GetProperties',params) pos = result['result']['position'] t = str(util.time2str(result['result']['time'])) add = time.time() result = bot.xbmc('Player.GetItem',{'playerid':pid,'properties':['file']}) fil = os.path.basename(str(result['result']['item']['file'])) # note that the position is stored 0-indexed bot.bm_store[name] = {'path':path,'add':add,'time':t, 'pid':pid,'pos':pos,'file':fil} bm_update(bot,name,bot.bm_store[name]) return 'Bookmark added for "'+name+'" item '+str(pos+1)+' at '+t elif args[0]=='remove': if len(args)==1: return 'To remove all bookmarks use "bookmarks remove *"' if not bm_remove(bot,args[1]): return 'Bookmark "'+name+'" not found' return 'Removed bookmark "%s"' % args[1] elif args[0]=='update': if not bot.last_resume: return 'No active bookmark' return bot.run_cmd('bookmark',['set',bot.last_resume]) elif args[0]=='show': args = args[1:] # actual code for show function because this is default behavior if len(bot.bm_store)==0: return 'No bookmarks' # if no args are passed return all bookmark names matches = bot.bm_store.keys() if len(args)==0 or args[0]=='': return 'There are '+str(len(matches))+' bookmarks: '+', '.join(matches) # if a search term was passed find matches and display them search = ' '.join(args).lower() matches = [m for m in matches if search in m.lower()] entries = [] for m in matches: item = bot.bm_store[m] pos = item['pos'] t = item['time'] f = item['file'] entries.append('"%s" at item %s and time %s which is "%s"' % (m,pos+1,t,f)) if len(entries)==0: return 'Found 0 bookmarks' if len(entries)==1: return 'Found 1 bookmark: '+str(entries[0]) return 'Found '+str(len(entries))+' bookmarks: '+util.list2str(entries)
def stream(bot,mess,args): """stream from [YouTube, Twitch (Live)] - stream url""" if not args: return 'You must specify a URL' agent = {'User-agent':'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:46.0) ' +'Gecko/20100101 Firefox/46.0'} msg = args[0] # remove http:// https:// www. from start msg = msg.replace('http://','').replace('https://','').replace('www.','') # account for mobile links from youtu.be and custom start times if msg.lower().startswith('youtu.be'): tim = None if '?t=' in msg: tim = msg[msg.find('?t=')+3:] msg = msg[:msg.find('?t=')] msg = 'youtube.com/watch?v='+msg[msg.rfind('/')+1:] if tim: msg += ('&t='+tim) # account for "&start=" custom start times msg = msg.replace('&start=','&t=') s = 'Unsupported URL' # parse youtube links if msg.lower().startswith('youtube'): #check for custom start time tim = None if '&t=' in msg: start = msg.find('&t=')+3 end = msg.find('&',start+1) if end==-1: end = len(msg) tim = msg[start:end] # get raw seconds from start time sec = 0 if 'h' in tim: sec += 3600*int(tim[:tim.find('h')]) tim = tim[tim.find('h')+1:] if 'm' in tim: sec += 60*int(tim[:tim.find('m')]) tim = tim[tim.find('m')+1:] if 's' in tim: sec += int(tim[:tim.find('s')]) tim = '' if len(tim)>0: sec = int(tim) # parse seconds to 'h:mm:ss' tim = {'hours':0,'minutes':0,'seconds':0} if int(sec/3600)>0: tim['hours'] = int(sec/3600) sec -= 3600*tim['hours'] if int(sec/60)>0: tim['minutes'] = int(sec/60) sec -= 60*tim['minutes'] tim['seconds'] = sec tim = util.time2str(tim) # remove feature, playlist, etc info from end and get vid if '&' in msg: msg = msg[:msg.find('&')] vid = msg[msg.find('watch?v=')+8:] # send xbmc request and seek if given custom start time result = bot.xbmc('Player.Open',{'item':{'file': 'plugin://plugin.video.youtube/play/?video_id='+vid}}) if tim: bot.run_cmd('seek',[tim]) try: # retrieve video info from webpage api = 'https://youtube.com/oembed?url=https://www.youtube.com/watch?v=%s&format=json' j = json.loads(requests.get(api % vid,headers=agent).text) title = util.cleanhtml(j['title']) channel = util.cleanhtml(j['author_name']) # respond to the user with video info s = 'Streaming "'+title+'" by "'+channel+'" from YouTube' except: s = 'Streaming (unable to retrieve title) from YouTube' if tim: s += (' at '+tim) elif 'twitch' in msg.lower(): # get the webpage if 'channel=' in msg: vid = msg.split('channel=')[-1].split('&')[0] else: vid = msg.split('twitch.tv/')[-1].split('/')[0] html = requests.get('http://twitch.tv/'+vid,headers=agent).text # find the stream title stream = html.find("property='og:title'") stop = html.rfind("'",0,stream) start = html.rfind("'",0,stop)+1 stream = html[start:stop] # find the stream description title = html.find("property='og:description'") stop = html.rfind("'",0,title) start = html.rfind("'",0,stop)+1 title = html[start:stop] response = bot.xbmc('Player.Open',{'item':{'file': 'plugin://plugin.video.twitch/playLive/'+vid}}) s = 'Streaming "'+title+'" by "'+stream+'" from Twitch Live' bot.last_played = None if bot.has_plugin('bookmark'): bot.last_resume = None return s