Initial commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
last_fm_credentials.json
|
||||||
|
__pycache__/
|
||||||
29
last_fm.py
Normal file
29
last_fm.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import json
|
||||||
|
from typing import List
|
||||||
|
|
||||||
|
class LastFm:
|
||||||
|
def __init__(self, credentials_file):
|
||||||
|
with open(credentials_file, 'r') as f:
|
||||||
|
credentials = json.loads(f.read())
|
||||||
|
|
||||||
|
self.lastfm = pylast.LastFMNetwork(
|
||||||
|
api_key=credentials['api_kay'],
|
||||||
|
api_secret=credentials['api_secret']
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_recent_plays(self, username):
|
||||||
|
self.lastfm.get_user(username).get_recent_tracks(limit=200)
|
||||||
|
|
||||||
|
def get_top_artists(self, username: str, min_scrobbles: int) -> List[pylast.TopItem]:
|
||||||
|
artists = []
|
||||||
|
page = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
artists_page = self.lastfm.get_user(username).get_top_artists()
|
||||||
|
|
||||||
|
for artist in artists_page:
|
||||||
|
if (artist.weight > min_scrobbles):
|
||||||
|
artists.append(artist)
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
57
main.py
Normal file
57
main.py
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
from sys import argv
|
||||||
|
|
||||||
|
usage = """
|
||||||
|
Usage:
|
||||||
|
|
||||||
|
add_lastfm_user
|
||||||
|
recents
|
||||||
|
discography of artists over x plays
|
||||||
|
recommendations?
|
||||||
|
|
||||||
|
add_playlist <playlist_id>
|
||||||
|
spotify
|
||||||
|
tidal
|
||||||
|
lastfm?
|
||||||
|
last fm likes?
|
||||||
|
spotify likes
|
||||||
|
tidal likes?
|
||||||
|
|
||||||
|
update existing data from mb
|
||||||
|
auto import/data gather of downlads from bandcamp
|
||||||
|
"""
|
||||||
|
|
||||||
|
def sync():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add_lastfm_user(username):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def add_playlist(playlist_id):
|
||||||
|
pass
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(argv) == 1:
|
||||||
|
print(usage)
|
||||||
|
exit()
|
||||||
|
|
||||||
|
if argv[1] == "sync":
|
||||||
|
sync()
|
||||||
|
|
||||||
|
elif argv[1] == "add_lastfm_user":
|
||||||
|
if len(argv) < 3:
|
||||||
|
print("Please provide a lastfm username")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
username = argv[2]
|
||||||
|
add_lastfm_user(username)
|
||||||
|
|
||||||
|
elif argv[1] == "add_playlist":
|
||||||
|
if len(argv) < 3:
|
||||||
|
print("Please provide a playlist id")
|
||||||
|
exit()
|
||||||
|
|
||||||
|
playlist_id = argv[2]
|
||||||
|
add_playlist(playlist_id)
|
||||||
|
|
||||||
|
else:
|
||||||
|
print(f"Invalid argument '{argv[1]}'")
|
||||||
40
musicbrainz.py
Normal file
40
musicbrainz.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from datetime import datetime, timedelta, UTC
|
||||||
|
from typing import Dict, List
|
||||||
|
from requests import get
|
||||||
|
from musicbrainz_entities import MbRecording, MbArtist
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
class MusicBrainz:
|
||||||
|
def __init__(self, application_name: str, version: str, contact: str, root_url: str = "https://musicbrainz.org/ws/2/"):
|
||||||
|
self._user_agent_string = f"{application_name}/{version} ( {contact} )"
|
||||||
|
self._last_request_time = datetime.now(UTC) + timedelta(seconds=-1)
|
||||||
|
self._root_url = root_url
|
||||||
|
|
||||||
|
def _request(self, method, endpoint:str, params: Dict[str, object] = dict()):
|
||||||
|
url = f"{self._root_url.rstrip('/')}/{endpoint.lstrip('/')}"
|
||||||
|
params['fmt'] = 'json'
|
||||||
|
# TODO: retries
|
||||||
|
|
||||||
|
if datetime.now(UTC) - self._last_request_time < timedelta(seconds=1):
|
||||||
|
sleep(1 - (datetime.now(UTC) - self._last_request_time).total_seconds())
|
||||||
|
|
||||||
|
response = method(url, params=params)
|
||||||
|
self._last_request_time = datetime.now(UTC)
|
||||||
|
return response
|
||||||
|
|
||||||
|
def isrc_lookup(self, isrc: str) -> List[MbRecording]:
|
||||||
|
result = self._request(get, f"/isrc/{isrc}", { 'inc': 'artists+isrcs+releases+url-rels' })
|
||||||
|
return [MbRecording(recording) for recording in result.json()['recordings']]
|
||||||
|
|
||||||
|
def get_artist_by_id(self, id: str) -> MbArtist:
|
||||||
|
result = self._request(get, f'/artist/{id}', { 'inc': 'genres' })
|
||||||
|
return MbArtist(result.json())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
mb = MusicBrainz("pob_tag_test", "0.1", "musicbrainz@pobnellion.com")
|
||||||
|
|
||||||
|
res = mb.isrc_lookup('JPPC09428330')
|
||||||
|
print(res[0].title)
|
||||||
|
artist = mb.get_artist_by_id(res[0].artist_credit[0].id)
|
||||||
|
print(artist.name)
|
||||||
34
musicbrainz_entities.py
Normal file
34
musicbrainz_entities.py
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
from typing import List
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
|
||||||
|
class MbArtistCredit:
|
||||||
|
def __init__(self, mb_json):
|
||||||
|
self.id: str = mb_json['artist']['id']
|
||||||
|
self.name: str = mb_json['artist']['name']
|
||||||
|
self.type: str = mb_json['artist']['type']
|
||||||
|
self.country: str = mb_json['artist']['country']
|
||||||
|
self.disambiguation: str = mb_json['artist']['disambiguation']
|
||||||
|
self.join_phrase: str = mb_json['joinphrase']
|
||||||
|
|
||||||
|
|
||||||
|
class MbRecording:
|
||||||
|
def __init__(self, mb_json):
|
||||||
|
self.id: str = mb_json['id']
|
||||||
|
self.title: str = mb_json['title']
|
||||||
|
self.is_video: bool = mb_json['video']
|
||||||
|
self.disambiguation: str = mb_json['disambiguation']
|
||||||
|
self.isrcs: List[str] = mb_json['isrcs']
|
||||||
|
self.first_release_date: datetime = datetime.strptime(mb_json['first-release-date'], '%Y-%m-%d')
|
||||||
|
self.length: timedelta = timedelta(seconds = int(mb_json['length']))
|
||||||
|
self.artist_credit: List[MbArtistCredit] = [MbArtistCredit(artist_credit) for artist_credit in mb_json['artist-credit']]
|
||||||
|
|
||||||
|
|
||||||
|
class MbArtist:
|
||||||
|
def __init__(self, mb_json):
|
||||||
|
self.id: str = mb_json['id']
|
||||||
|
self.name: str = mb_json['name']
|
||||||
|
self.disambiguation: str = mb_json['disambiguation']
|
||||||
|
self.country: str = mb_json['country']
|
||||||
|
# TODO: more
|
||||||
|
|
||||||
5
track_cache_db.py
Normal file
5
track_cache_db.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import sqlite3
|
||||||
|
|
||||||
|
class TrackCacheDb:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
Reference in New Issue
Block a user