party-upload: port to python 3
authorClinton Ebadi <clinton@unknownlamer.org>
Sat, 10 Oct 2020 17:20:50 +0000 (13:20 -0400)
committerClinton Ebadi <clinton@unknownlamer.org>
Sat, 10 Oct 2020 17:20:50 +0000 (13:20 -0400)
Overdue update for python 3 and kodijson. No functional changes.

party-upload/admin.cgi
party-upload/normals.cgi
party-upload/partyparty.py
party-upload/upload.cgi

index 56c523d..fb27e84 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 # Simple PartyMode Web Console
 # Copyright (c) 2015,2016  Clinton Ebadi <clinton@unknownlamer.org>
 # This program is free software: you can redistribute it and/or modify
 # Simple PartyMode Web Console
 # Copyright (c) 2015,2016  Clinton Ebadi <clinton@unknownlamer.org>
 # This program is free software: you can redistribute it and/or modify
 # todo
 # any kind of error checking
 
 # 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 cgi, cgitb
 from datetime import datetime
 import hashlib
+import html
 import numbers
 import os
 import random
 import subprocess
 import numbers
 import os
 import random
 import subprocess
-from xbmcjson import XBMC
+from kodijson import Kodi
 from yattag import Doc
 
 import partyparty
 from yattag import Doc
 
 import partyparty
@@ -75,10 +65,10 @@ def show_menu ():
 
    print (doc.getvalue ())
 
 
    print (doc.getvalue ())
 
-xbmc = partyparty.connect (XBMC ("http://localhost:8080/jsonrpc"))
+xbmc = partyparty.connect (Kodi ("http://localhost:8080/jsonrpc"))
 
 def print_escaped (item):
 
 def print_escaped (item):
-   print (u"<p>{}</p>".format (cgi.escape (u"{}".format (item))))
+   print (u"<p>{}</p>".format (html.escape (u"{}".format (item))))
 
 show_menu ()
 
 
 show_menu ()
 
@@ -121,7 +111,7 @@ print ('''
 <button name="volmute" value="1">Toggle Mute</button>
 
 </form>
 <button name="volmute" value="1">Toggle Mute</button>
 
 </form>
-'''.format (cgi.escape (PAGE_SELF)))
+'''.format (html.escape (PAGE_SELF)))
 
 print ('''
 <form method="post" action="{}" style="display: inline-block">
 
 print ('''
 <form method="post" action="{}" style="display: inline-block">
@@ -129,7 +119,7 @@ print ('''
 <button name="navigate" value="next" type="submit">&#x23ed;</button>
 <button name="navigate" value="playpause" type="submit">&#x23ef;</button>
 </form>
 <button name="navigate" value="next" type="submit">&#x23ed;</button>
 <button name="navigate" value="playpause" type="submit">&#x23ef;</button>
 </form>
-'''.format (cgi.escape (PAGE_SELF)))
+'''.format (html.escape (PAGE_SELF)))
 
 print ('<a name="playlist"></a><h1>Playlist</h1>')
 print (playlist.show ())
 
 print ('<a name="playlist"></a><h1>Playlist</h1>')
 print (playlist.show ())
@@ -141,7 +131,7 @@ print ('<a name="search"></a>')
 Search ().show_quick_search (thereal=True)
 show_menu ()
 
 Search ().show_quick_search (thereal=True)
 show_menu ()
 
-print ('<form method="post" action="{}" style="display: inline-block">'.format (cgi.escape (PAGE_SELF)))
+print ('<form method="post" action="{}" style="display: inline-block">'.format (html.escape (PAGE_SELF)))
 print ('<button name="partyon" value="true">re-enable party</button>')
 #print ('<button name="lockon" value="true">lock em out</button>')
 print ('<button name="lights" value="on">lights on</button>')
 print ('<button name="partyon" value="true">re-enable party</button>')
 #print ('<button name="lockon" value="true">lock em out</button>')
 print ('<button name="lights" value="on">lights on</button>')
