Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Ampache resolver #33

Open
wants to merge 6 commits into from

1 participant

Remo Giermann
Remo Giermann

Hey,
I wrote another ampache resolver which uses its web API and can resolve to multiple ampaches at once.
It works for me, you might want to take a look.

Best regards,
mo

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 4, 2011
  1. Remo Giermann
  2. Remo Giermann

    modul authored
  3. Remo Giermann

    minor change

    modul authored
  4. Remo Giermann

    renamed files

    modul authored
  5. Remo Giermann

    fixed typo

    modul authored
Commits on Apr 10, 2011
  1. Remo Giermann

    minor change

    modul authored
This page is out of date. Refresh to see the latest.
3  contrib/ampache-api/README
View
@@ -0,0 +1,3 @@
+ This is an Ampache resolver which uses Ampache's XML Web-API.
+ To use it, one only needs a user account on any ampache installation.
+ It's possible to use multiple Ampache servers/accounts.
4 contrib/ampache-api/ampache-resolver.cfg
View
@@ -0,0 +1,4 @@
+[localhost] # section name is used to form source name
+url = http://localhost/ampache
+user = John
+password = Doe
92 contrib/ampache-api/ampache-resolver.py
View
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# -*- coding: utf8 -*-
+#
+# Ampache resolver for playdar
+# using Ampache's Web API
+#
+# author: Remo Giermann <mo@liberejo.de>
+# created: 2011/04/03
+#
+
+import os, sys
+from ConfigParser import ConfigParser
+
+import ampache
+import playdar_resolver
+from playdar_resolver import soundex
+
+configuration = os.path.join(os.path.dirname(sys.argv[0]), "ampache-resolver.cfg")
+
+
+class AmpacheResolver(playdar_resolver.PlaydarResolver):
+
+ def __init__(self):
+
+ self.ampaches = []
+
+ config = ConfigParser()
+ if not config.read(configuration):
+ return
+ else:
+ for section in config.sections():
+ if config.options(section) == ['url', 'password', 'user']:
+ url = config.get(section, 'url')
+ un = config.get(section, 'user')
+ pw = config.get(section, 'password')
+
+ amp = ampache.Ampache(url)
+ if amp.handshake(un, pw) is True:
+ self.ampaches.append((amp, "Ampache (%s)" % section))
+
+
+ def resolver_settings(self):
+ """My settings"""
+ return {'name':"Ampache (API) Resolver", 'targettime':5000, 'weight':60}
+
+
+ def results(self, query):
+ results = []
+
+ for amp, name in self.ampaches:
+
+ songs = amp.search_songs(u'{artist} {track}'.format(**query))
+
+ # first item in search results is best match, last item is worst,
+ # so scoring is simple:
+ score = 1.0
+ for s in songs:
+
+ if s.artist['name'].lower() == query['artist'].lower() \
+ and score > 0.5:
+
+ results.append(
+ {'artist': s.artist['name'],
+ 'track': s.title,
+ 'album': s.album['name'],
+ 'duration': int(s.time),
+ 'url': s.url,
+ 'score': score,
+ 'extension': s.url[-3:],
+ 'art': s.art,
+ #'size': int(s.size),
+ 'source': name
+ })
+ # decrement score for next match
+ score -= .1
+
+ else:
+ break
+
+
+ return results
+
+
+
+if __name__ == "__main__":
+ #q = {'qid':'test', 'artist': 'iron maiden', 'track': 'aces high'}
+ #r = AmpacheResolver()
+ #playdar_resolver.print_result(r.resolve(q))
+ try:
+ AmpacheResolver.start_static()
+ except:
+ traceback.print_exc(file=sys.stderr)
180 contrib/ampache-api/ampache.py
View
@@ -0,0 +1,180 @@
+# -*- coding: utf8 -*-
+# This class speaks to the Ampache XML API
+#
+# author: Remo Giermann <mo@liberejo.de>
+# created: 2011/03/31
+#
+
+import time, urllib
+from hashlib import sha256
+from xml.etree.ElementTree import ElementTree
+
+def passphrase(password):
+ """
+ Generates the PASSPRHASE needed for a handshake.
+ """
+ now = int(time.time())
+ key = sha256(password).hexdigest()
+ phrase = sha256(str(now)+key).hexdigest()
+
+ return (now, phrase)
+
+
+class AmpacheArtist(object):
+ """
+ Simple container class corresponding to
+ Ampache's Artist XML.
+ """
+ def __init__(self, element):
+ self.id = element.attrib['id']
+ self.tags = element.findall('tag')
+ self.name = element.find('name').text
+
+ self.albums = element.find('albums').text
+ self.songs = element.find('songs').text
+
+ self.preciserating = element.find('preciserating').text
+ self.rating = element.find('rating').text
+
+class AmpacheAlbum(object):
+ """
+ Simple container class corresponding to
+ Ampache's Album XML.
+ """
+ def __init__(self, element):
+ self.id = element.attrib['id']
+ self.tags = element.findall('tag')
+ self.name = element.find('name').text
+ artist = element.find('artist')
+ self.artist = {'id': artist.attrib['id'], 'name': artist.text}
+
+ self.year = element.find('year').text
+ self.tracks = element.find('tracks').text
+ self.disk = element.find('disk').text
+ self.art = element.find('art').text
+
+ self.preciserating = element.find('preciserating').text
+ self.rating = element.find('rating').text
+
+class AmpacheSong(object):
+ """
+ Simple container class corresponding to
+ Ampache's Song XML.
+ """
+ def __init__(self, element):
+ self.id = element.attrib['id']
+ self.tags = element.findall('tag')
+ self.title = element.find('title').text
+ artist = element.find('artist')
+ self.artist = {'id': artist.attrib['id'], 'name': artist.text}
+ album = element.find('album')
+ self.album = {'id': album.attrib['id'], 'name': album.text}
+
+ self.track = element.find('track').text
+ self.time = element.find('time').text
+ self.url = element.find('url').text
+ self.size = element.find('size').text
+ self.art = element.find('art').text
+
+ self.preciserating = element.find('preciserating').text
+ self.rating = element.find('rating').text
+
+
+class Ampache(object):
+ """
+ This class speaks to an Ampache server through its
+ XML API. Only a few methods are implemented, but
+ every method of the API could be added quickly.
+
+ See http://ampache.org/wiki/dev:xmlapi for info.
+ """
+
+ def __init__(self, url):
+ self.auth = ''
+ self.serverurl = url + u"/server/xml.server.php?"
+
+
+ def __query(self, **kwargs):
+ for k,v in kwargs.items():
+ if type(v) is unicode:
+ kwargs[k] = v.encode('utf8')
+ query = urllib.urlencode(kwargs)
+
+ try:
+ fd = urllib.urlopen(self.serverurl+query)
+ except IOError:
+ self.auth = ''
+ return None
+ else:
+ tree = ElementTree()
+ tree.parse(fd)
+ return tree
+
+
+ def __action(self, action, **kwargs):
+ if not self.auth:
+ return False
+
+ return self.__query(action=action, auth=self.auth, **kwargs)
+
+
+ def handshake(self, username, password):
+
+ timestamp, phrase = passphrase(password)
+ tree = self.__query(action='handshake', auth=phrase, timestamp=timestamp, version=350001, user=username)
+
+ if tree is None:
+ auth = None
+ else:
+ auth = tree.find('auth')
+
+
+ if auth is None:
+ self.auth = ''
+ return False
+ else:
+ self.auth = auth.text
+ return True
+
+
+ # API method 'artist'
+ def artists(self, filter, **kwargs):
+ tree = self.__action('artists', filter=filter, **kwargs)
+ artists = tree.findall('artist')
+ return [AmpacheArtist(a) for a in artists]
+
+ # API method 'artist_songs'
+ def artist_songs(self, artist_uid):
+ tree = self.__action('artist_songs', filter=artist_uid)
+ songs = tree.findall('song')
+ return [AmpacheSong(a) for a in songs]
+
+ # API method 'artist_albums'
+ def artist_albums(self, artist_uid):
+ tree = self.__action('artist_albums', filter=artist_uid)
+ albums = tree.findall('album')
+ return [AmpacheAlbum(a) for a in albums]
+
+ # API method 'albums'
+ def albums(self, filter, **kwargs):
+ tree = self.__action('albums', filter=filter, **kwargs)
+ albums = tree.findall('albums')
+ return [AmpacheAlbums(a) for a in albums]
+
+ # API method 'album_songs'
+ def album_songs(self, album_uid):
+ tree = self.__action('album_songs', filter=album_uid)
+ songs = tree.findall('song')
+ return [AmpacheSong(a) for a in songs]
+
+ # API method 'songs'
+ def songs(self, filter, **kwargs):
+ tree = self.__action('songs', filter=filter, **kwargs)
+ songs = tree.findall('song')
+ return [AmpacheSong(a) for a in songs]
+
+ # API method 'search_songs'
+ def search_songs(self, filter, **kwargs):
+ tree = self.__action('search_songs', filter=filter, **kwargs)
+ songs = tree.findall('song')
+ return [AmpacheSong(a) for a in songs]
1  contrib/ampache-api/playdar_resolver.py
View
Something went wrong with that request. Please try again.