From: Clinton Ebadi Date: Sat, 10 Oct 2020 17:20:50 +0000 (-0400) Subject: party-upload: port to python 3 X-Git-Url: https://git.hcoop.net/clinton/unknownlamer-kodi-addons.git/commitdiff_plain/b61367d10ef971427d81c43df0240229b0430cd9 party-upload: port to python 3 Overdue update for python 3 and kodijson. No functional changes. --- diff --git a/party-upload/admin.cgi b/party-upload/admin.cgi index 56c523d..fb27e84 100755 --- a/party-upload/admin.cgi +++ b/party-upload/admin.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # Simple PartyMode Web Console # Copyright (c) 2015,2016 Clinton Ebadi # This program is free software: you can redistribute it and/or modify @@ -28,25 +28,15 @@ # 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 html import numbers import os import random import subprocess -from xbmcjson import XBMC +from kodijson import Kodi from yattag import Doc import partyparty @@ -75,10 +65,10 @@ def show_menu (): print (doc.getvalue ()) -xbmc = partyparty.connect (XBMC ("http://localhost:8080/jsonrpc")) +xbmc = partyparty.connect (Kodi ("http://localhost:8080/jsonrpc")) def print_escaped (item): - print (u"

{}

".format (cgi.escape (u"{}".format (item)))) + print (u"

{}