index d05378b..ff3efbe 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 
 # Simple PartyMode Web Console
 # Limited interface for normal party goers
 
 # Simple PartyMode Web Console
 # Limited interface for normal party goers
 
 # limit playlist view to next five
 
 
 # limit playlist view to next five
 
-import sys
-reload(sys)
-sys.setdefaultencoding ('utf-8')
-
 import cgi, cgitb
 from datetime import datetime
 import hashlib
 import cgi, cgitb
 from datetime import datetime
 import hashlib
@@ -29,7 +25,8 @@ import numbers
 import os
 import random
 import subprocess
 import os
 import random
 import subprocess
-from xbmcjson import XBMC
+import sys
+from kodijson import Kodi
 from yattag import Doc
 
 import partyparty
 from yattag import Doc
 
 import partyparty
@@ -42,18 +39,18 @@ sys.stdout.flush ()
 print ("<!DOCTYPE html>\n<html><head><title>partyparty beb</title></head><body>")
 print (partyparty.css ())
 
 print ("<!DOCTYPE html>\n<html><head><title>partyparty beb</title></head><body>")
 print (partyparty.css ())
 
-print '<p style="font-size: 5rem"><a href="upload.html">Upload A Song</a> | <a href="youtube.html">Add From YouTube</a> | <a href="normals.cgi">home</a> | <a href="normals.cgi?browseartists=1">browse</a></p>'
+print ('<p style="font-size: 5rem"><a href="upload.html">Upload A Song</a> | <a href="youtube.html">Add From YouTube</a> | <a href="normals.cgi">home</a> | <a href="normals.cgi?browseartists=1">browse</a></p>')
 
 
 
 class NormalsPlaylist (Playlist):
     def get_playlist (self):
 
 
 
 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    
 
 
 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 ()
 
 manager = NormalsManager (cgi.FieldStorage ())
 manager.process ()
index 6ac2fd3..98d8f9f 100644 (file)
@@ -18,6 +18,7 @@
 import cgi, cgitb
 from datetime import datetime
 import hashlib
 import cgi, cgitb
 from datetime import datetime
 import hashlib
+import html
 import itertools
 import numbers
 import os
 import itertools
 import numbers
 import os
@@ -25,16 +26,16 @@ import random
 import re
 import subprocess
 import urllib
 import re
 import subprocess
 import urllib
-from xbmcjson import XBMC
+from kodijson import Kodi
 from yattag import Doc
 import youtube_dl
 
 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 ''
 
 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
 
       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:
          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
             #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.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
          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 [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!',
 
 class SongControls:
    aactions = {'songup': 'up', 'songdown': 'down', 'songtop': 'next!', 'songbottom': 'banish!',
@@ -139,13 +140,13 @@ class Search:
            return {}
 
        if (self.prop != 'any'):
            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:
            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...
                         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')
                       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()
 
    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 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'
 
 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])
     # 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):
         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 ()
         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):
     return doc.getvalue ()
 
 def print_escaped (item):
-   print (u"<p>{}</p>".format (cgi.escape (u"{}".format (item))))
+   print (u"<p>{}</p>".format (html.escape (u"{}".format (item))))
 
 # This is awful
 class PartyManager:
 
 # This is awful
 class PartyManager:
@@ -296,10 +297,10 @@ class PartyManager:
         # divisor) songs
         if divisor is None:
             divisor = self.DEFAULT_QUEUE_DIVISOR
         # 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)
         playpos = random.randint (1, totalitems / divisor + 1)
-        print_escaped (xbmc.Playlist.Insert (playlistid=0, item=item, position=playpos))
-        print '<p style="font-size: x-large">Your song is number {0} in the queue ({1} songs in playlist).</p>'.format (playpos, totalitems+1)
+        print_escaped (kodi.Playlist.Insert (playlistid=0, item=item, position=playpos))
+        print ('<p style="font-size: x-large">Your song is number {0} in the queue ({1} songs in playlist).</p>'.format (playpos, totalitems+1))
         return (playpos, totalitems+1)
 
     def process (self):
         return (playpos, totalitems+1)
 
     def process (self):
