X-Git-Url: http://git.hcoop.net/clinton/unknownlamer-kodi-addons.git/blobdiff_plain/a68240a2deb1c49293214168bfb39515bf9e7c66..51a600c287ae8bf683b911dbee9a0ad1a397db6f:/party-upload/admin.cgi diff --git a/party-upload/admin.cgi b/party-upload/admin.cgi dissimilarity index 79% index 88fea04..56c523d 100755 --- a/party-upload/admin.cgi +++ b/party-upload/admin.cgi @@ -1,312 +1,150 @@ -#!/usr/bin/python - -# ADD COMMAND TO RESTART PARTY MODE -# (probably should require confirmation) -# also add undelete link to post-del link just in case (reinsert at old pos) - -# Trivial xbmc admin script to view active playlist, control volume, -# etc. - -# I would not recommend putting this online, no attempt is made at -# being even trivially secure (e.g. form values are passed directly to -# kodi with zero verification) - -# todo -# any kind of error checking - -from __future__ import unicode_literals - -# Python is being obnoxious as hell and refusing to .format() utf-8 -# strings. I have no idea. Just hack around it and deal with the -# actual problem later instead of scattering the code with .encode -# calls. - -import sys -reload(sys) -sys.setdefaultencoding ('utf-8') - -import cgi, cgitb -import hashlib -import numbers -import os -import random -import subprocess -from xbmcjson import XBMC -from yattag import Doc - -cgitb.enable() - -print ("content-type: text/html; charset=utf-8\n\n") -print ("\npartyparty beb") - -SONG_PROPERTIES = ['album', 'artist', 'albumartist', 'dateadded', 'rating'] - -class Song: - def __init__ (self, song): - self._song = song - if len(song['artist']) > 0: - self.artist = song['artist'][0] - elif 'albumartist' in song and len(song['albumartist']) > 0: - self.artist = song['albumartist'][0] - else: - self.artist = 'who fucking knows' - - if len(song['album']) > 0: - self.album = song['album'] - else: - self.album = 'album is for losers' - - if 'id' in song: - # item from playlist - self.key = hashlib.sha256(str(song['id'])).hexdigest() - self.kodi_id = song['id'] - # the playlist will not update things like ratings if we - # update via RPC. Just grab it from the library instead. - if 'rating' in song: - libsong = xbmc.AudioLibrary.GetSongDetails (songid = song['id'], properties = ['rating']) - #print (libsong) - if 'result' in libsong and 'songdetails' in libsong['result']: - song['rating'] = libsong['result']['songdetails']['rating'] - elif 'songid' in song: - # search results - self.key = hashlib.sha256(str(song['songid'])).hexdigest() - self.kodi_id = song['songid'] - else: - self.key = hashlib.sha256(song['label'] + self.artist).hexdigest() - self.kodi_id = 0 - - # videos can still be labeled as songs, but the rating will be a - # float... - if 'rating' in song and isinstance (song['rating'], numbers.Integral): - self.rating = song['rating'] - else: - self.rating = -1 # might be better to use None here - - self.label = song['label'] - -def songs(items): - '''Convert list of Kodi Items into Song instances''' - return [Song(item) for item in items] - -def get_playlist (playlistid=0): - return songs (xbmc.Playlist.GetItems (playlistid=playlistid, properties=SONG_PROPERTIES)['result']['items']) - -class SongControls: - aactions = {'songup': 'up', 'songdown': 'down', 'songdel': 'del', 'randomqueue': 'yeh', 'songrate': 'rate'} - - def __init__ (self, song, actions = ['songup', 'songdown', 'songdel']): - self.song = song - self.actions = actions - - def controls (self): - doc, tag, text = Doc().tagtext() - with tag ('form', method = 'post', action = 'admin.cgi', klass = 'song_controls'): #, style = 'display: inline-block'): - for action in self.actions: - with tag ('button', name = action, value = self.song.key): - text (self.aactions[action]) - doc.asis (self.extra_elements (action)) - return doc.getvalue() - - def extra_elements (self, action): - doc, tag, text = Doc().tagtext() - if action == 'randomqueue': - doc.stag ('input', type = 'hidden', name = 'songkodiid', value = self.song.kodi_id) - elif action == 'songrate': - if self.song.rating > -1: - doc.defaults = {'songrating': self.song.rating} - with doc.select (name = 'songrating'): - with doc.option (value = 0): - text ('na') - for i in range (1,6): - with doc.option (value = i): - text (str (i)) - doc.stag ('input', type = 'hidden', name = 'songkodiid', value = self.song.kodi_id) - - return doc.getvalue () - - -class Search: - def __init__ (self, term = '', prop = 'title'): - self.term = term - self.prop = prop - if (term != ''): - res = xbmc.AudioLibrary.GetSongs (filter={'operator': "contains", 'field': self.prop, 'value': self.term}, properties=SONG_PROPERTIES, sort={'order': 'ascending', 'method': 'artist'})['result'] - if 'songs' in res: - self.results = songs(res['songs']) - else: - self.results = [] - - def show_quick_search (self, thereal=False): - print (u''' -
- - - -
- ''').format(self.term, 'id="quicksearch"' if thereal else '') - - def show_search_results (self): - doc, tag, text = Doc().tagtext() - with tag ('h1'): - text ('Results') - if len (self.results) > 0: - with tag ('ol'): - for song in self.results: - with tag ('li'): - text (u'{} ({}) {}'.format (song.artist, song.album, song.label)) - doc.asis (SongControls (song, actions = ['randomqueue']).controls ()) - else: - with tag ('p'): - text ('You are unworthy. No results.') - - print (doc.getvalue ()) - - -def show_menu (): - doc, tag, text = Doc().tagtext() - with tag ('style'): - text (''' -input, select, button { font-size: 200%; margin: 0.1em; } -.horiz-menu li { display: inline; padding-right: 0.5em; } -body { /* background-image: url("fire-under-construction-animation.gif"); */ - color: white; - background-color: black; -} -a { color: #5dfc0a} -button[name=songdel] { margin-left: 1em; margin-right: 1em; } -div.flex_row { - display: flex; - flex-flow: row nowrap; - justify-content: space-between; -} - -ol li:nth-child(even) { background-color: #202020 } -''') - with tag ('ul', klass = 'horiz-menu'): - for target, description in [('admin.cgi', 'reload'), ('#playlist', 'playlist'), - ('#controls', 'controls'), ('javascript:document.getElementById("quicksearch").focus()', 'search')]: - with tag ('li'): - with tag ('a', href = target): - text (description) - - print (doc.getvalue ()) - -form = cgi.FieldStorage () - -xbmc = XBMC ("http://localhost:8080/jsonrpc") - -def print_escaped (item): - print (u"

{}

".format (cgi.escape (u"{}".format (item)))) - -show_menu () - -if 'songdel' in form: - songid = form['songdel'].value - print (u"

{}

".format (songid)) - (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid) - print (u'

Deleted {}

'.format(cgi.escape (song.label))) - print_escaped (xbmc.Playlist.Remove (playlistid=0, position=pos)) -elif 'songup' in form: - songid = form['songup'].value - print (u"

{}

".format (songid)) - (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid) - print (u"

Promoted {}

".format(cgi.escape(song.label))) - print_escaped (xbmc.Playlist.Swap (playlistid=0, position1=pos, position2=pos-1)) -elif 'songdown' in form: - songid = form['songdown'].value - print (u"

{}

".format (songid)) - (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid) - print (u"

Demoted {}

".format(cgi.escape(song.label))) - print_escaped (xbmc.Playlist.Swap (playlistid=0, position1=pos, position2=pos+1)) -elif 'volchange' in form: - curvolume = xbmc.Application.GetProperties (properties=['volume'])['result']['volume'] - newvolume = max (0, min (int (form['volchange'].value) + curvolume, 100)) - print_escaped (xbmc.Application.SetVolume (volume=newvolume)) -elif 'volmute' in form: - print_escaped (xbmc.Application.SetMute (mute="toggle")) -elif 'navigate' in form: - action = form['navigate'].value - if action == 'prev': - print_escaped (xbmc.Player.GoTo (to="previous", playerid=0)) - elif action == 'next': - print_escaped (xbmc.Player.GoTo (to="next", playerid=0)) - elif action == 'playpause': - print_escaped (xbmc.Player.PlayPause (play="toggle", playerid=0)) -elif 'searchgo' in form: - term = form['searchterm'].value - field = form['searchfield'].value - search = Search (term, field) - search.show_quick_search () - search.show_search_results () -elif 'randomqueue' in form: - songid = int(form['songkodiid'].value) - totalitems = xbmc.Playlist.GetItems (playlistid=0)['result']['limits']['total'] - playpos = random.randint (1, totalitems / 3 + 1) - print_escaped (xbmc.Playlist.Insert (playlistid=0, item={"songid": songid}, position=playpos)) - print '

Your song is number {0} in the queue ({1} songs in playlist).

'.format (playpos, totalitems+1) -elif 'songrate' in form: - songid = int(form['songkodiid'].value) - newrating = int(form['songrating'].value) - print (songid) - print (newrating) - print_escaped (xbmc.AudioLibrary.SetSongDetails (songid = songid, rating = newrating)) - print_escaped (u'Rating Changed') -elif 'partyon' in form: - if 'error' in xbmc.Player.SetPartymode (partymode=True, playerid=0): - xbmc.Player.Open (item={"partymode": "music"}) -elif 'lockon' in form: - subprocess.call (['/usr/bin/xscreensaver-command', 'lock']) - - - - - -playlist = get_playlist () -#playpos = random.randint (1, totalitems / (1 if 'asap' not in form else 3)) - -print ('') -print ('

Volume: {}%

'.format(xbmc.Application.GetProperties (properties=['volume'])['result']['volume'])) -print (''' -
- - - - - - - - -
-''') - -print (''' -
- - - -
-''') - - -print ('

Playlist

') -print ('
    ') -for song in playlist: -# print (song._song) - print (u'
  1. {0} {1}

    '.format(song.artist, song.label).encode('UTF-8')) - print (SongControls (song, ['songup', 'songdown', 'songdel', 'songrate']).controls ()) - print ("
  2. ") -print ("
") - -print ('') -Search ().show_quick_search (thereal=True) -show_menu () - -print ('
') -print ('') -print ('') -print ('
') -print ('') +#!/usr/bin/python +# Simple PartyMode Web Console +# Copyright (c) 2015,2016 Clinton Ebadi +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Trivial xbmc admin script to view active playlist, control volume, +# etc. + +# I would not recommend putting this online, no attempt is made at +# being even trivially secure (e.g. form values are passed directly to +# kodi with zero verification) + +# ADD COMMAND TO RESTART PARTY MODE +# (probably should require confirmation) +# also add undelete link to post-del link just in case (reinsert at old pos) + +# todo +# any kind of error checking + +from __future__ import unicode_literals + +# Python is being obnoxious as hell and refusing to .format() utf-8 +# strings. I have no idea. Just hack around it and deal with the +# actual problem later instead of scattering the code with .encode +# calls. + +import sys +reload(sys) +sys.setdefaultencoding ('utf-8') + +import cgi, cgitb +from datetime import datetime +import hashlib +import numbers +import os +import random +import subprocess +from xbmcjson import XBMC +from yattag import Doc + +import partyparty +from partyparty import Song, SongControls, Search, Playlist, PartyManager + +cgitb.enable() +PAGE_SELF = os.environ['SCRIPT_NAME'] if 'SCRIPT_NAME' in os.environ else '' + +print ("content-type: text/html; charset=utf-8\n\n") +print ("\npartyparty beb") +print (partyparty.css ()) + +#print (os.environ) +#print (os.environ['SCRIPT_NAME']) + +def show_menu (): + doc, tag, text = Doc().tagtext() + with tag ('ul', klass = 'horiz-menu flex_row'): + for target, description in [('#playlist', 'playlist'), + ('#controls', 'controls'), + ('javascript:document.getElementById("quicksearch").focus()', 'search'), + (PAGE_SELF, 'reload')]: + with tag ('li'): + with tag ('a', href = target): + text (description) + + print (doc.getvalue ()) + +xbmc = partyparty.connect (XBMC ("http://localhost:8080/jsonrpc")) + +def print_escaped (item): + print (u"

{}

".format (cgi.escape (u"{}".format (item)))) + +show_menu () + +manager = PartyManager (cgi.FieldStorage ()) +manager.process () + +playlist = Playlist() +#playpos = random.randint (1, totalitems / (1 if 'asap' not in form else 3)) + +class PlayerControls: + def __init__ (self, name='controls'): + self.name = name + + def info (self): + doc, tag, text = Doc().tagtext() + _playtime = xbmc.Player.GetProperties (playerid=0, properties = ['position', 'percentage', 'time', 'totaltime']) + pt = _playtime['result'] if 'result' in _playtime else None + with tag ('ul', klass = 'horiz-menu'): + for infotext in ['Volume {}%'.format(xbmc.Application.GetProperties (properties=['volume'])['result']['volume']), + 'Time {:02d}:{:02d} / {:02d}:{:02d} ({:.2f}%) @ {:%H:%M:%S}'.format (pt['time']['hours'] * 60 + pt['time']['minutes'], pt['time']['seconds'], pt['totaltime']['hours'] * 60 + pt['totaltime']['minutes'], pt['totaltime']['seconds'], pt['percentage'], datetime.now())]: + with tag ('li'): + text (infotext) + + return doc.getvalue () + + + +controls = PlayerControls () +print (controls.info ()) + +print ('') +print (''' +
+ + + + + + + + +
+'''.format (cgi.escape (PAGE_SELF))) + +print (''' +
+ + + +
+'''.format (cgi.escape (PAGE_SELF))) + +print ('

Playlist

') +print (playlist.show ()) + + + + +print ('') +Search ().show_quick_search (thereal=True) +show_menu () + +print ('
'.format (cgi.escape (PAGE_SELF))) +print ('') +#print ('') +print ('') +print ('') +print ('
') +print ('')