".format (html.escape (u"{}".format (item)))) show_menu () @@ -121,7 +111,7 @@ print (''' -'''.format (cgi.escape (PAGE_SELF))) +'''.format (html.escape (PAGE_SELF))) print ('''
@@ -129,7 +119,7 @@ print ('''
-'''.format (cgi.escape (PAGE_SELF))) +'''.format (html.escape (PAGE_SELF))) print ('

Playlist

') print (playlist.show ()) @@ -141,7 +131,7 @@ print ('') Search ().show_quick_search (thereal=True) show_menu () -print ('
'.format (cgi.escape (PAGE_SELF))) +print (''.format (html.escape (PAGE_SELF))) print ('') #print ('') print ('') diff --git a/party-upload/normals.cgi b/party-upload/normals.cgi index d05378b..ff3efbe 100755 --- a/party-upload/normals.cgi +++ b/party-upload/normals.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # Simple PartyMode Web Console # Limited interface for normal party goers @@ -18,10 +18,6 @@ # limit playlist view to next five -import sys -reload(sys) -sys.setdefaultencoding ('utf-8') - import cgi, cgitb from datetime import datetime import hashlib @@ -29,7 +25,8 @@ import numbers import os import random import subprocess -from xbmcjson import XBMC +import sys +from kodijson import Kodi from yattag import Doc import partyparty @@ -42,18 +39,18 @@ sys.stdout.flush () print ("\npartyparty beb") print (partyparty.css ()) -print '

Upload A Song | Add From YouTube | home | browse

' +print ('

Upload A Song | Add From YouTube | home | browse

') class NormalsPlaylist (Playlist): def get_playlist (self): - return Playlist.get_playlist (self)[0:6] + return Playlist.get_playlist (self)#[0:10] class NormalsManager (PartyManager): DEFAULT_QUEUE_DIVISOR = 1 -xbmc = partyparty.connect (XBMC ("http://localhost:8080/jsonrpc")) +xbmc = partyparty.connect (Kodi ("http://localhost:8080/jsonrpc")) manager = NormalsManager (cgi.FieldStorage ()) manager.process () diff --git a/party-upload/partyparty.py b/party-upload/partyparty.py index 6ac2fd3..98d8f9f 100644 --- a/party-upload/partyparty.py +++ b/party-upload/partyparty.py @@ -18,6 +18,7 @@ import cgi, cgitb from datetime import datetime import hashlib +import html import itertools import numbers import os @@ -25,16 +26,16 @@ import random import re import subprocess import urllib -from xbmcjson import XBMC +from kodijson import Kodi from yattag import Doc import youtube_dl -xbmc = None +kodi = None -def connect (_xbmc): - global xbmc - xbmc = _xbmc - return xbmc +def connect (_kodi): + global kodi + kodi = _kodi + return kodi SONG_PROPERTIES = ['album', 'artist', 'albumartist', 'dateadded', 'userrating', 'displayartist'] PAGE_SELF = os.environ['SCRIPT_NAME'] if 'SCRIPT_NAME' in os.environ else '' @@ -58,21 +59,21 @@ class Song: if 'id' in song: # item from playlist - self.key = hashlib.sha256(str(song['id'])).hexdigest() + self.key = hashlib.sha256(str(song['id']).encode('utf-8')).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 'userrating' in song: - libsong = xbmc.AudioLibrary.GetSongDetails (songid = song['id'], properties = ['userrating']) + libsong = kodi.AudioLibrary.GetSongDetails (songid = song['id'], properties = ['userrating']) #print (libsong) if 'result' in libsong and 'songdetails' in libsong['result']: song['userrating'] = libsong['result']['songdetails']['userrating'] elif 'songid' in song: # search results - self.key = hashlib.sha256(str(song['songid'])).hexdigest() + self.key = hashlib.sha256(str(song['songid']).encode('utf-8')).hexdigest() self.kodi_id = song['songid'] else: - self.key = hashlib.sha256(song['label'] + self.artist).hexdigest() + self.key = hashlib.sha256((song['label'] + self.artist).encode('utf-8')).hexdigest() self.kodi_id = 0 # videos can still be labeled as songs, but the rating will be a @@ -89,7 +90,7 @@ def songs(items): return [Song(item) for item in items] def get_playlist (playlistid=0): - return songs (xbmc.Playlist.GetItems (playlistid=playlistid, properties=SONG_PROPERTIES)['result']['items']) + return songs (kodi.Playlist.GetItems (playlistid=playlistid, properties=SONG_PROPERTIES)['result']['items']) class SongControls: aactions = {'songup': 'up', 'songdown': 'down', 'songtop': 'next!', 'songbottom': 'banish!', @@ -139,13 +140,13 @@ class Search: return {} if (self.prop != 'any'): - res = xbmc.AudioLibrary.GetSongs (filter={'operator': "contains", 'field': self.prop, 'value': self.term}, properties=SONG_PROPERTIES, sort={'order': 'ascending', 'method': 'artist'})['result'] + res = kodi.AudioLibrary.GetSongs (filter={'operator': "contains", 'field': self.prop, 'value': self.term}, properties=SONG_PROPERTIES, sort={'order': 'ascending', 'method': 'artist'})['result'] if 'songs' in res: return songs(res['songs']) else: return [] else: - all_songs = [xbmc.AudioLibrary.GetSongs (filter={'operator': "contains", 'field': p, 'value': self.term}, properties=SONG_PROPERTIES, sort={'order': 'ascending', 'method': 'artist'})['result'] + all_songs = [kodi.AudioLibrary.GetSongs (filter={'operator': "contains", 'field': p, 'value': self.term}, properties=SONG_PROPERTIES, sort={'order': 'ascending', 'method': 'artist'})['result'] for p in self.ANY_SEARCH_PROPERTIES] # does not remove duplicates... @@ -164,7 +165,7 @@ class Search: text (prop) with tag ('button', type = 'submit', name = 'searchgo', value = '1'): text ('Search') - print doc.getvalue () + print (doc.getvalue ()) def show_search_results (self): doc, tag, text = Doc().tagtext() @@ -203,7 +204,7 @@ class Playlist: return doc.getvalue () def get_playlist (self, playlistid=0): - return songs (xbmc.Playlist.GetItems (playlistid=playlistid, properties=SONG_PROPERTIES)['result']['items']) + return songs (kodi.Playlist.GetItems (playlistid=playlistid, properties=SONG_PROPERTIES)['result']['items']) class Upload: upload_dir = '/srv/archive/incoming/stolen-moosic' @@ -216,12 +217,12 @@ class Upload: # works instead of dealing with MIME. For now. def attempt_rpgain (self): subprocess.call (["/usr/bin/vorbisgain", "-q", self.filename]) - subprocess.call (["/usr/bin/mp3gain", "-q", "-s", "i", self.filename]) + subprocess.call (["/usr/local/bin/mp3gain", "-q", "-s", "i", self.filename]) subprocess.call (["/usr/bin/aacgain", "-q", "-s", "i", self.filename]) subprocess.call (["/usr/bin/metaflac", "--add-replay-gain", self.filename]) def save (self): - fout = file (os.path.join(self.upload_dir, self.fileitem.filename), 'wb') + fout = open (os.path.join(self.upload_dir, self.fileitem.filename), 'wb') fout.write (self.fileitem.value) fout.close() self.attempt_rpgain () @@ -282,7 +283,7 @@ ol li:nth-child(even) { background-color: #202020 } return doc.getvalue () def print_escaped (item): - print (u"

{}

".format (cgi.escape (u"{}".format (item)))) + print (u"

{}

".format (html.escape (u"{}".format (item)))) # This is awful class PartyManager: @@ -296,10 +297,10 @@ class PartyManager: # divisor) songs if divisor is None: divisor = self.DEFAULT_QUEUE_DIVISOR - totalitems = xbmc.Playlist.GetItems (playlistid=0)['result']['limits']['total'] + totalitems = kodi.Playlist.GetItems (playlistid=0)['result']['limits']['total'] playpos = random.randint (1, totalitems / divisor + 1) - print_escaped (xbmc.Playlist.Insert (playlistid=0, item=item, position=playpos)) - print '

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

'.format (playpos, totalitems+1) + print_escaped (kodi.Playlist.Insert (playlistid=0, item=item, position=playpos)) + print ('

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

'.format (playpos, totalitems+1)) return (playpos, totalitems+1) def process (self): @@ -308,49 +309,49 @@ class PartyManager: 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)) + print (u'

Deleted {}

'.format(html.escape (song.label))) + print_escaped (kodi.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)) + print (u"

Promoted {}

".format(html.escape(song.label))) + print_escaped (kodi.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)) + print (u"

Demoted {}

".format(html.escape(song.label))) + print_escaped (kodi.Playlist.Swap (playlistid=0, position1=pos, position2=pos+1)) elif 'songtop' in form: songid = form['songtop'].value print (u"

{}

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

Bumped Up {}

".format(cgi.escape(song.label))) + print (u"

Bumped Up {}

".format(html.escape(song.label))) for i in range (pos, 1, -1): - print_escaped (xbmc.Playlist.Swap (playlistid=0, position1=i, position2=i-1)) + print_escaped (kodi.Playlist.Swap (playlistid=0, position1=i, position2=i-1)) elif 'songbottom' in form: songid = form['songbottom'].value print (u"

{}

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

Banished {}

".format(cgi.escape(song.label))) + print (u"

Banished {}

".format(html.escape(song.label))) for i in range (pos, len (playlist), 1): - print_escaped (xbmc.Playlist.Swap (playlistid=0, position1=i, position2=i+1)) + print_escaped (kodi.Playlist.Swap (playlistid=0, position1=i, position2=i+1)) elif 'volchange' in form: - curvolume = xbmc.Application.GetProperties (properties=['volume'])['result']['volume'] + curvolume = kodi.Application.GetProperties (properties=['volume'])['result']['volume'] newvolume = max (0, min (int (form['volchange'].value) + curvolume, 100)) - print_escaped (xbmc.Application.SetVolume (volume=newvolume)) + print_escaped (kodi.Application.SetVolume (volume=newvolume)) elif 'volmute' in form: - print_escaped (xbmc.Application.SetMute (mute="toggle")) + print_escaped (kodi.Application.SetMute (mute="toggle")) elif 'navigate' in form: action = form['navigate'].value if action == 'prev': - print_escaped (xbmc.Player.GoTo (to="previous", playerid=0)) + print_escaped (kodi.Player.GoTo (to="previous", playerid=0)) elif action == 'next': - print_escaped (xbmc.Player.GoTo (to="next", playerid=0)) + print_escaped (kodi.Player.GoTo (to="next", playerid=0)) elif action == 'playpause': - print_escaped (xbmc.Player.PlayPause (play="toggle", playerid=0)) + print_escaped (kodi.Player.PlayPause (play="toggle", playerid=0)) elif 'searchgo' in form: term = form['searchterm'].value field = form['searchfield'].value @@ -365,10 +366,10 @@ class PartyManager: newrating = int(form['songrating'].value) print (songid) print (newrating) - print_escaped (xbmc.AudioLibrary.SetSongDetails (songid = songid, userrating = newrating)) + print_escaped (kodi.AudioLibrary.SetSongDetails (songid = songid, userrating = newrating)) print_escaped (u'Rating Changed') elif 'browseartists' in form: - artists = xbmc.AudioLibrary.GetArtists (sort={'order': 'ascending', 'method': 'artist'})['result']['artists'] + artists = kodi.AudioLibrary.GetArtists (sort={'order': 'ascending', 'method': 'artist'})['result']['artists'] doc, tag, text = Doc().tagtext() with tag ('ol', klass='flex_list'): for artist in artists: @@ -385,8 +386,8 @@ class PartyManager: item = youtube.save () self.randomqueue (item, 1 if 'asap' not in form else 3) elif 'partyon' in form: - if 'error' in xbmc.Player.SetPartymode (partymode=True, playerid=0): - xbmc.Player.Open (item={"partymode": "music"}) + if 'error' in kodi.Player.SetPartymode (partymode=True, playerid=0): + kodi.Player.Open (item={"partymode": "music"}) elif 'lockon' in form: subprocess.call (['/usr/bin/xscreensaver-command', 'lock']) elif 'lights' in form: diff --git a/party-upload/upload.cgi b/party-upload/upload.cgi index 45a109a..8eb2a13 100755 --- a/party-upload/upload.cgi +++ b/party-upload/upload.cgi @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/python3 # Simple PartyMode Web Console # Copyright (c) 2015,2016 Clinton Ebadi # This program is free software: you can redistribute it and/or modify @@ -57,7 +57,7 @@ import os, sys import daemon import subprocess import random -from xbmcjson import XBMC +from kodijson import Kodi import partyparty from partyparty import Upload, PartyManager @@ -74,7 +74,7 @@ manager = PartyManager (form) print '

Upload another song

' sys.stdout.flush () -xbmc = partyparty.connect (XBMC ("http://localhost:8080/jsonrpc")) +xbmc = partyparty.connect (Kodi ("http://localhost:8080/jsonrpc")) manager.randomqueue ({"file": filename}, 1 if 'asap' not in form else 3) # todo: use REMOTE_ADDR to limit how many asap requests a person can