@@ -308,49 +309,49 @@ class PartyManager:
             songid = form['songdel'].value
             print (u"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
             songid = form['songdel'].value
             print (u"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
-            print (u'<p>Deleted {}</p>'.format(cgi.escape (song.label)))
-            print_escaped (xbmc.Playlist.Remove (playlistid=0, position=pos))
+            print (u'<p>Deleted {}</p>'.format(html.escape (song.label)))
+            print_escaped (kodi.Playlist.Remove (playlistid=0, position=pos))
         elif 'songup' in form:
             songid = form['songup'].value
             print (u"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
         elif 'songup' in form:
             songid = form['songup'].value
             print (u"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
-            print (u"<p>Promoted {}</p>".format(cgi.escape(song.label)))
-            print_escaped (xbmc.Playlist.Swap (playlistid=0, position1=pos, position2=pos-1))
+            print (u"<p>Promoted {}</p>".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"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
         elif 'songdown' in form:
             songid = form['songdown'].value
             print (u"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
-            print (u"<p>Demoted {}</p>".format(cgi.escape(song.label)))
-            print_escaped (xbmc.Playlist.Swap (playlistid=0, position1=pos, position2=pos+1))
+            print (u"<p>Demoted {}</p>".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"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
         elif 'songtop' in form:
             songid = form['songtop'].value
             print (u"<p>{}</p>".format (songid))
             (pos,song) = next ((i,s) for i,s in enumerate(get_playlist ()) if s.key == songid)
-            print (u"<p>Bumped Up {}</p>".format(cgi.escape(song.label)))
+            print (u"<p>Bumped Up {}</p>".format(html.escape(song.label)))
             for i in range (pos, 1, -1):
             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"<p>{}</p>".format (songid))
             playlist = get_playlist ()
             (pos,song) = next ((i,s) for i,s in enumerate(playlist) if s.key == songid)
         elif 'songbottom' in form:
             songid = form['songbottom'].value
             print (u"<p>{}</p>".format (songid))
             playlist = get_playlist ()
             (pos,song) = next ((i,s) for i,s in enumerate(playlist) if s.key == songid)
-            print (u"<p>Banished {}</p>".format(cgi.escape(song.label)))
+            print (u"<p>Banished {}</p>".format(html.escape(song.label)))
             for i in range (pos, len (playlist), 1):
             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:
         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))
             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:
         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':
         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':
             elif action == 'next':
-                print_escaped (xbmc.Player.GoTo (to="next", playerid=0))
+                print_escaped (kodi.Player.GoTo (to="next", playerid=0))
             elif action == 'playpause':
             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
         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)
             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:
             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:
             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:
             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:
         elif 'lockon' in form:
             subprocess.call (['/usr/bin/xscreensaver-command', 'lock'])
         elif 'lights' in form:
index 45a109a..8eb2a13 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/python
+#!/usr/bin/python3
 # Simple PartyMode Web Console
 # Copyright (c) 2015,2016 Clinton Ebadi <clinton@unknownlamer.org>
 # This program is free software: you can redistribute it and/or modify
 # Simple PartyMode Web Console
 # Copyright (c) 2015,2016 Clinton Ebadi <clinton@unknownlamer.org>
 # 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
 import daemon
 import subprocess
 import random
-from xbmcjson import XBMC
+from kodijson import Kodi
 
 import partyparty
 from partyparty import Upload, PartyManager
 
 import partyparty
 from partyparty import Upload, PartyManager
@@ -74,7 +74,7 @@ manager = PartyManager (form)
 print '<p><a href="upload.html">Upload another song</a></p>'
 sys.stdout.flush ()
 
 print '<p><a href="upload.html">Upload another song</a></p>'
 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
 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