diff --git a/Artist.py b/Artist.py
new file mode 100644
index 0000000..3fa0694
--- /dev/null
+++ b/Artist.py
@@ -0,0 +1,15 @@
+class Artist:
+ id: str
+ name: str
+ albumCount: int
+ coverArt: str
+ artistImageUrl: str
+
+ def __init__(self, id: str, name: str, albumCount: str | int, coverArt: str, artistImageUrl: str):
+ self.id = id
+ self.name = name
+ self.albumCount = int(albumCount)
+ self.coverArt = coverArt
+ self.artistImageUrl = artistImageUrl
+
+
diff --git a/ArtistIndex.py b/ArtistIndex.py
new file mode 100644
index 0000000..634ae63
--- /dev/null
+++ b/ArtistIndex.py
@@ -0,0 +1,65 @@
+import xml.etree.ElementTree
+
+import Artist
+
+
+class ArtistIndex:
+ name: str
+ artists: list[Artist.Artist]
+
+ def __init__(self, indexInfo: dict, artists: list[dict]):
+ self.name = indexInfo['name']
+
+ self.artists = []
+ for artist in artists:
+ self.artists.append(Artist.Artist(
+ artist['id'],
+ artist['name'],
+ artist['albumCount'],
+ artist['coverArt'],
+ artist['artistImageUrl']
+ ))
+
+
+
+class ArtistIndexes:
+ indexes: list[ArtistIndex]
+
+ def __init__(self, xml_data: bytes):
+ self._parseXml(xml_data.decode('utf-8'))
+
+ def _parseXml(self, xml_data: str):
+ root = xml.etree.ElementTree.fromstring(xml_data)
+
+ self.indexes: list[ArtistIndex] = []
+
+ if root.get('status') != 'ok':
+ return None
+
+ in_index = False
+ artists = []
+ index_info = None
+ for item in root.iter():
+ print(item.tag, dict(item.items()))
+
+ if item.tag == '{http://subsonic.org/restapi}index':
+
+ if in_index:
+ in_index = not in_index
+
+ self.indexes.append(ArtistIndex(index_info, artists))
+
+ artists = []
+ else:
+ in_index = not in_index
+ index_info = dict(item.items())
+
+ elif item.tag == '{http://subsonic.org/restapi}artist':
+ artists.append(dict(item.items()))
+
+
+
+
+
+
+
diff --git a/SubSonic.py b/SubSonic.py
index 95a437b..cb0cf03 100644
--- a/SubSonic.py
+++ b/SubSonic.py
@@ -10,76 +10,280 @@ import xml.etree.ElementTree
import requests
import libsonic
import simpleaudio
-import pyaudio
+# import pyaudio
u = 'pseudo'
p = 'telegram9dock-MICHEL'
-
-def saltGenerator() -> str:
- return ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(8))
-
-salt = saltGenerator()
-t = hashlib.md5((p + salt).encode('utf-8')).hexdigest()
-
-payload = {
- "u" : u,
- "t" : t,
- "s" : salt,
- "v" : '1.16.1',
- "c" : 'testing'
-}
-
-url = 'https://music.0x01fe.net/rest/getArtists?'
-
-url = url + urllib.parse.urlencode(payload, quote_via=urllib.parse.quote_plus)
-
-# print(url)
-# response = requests.get(url)
-
-# with open("artist_response.xml", 'wb') as file:
-# file.write(response.content)
-
-
-
class Artist:
-
id: str
- imageUrl: str
name: str
albumCount: int
+ coverArt: str
+ artistImageUrl: str
- def __init__(self):
- pass
+ def __init__(self, id: str, name: str, albumCount: str | int, coverArt: str, artistImageUrl: str):
+ self.id = id
+ self.name = name
+ self.albumCount = int(albumCount)
+ self.coverArt = coverArt
+ self.artistImageUrl = artistImageUrl
- def fromDict(self, d: dict):
- self.id = d['id']
- self.imageUrl = d['artistImageUrl']
- self.name = d['name']
- self.albumCount = d['albumCount']
+class ArtistIndex:
+ name: str
+ artists: list[Artist]
-def getArtists() -> list[Artist]:
- tree = xml.etree.ElementTree.parse("artist_response.xml")
- root = tree.getroot()
+ def __init__(self, indexInfo: dict, artists: list[dict]):
+ self.name = indexInfo['name']
- artists: list[Artist] = []
+ self.artists = []
+ for artist in artists:
+ self.artists.append(Artist(
+ artist['id'],
+ artist['name'],
+ artist['albumCount'],
+ artist['coverArt'],
+ artist['artistImageUrl']
+ ))
- if root.get('status') != 'ok':
- return []
+class ArtistIndexes:
+ indexes: list[ArtistIndex]
- for item in root.iter():
- print(item.tag, dict(item.items()))
+ def __init__(self, xml_data: bytes):
+ self._parseXml(xml_data.decode('utf-8'))
- if item.tag == '{http://subsonic.org/restapi}artist':
- a = Artist()
- a.fromDict(dict(item.items()))
+ def _parseXml(self, xml_data: str):
+ root = xml.etree.ElementTree.fromstring(xml_data)
- artists.append(a)
+ self.indexes: list[ArtistIndex] = []
+
+ if root.get('status') != 'ok':
+ return None
+
+ in_index = False
+ artists = []
+ index_info = None
+ for item in root.iter():
+ # print(item.tag, dict(item.items()))
+
+ if item.tag == '{http://subsonic.org/restapi}index':
+
+ if in_index:
+ in_index = not in_index
+
+ self.indexes.append(ArtistIndex(index_info, artists))
+
+ artists = []
+ else:
+ in_index = not in_index
+ index_info = dict(item.items())
+
+ elif item.tag == '{http://subsonic.org/restapi}artist':
+ artists.append(dict(item.items()))
+
+class Album:
+ id: str
+ title: str
+ name: str
+ album: str
+ coverArtId: str
+ duration: int
+ artistId: str
+ songCount: int
+
+ def __init__(self, album_info: dict):
+ self.id = album_info['id']
+ self.title = album_info['title']
+ self.name = album_info['name']
+ self.album = album_info['album']
+ self.coverArtId = album_info['coverArt']
+ self.duration = int(album_info['duration'])
+ self.artistId = album_info['artistId']
+ self.songCount = int(album_info['songCount'])
+
+class Song:
+ id: str
+ title: str
+ album: str
+ artist: str
+ trackNumber: int
+ contentType: str
+ suffix: str
+ duration: int
+ bitRate: int
+ path: str
+ discNumber: int
+ albumId: str
+ artistId: str
+ comment: str
+ channelCount: int
+ samplingRate: int
+
+ def __init__(self, song_info: dict):
+ self.id = song_info['id']
+ self.title = song_info['title']
+ self.album = song_info['album']
+ self.artist = song_info['artist']
+ self.trackNumber = int(song_info['track'])
+ self.contentType = song_info['contentType']
+ self.suffix = song_info['suffix']
+ self.duration = int(song_info['duration'])
+ self.bitRate = int(song_info['bitRate'])
+ self.path = song_info['path']
+ self.discNumber = int(song_info['discNumber'])
+ self.albumId = song_info['albumId']
+ self.artistId = song_info['artistId']
+ self.comment = song_info['comment']
+ self.channelCount = int(song_info['channelCount'])
+ self.samplingRate = int(song_info['samplingRate'])
+
+class SubpyConn:
+ username: str
+ password: str
+ base_url: str
+ salt: str
+ salt_len: int = 8
+ version: str = "1.16.1"
+ client_name: str = "testing"
+
+ def __init__(self, u: str, p: str, base_url: str, salt_len: int | None = 8):
+ self.username = u
+ self.password = p
+ self.base_url = base_url
+
+ self.salt_len = salt_len
+
+ def _saltGenerator(self) -> None:
+ self.salt = ''.join(random.SystemRandom().choice(string.ascii_uppercase + string.digits) for _ in range(self.salt_len))
+
+ def _hashPass(self) -> str:
+ self._saltGenerator()
+ return hashlib.md5((self.password + self.salt).encode('utf-8')).hexdigest()
+
+ def _getBasePayload(self) -> dict:
+ return {
+ "u" : self.username,
+ "t" : self._hashPass(),
+ "s" : self.salt,
+ "v" : self.version,
+ "c" : self.client_name
+ }
+
+ def _encodePayload(self, payload: dict) -> str:
+ return urllib.parse.urlencode(payload, quote_via=urllib.parse.quote_plus)
+
+ def getIndexes(self) -> ArtistIndexes:
+ url = self.base_url + '/rest/getIndexes?'
+
+ return ArtistIndexes(requests.get(url + self._encodePayload(self._getBasePayload())).content)
+
+ def _getMusicDirectory(self, id: str):
+ url = self.base_url + '/rest/getMusicDirectory?'
+
+ payload = self._getBasePayload()
+ payload['id'] = id
+
+ return requests.get(url + self._encodePayload(payload))
+
+ def getArtistAlbums(self, artist_id: str) -> list[Album]:
+ r: requests.Response = self._getMusicDirectory(artist_id)
+ xml_data: str = r.content.decode('utf-8')
+
+ root: xml.etree.ElementTree.Element = xml.etree.ElementTree.fromstring(xml_data)
+ albums: list[Album] = []
+
+ for item in root.iter():
+ # print(item.tag, dict(item.items()))
+
+ if item.tag == '{http://subsonic.org/restapi}child':
+ albums.append(Album(dict(item.items())))
+
+ return albums
+
+ def getAlbumSongs(self, album_id: str) -> list[Song]:
+ r: requests.Response = self._getMusicDirectory(album_id)
+ xml_data: str = r.content.decode('utf-8')
+
+ root: xml.etree.ElementTree.ElementTree = xml.etree.ElementTree.fromstring(xml_data)
+ songs: list[Song] = []
+
+ for item in root.iter():
+
+ if item.tag == '{http://subsonic.org/restapi}child':
+ songs.append(Song(dict(item.items())))
+
+ return songs
+
+ def stream(self, song_id: str):
+ url = self.base_url + '/rest/stream?'
+
+ payload = self._getBasePayload()
+
+ payload['id'] = song_id
+
+ return requests.get(url + self._encodePayload(payload))
+
+conn = SubpyConn(u, p, "https://music.0x01fe.net")
- return artists
+# artistIndexes = conn.getIndexes()
+# for artistIndex in artistIndexes.indexes:
+# print(artistIndex.name, artistIndex.artists)
+
+helios_id = 'c69cdc593487ed813f1e11ecb270b228'
+yakui_id = "7f6ca9951af294420382442061a2d6ee"
+# r = conn.getMusicDirectory(helios_id)
+# with open("getHelios.xml", 'wb') as file:
+# file.write(r.content)
+
+# yakui_albums = conn.getArtistAlbums(yakui_id)
+
+# for album in yakui_albums:
+# print(album.name)
+
+helios_songs = conn.getAlbumSongs(helios_id)
+for song in helios_songs:
+ print(song.trackNumber, song.title)
+
+# class Artist:
+
+# id: str
+# imageUrl: str
+# name: str
+# albumCount: int
+
+# def __init__(self):
+# pass
+
+# def fromDict(self, d: dict):
+# self.id = d['id']
+# self.imageUrl = d['artistImageUrl']
+# self.name = d['name']
+# self.albumCount = d['albumCount']
+
+# def getArtists() -> list[Artist]:
+# tree = xml.etree.ElementTree.parse("artist_response.xml")
+# root = tree.getroot()
+
+# artists: list[Artist] = []
+
+# if root.get('status') != 'ok':
+# return []
+
+# for item in root.iter():
+# print(item.tag, dict(item.items()))
+
+# if item.tag == '{http://subsonic.org/restapi}artist':
+# a = Artist()
+# a.fromDict(dict(item.items()))
+
+# artists.append(a)
+
+
+
+# return artists
@@ -89,26 +293,26 @@ def getArtists() -> list[Artist]:
# print(artist.name)
-conn = libsonic.Connection('https://music.0x01fe.net', 'pseudo', p, port=443)
+# conn = libsonic.Connection('https://music.0x01fe.net', 'pseudo', p, port=443)
-song = conn.getRandomSongs(1)['randomSongs']['song'][0]
-song_id = song['id']
-rate = song['samplingRate']
+# song = conn.getRandomSongs(1)['randomSongs']['song'][0]
+# song_id = song['id']
+# rate = song['samplingRate']
-print(song_id)
+# print(song_id)
-stream = conn.stream(song_id)
+# stream = conn.stream(song_id)
-while not stream.fp:
- pass
+# while not stream.fp:
+# pass
-pya = pyaudio.PyAudio()
-pya_stream = pya.open(format=)
-wave_obj = simpleaudio.WaveObject(stream.fp)
-play_obj = wave_obj.play()
-play_obj.wait_done()
+# pya = pyaudio.PyAudio()
+# pya_stream = pya.open(format=)
+# wave_obj = simpleaudio.WaveObject(stream.fp)
+# play_obj = wave_obj.play()
+# play_obj.wait_done()
diff --git a/responses/artist_response.xml b/responses/artist_response.xml
new file mode 100644
index 0000000..fa0272e
--- /dev/null
+++ b/responses/artist_response.xml
@@ -0,0 +1,382 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/responses/getHelios.xml b/responses/getHelios.xml
new file mode 100644
index 0000000..6e4bbe7
--- /dev/null
+++ b/responses/getHelios.xml
@@ -0,0 +1,141 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/responses/getIndexes.xml b/responses/getIndexes.xml
new file mode 100644
index 0000000..4f46f50
--- /dev/null
+++ b/responses/getIndexes.xml
@@ -0,0 +1,297 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/responses/getYakui.xml b/responses/getYakui.xml
new file mode 100644
index 0000000..c16a748
--- /dev/null
+++ b/responses/getYakui.xml
@@ -0,0 +1,116 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file