writing my own subsonic api library i guess
This commit is contained in:
1 parent
164e59e353
commit
6edcd1db98
7 files changed
+1283
-63
No files matched your search
+267
-63
@@ -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()
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in new issue
Block a user