summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHombreLaser <sebastian-440@live.com>2022-05-14 14:39:45 -0500
committerHombreLaser <sebastian-440@live.com>2022-05-14 14:39:45 -0500
commit74b01c4942e38afce9efdf60fa46ab573f4f6f86 (patch)
tree54f788021b8933c15b4b79fbc3200130343062cb
Commit inicial
-rw-r--r--src/ampache/__init__.py0
-rw-r--r--src/ampache/ampache.py104
-rw-r--r--src/ampache/exceptions.py20
-rw-r--r--src/ampache/models.py25
-rw-r--r--src/ampache/test.py4
5 files changed, 153 insertions, 0 deletions
diff --git a/src/ampache/__init__.py b/src/ampache/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ampache/__init__.py
diff --git a/src/ampache/ampache.py b/src/ampache/ampache.py
new file mode 100644
index 0000000..9282040
--- /dev/null
+++ b/src/ampache/ampache.py
@@ -0,0 +1,104 @@
+from http import client
+from urllib import parse
+from datetime import datetime
+import exceptions
+import models
+import json
+import requests
+
+
+def get_utc_offset(time):
+ """
+ All the datetimes the API yields are in the form yyyy-mm-ddthh:mm:ss-00:00,
+ where the last 5 characters are the UTC offset. Python datetime objects can
+ parse this data, but in the form 0000 (sans the :) so we have to remove it.
+ """
+ prefix = time[:len(time) - 5]
+ suffix = time[len(time) - 5:].replace(':', '')
+
+ return prefix + suffix
+
+
+class AmpacheClient:
+ """
+ The ampache client class. Responsible for making API calls to your ampache
+ instance.
+ """
+ def __init__(self, host, api_key, version):
+ """
+ Host: url of your apache instance.
+ api_key: your api key (you can get it under settings->account). It's
+ preferable that you provide an admin's api key.
+ """
+ self._endpoint = '/server/json.server.php?'
+ self._version = version
+ self._host = host
+ self._api_key = api_key
+ self.authenticate()
+
+ def raise_by_status(self, error_code):
+ """
+ The ampache API has a bunch of error codes that can help us diagnose
+ the problem. Depending of the error code, we'll raise an appropiate exception.
+ """
+ pass
+
+ def request(self, params, headers):
+ """
+ All in one function to pass JSON requests to the API.
+ """
+ self.renew_token()
+
+ response = requests.get(self._host + self._endpoint, params=params,
+ headers=headers)
+ if not response.ok:
+ response.raise_for_status()
+
+ data = response.json()
+
+ if 'error' in data:
+ raise possible_exception(data['error']['errorMessage'])
+
+ return data
+
+
+ def authenticate(self):
+ """
+ Authenticate with the API, setting the token.
+ """
+ params = {
+ 'action': 'handshake',
+ 'auth': self._api_key,
+ 'version': self._version
+ }
+ headers = {
+ 'Content-type': 'application/json'
+ }
+
+ data = self.request(params, headers)
+ self._auth = models.AuthToken(datetime.strptime(get_utc_offset(data['session_expire']), '%Y-%m-%dT%H:%M:%S%z'),
+ data['auth'])
+
+ def get_song(self, song_id):
+ """
+ Get the detail of a song given its primary key.
+ """
+ self.renew_token()
+
+ params = {
+ 'action': 'song',
+ 'auth': self._auth,
+ 'filter': song_id,
+ 'version': self._version
+ }
+ headers = {
+ 'Content-type': 'application/json'
+ }
+ data = self.request(params, headers)
+
+ def renew_token(self):
+ if datetime.now(self._auth.expires.tzinfo) > self._auth.expires:
+ self.authenticate()
+
+ def get_token(self):
+ return self._auth
diff --git a/src/ampache/exceptions.py b/src/ampache/exceptions.py
new file mode 100644
index 0000000..345d8e2
--- /dev/null
+++ b/src/ampache/exceptions.py
@@ -0,0 +1,20 @@
+class AccessException(Exception):
+ """
+ Happens when the API is not enabled. Error code: 4700-
+ """
+ pass
+
+
+class AuthenticationException(Exception):
+ """
+ Happens in faulty authentication or when the session expires.
+ Error code: 4701.
+ """
+ pass
+
+
+class AccessDeniedException(Exception):
+ """
+ Happens when the request method is not enabled. Error code: 4703
+ """
+ pass
diff --git a/src/ampache/models.py b/src/ampache/models.py
new file mode 100644
index 0000000..2e0ed1b
--- /dev/null
+++ b/src/ampache/models.py
@@ -0,0 +1,25 @@
+"""
+The data structures of the ampache API (songs, artists, albums, etc).
+"""
+from dataclasses import dataclass
+import datetime
+
+
+@dataclass
+class AuthToken:
+ expires: datetime.datetime
+ auth: str
+
+ def __str__(self):
+ return f"Expires: {self.expires}\nToken: {self.auth}"
+
+
+@dataclass
+class Song:
+ song_id: str
+ title: str
+ album: str
+ artist: str
+
+ def __str__(self):
+ return f"{self.title} by {self.artist}"
diff --git a/src/ampache/test.py b/src/ampache/test.py
new file mode 100644
index 0000000..8ca38df
--- /dev/null
+++ b/src/ampache/test.py
@@ -0,0 +1,4 @@
+from ampache import AmpacheClient
+
+my_ampache = AmpacheClient('https://music.silosneeded.com', '22efaa9fecfd8f074ef4bc95e85a1b84', '532000')
+print(my_ampache.get_token())