2022-11-21 08:07:52 +00:00
|
|
|
from src.settings import get_config
|
2022-12-18 01:02:53 +00:00
|
|
|
import requests
|
|
|
|
import json
|
|
|
|
import time
|
2022-11-20 22:49:19 +00:00
|
|
|
import urllib.parse
|
2022-11-09 10:11:36 +00:00
|
|
|
import os
|
2022-11-01 10:15:28 +00:00
|
|
|
from loguru import logger
|
|
|
|
|
2023-02-05 23:01:53 +00:00
|
|
|
attempts_for_federate = 3
|
2022-11-09 10:11:36 +00:00
|
|
|
auth_file = '.auth.json'
|
|
|
|
if os.path.exists(auth_file):
|
|
|
|
with open('.auth.json', 'rt') as f:
|
|
|
|
auth = json.loads(f.read())
|
|
|
|
else:
|
|
|
|
# The default umask is 0o22 which turns off write permission of group and others
|
|
|
|
os.umask(0)
|
|
|
|
|
|
|
|
descriptor = os.open(
|
|
|
|
path=auth_file,
|
|
|
|
flags=(
|
|
|
|
os.O_WRONLY # access mode: write only
|
|
|
|
| os.O_CREAT # create if not exists
|
|
|
|
| os.O_TRUNC # truncate the file to zero
|
|
|
|
),
|
|
|
|
mode=0o600)
|
|
|
|
with open(descriptor, 'wt') as f:
|
|
|
|
f.write('{}')
|
|
|
|
auth = {}
|
2022-11-01 10:15:28 +00:00
|
|
|
|
2022-11-03 23:45:40 +00:00
|
|
|
|
2022-12-04 01:01:11 +00:00
|
|
|
class current_instance:
|
|
|
|
s = requests.Session()
|
2023-01-02 15:43:18 +00:00
|
|
|
s.headers.update({"Accept-encoding": 'gzip, br, deflate'})
|
2022-12-04 01:01:11 +00:00
|
|
|
instance = get_config('instance')
|
|
|
|
token = auth.get(instance)
|
2023-01-02 14:43:50 +00:00
|
|
|
listen_token = None
|
|
|
|
|
2022-12-18 01:02:53 +00:00
|
|
|
|
2022-12-04 01:01:11 +00:00
|
|
|
@logger.catch
|
|
|
|
def select_instance(new_instance=None):
|
|
|
|
current_instance.instance = new_instance
|
|
|
|
with open(auth_file, 'rt') as f:
|
|
|
|
auth = json.loads(f.read())
|
|
|
|
new_token = auth.get(current_instance.instance)
|
2023-01-02 15:43:18 +00:00
|
|
|
current_instance.s.headers.update({"Authorization": None})
|
2023-01-02 14:43:50 +00:00
|
|
|
current_instance.token = new_token
|
|
|
|
current_instance.listen_token = None
|
2022-12-04 01:01:11 +00:00
|
|
|
if new_token:
|
|
|
|
s.get(f'https://{current_instance.instance}')
|
2023-01-02 15:43:18 +00:00
|
|
|
s.headers.update({"Authorization": "Bearer " + new_token})
|
2022-12-04 01:01:11 +00:00
|
|
|
|
|
|
|
|
|
|
|
if current_instance.token:
|
2023-01-02 15:43:18 +00:00
|
|
|
current_instance.s.headers.update({"Authorization": "Bearer " + current_instance.token})
|
2022-11-03 23:45:40 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
# Get cookies from unauthorized instance for working some functionality (radios)
|
|
|
|
current_instance.s.get(f'https://{current_instance.instance}/')
|
2023-01-02 14:43:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
@logger.catch
|
|
|
|
def get_me():
|
|
|
|
'''Return current user if token avalaible'''
|
|
|
|
if not current_instance.token:
|
|
|
|
return
|
|
|
|
r = current_instance.s.get(f'https://{current_instance.instance}/api/v1/users/me')
|
|
|
|
resp = r.json()
|
|
|
|
current_instance.listen_token = resp['tokens']['listen']
|
|
|
|
return resp
|
2022-11-03 23:45:40 +00:00
|
|
|
|
|
|
|
|
2022-11-27 23:17:21 +00:00
|
|
|
@logger.catch
|
|
|
|
def get_instance_settings():
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/instance/settings')
|
2022-11-27 23:17:21 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-18 15:57:25 +00:00
|
|
|
@logger.catch
|
2023-01-02 01:19:09 +00:00
|
|
|
def get_audio_file(track_uuid, listen_url=False, download=False,
|
|
|
|
external_transcoding=get_config('external_transcoder_http_proxy_path'),
|
2022-11-21 08:07:52 +00:00
|
|
|
transcoding=get_config('enable_server_transcoding'), to='ogg'):
|
2022-11-18 15:57:25 +00:00
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
"download": download,
|
|
|
|
"to": to
|
2022-11-18 15:57:25 +00:00
|
|
|
}
|
2023-01-02 14:43:50 +00:00
|
|
|
if current_instance.token and not current_instance.listen_token:
|
|
|
|
get_me()
|
|
|
|
if current_instance.listen_token:
|
|
|
|
params['token'] = current_instance.listen_token
|
|
|
|
|
2022-12-20 01:05:54 +00:00
|
|
|
if not transcoding:
|
|
|
|
del params['to']
|
2022-11-18 15:57:25 +00:00
|
|
|
if listen_url:
|
2022-12-04 01:01:11 +00:00
|
|
|
url = f'https://{current_instance.instance}{track_uuid}?'
|
2022-11-18 15:57:25 +00:00
|
|
|
else:
|
2022-12-04 01:01:11 +00:00
|
|
|
url = f'https://{current_instance.instance}/api/v1/listen/{track_uuid}?'
|
2023-01-02 01:19:09 +00:00
|
|
|
if external_transcoding != "":
|
|
|
|
url = external_transcoding + url
|
2022-12-20 01:05:54 +00:00
|
|
|
return url + urllib.parse.urlencode(params, doseq=True)
|
2022-11-01 10:15:28 +00:00
|
|
|
|
2022-11-03 23:45:40 +00:00
|
|
|
|
2022-11-08 17:58:27 +00:00
|
|
|
@logger.catch
|
2022-12-29 20:14:28 +00:00
|
|
|
def get_tracks(page=None, q=None, artist=None, album=None, library=None,
|
2022-11-30 00:17:18 +00:00
|
|
|
tag=None, favourites=None, include_channels=None, pg=None):
|
2022-11-03 23:45:40 +00:00
|
|
|
'''This function get tracks by params'''
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'q': q,
|
|
|
|
'artist': artist,
|
|
|
|
'album': album,
|
|
|
|
'tag': tag,
|
|
|
|
'favourites': favourites,
|
2022-12-29 20:14:28 +00:00
|
|
|
'library': library,
|
2022-12-18 01:02:53 +00:00
|
|
|
'include_channels': include_channels
|
2022-11-03 23:45:40 +00:00
|
|
|
}
|
2022-11-08 17:58:27 +00:00
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-08 17:58:27 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/tracks', params=params)
|
2022-11-08 17:58:27 +00:00
|
|
|
return r.json()
|
|
|
|
|
2022-11-27 23:17:21 +00:00
|
|
|
|
2022-11-15 01:22:32 +00:00
|
|
|
@logger.catch
|
|
|
|
def get_favorires_tracks(page=None, q=None, scope=None, include_channels=None, pg=None):
|
2023-06-06 23:37:52 +00:00
|
|
|
'''Get favorites tracks (not only for user)'''
|
2022-11-15 01:22:32 +00:00
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'q': q,
|
|
|
|
'scope': scope,
|
|
|
|
'include_channels': include_channels
|
2022-11-15 01:22:32 +00:00
|
|
|
}
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-15 01:22:32 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/favorites/tracks/', params=params)
|
2022-11-15 01:22:32 +00:00
|
|
|
return r.json()
|
|
|
|
|
2022-11-03 23:45:40 +00:00
|
|
|
|
2023-06-06 23:37:52 +00:00
|
|
|
@logger.catch
|
|
|
|
def get_recently_listened(page=None, q=None, scope=None, include_channels=None, pg=None):
|
|
|
|
'''Get recently listened tracks (not only for user)'''
|
|
|
|
params = {
|
|
|
|
'page': page,
|
|
|
|
'q': q,
|
|
|
|
'scope': scope,
|
|
|
|
'include_channels': include_channels
|
|
|
|
}
|
|
|
|
if pg:
|
|
|
|
r = current_instance.s.get(pg)
|
|
|
|
else:
|
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/history/listenings', params=params)
|
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-08 17:58:27 +00:00
|
|
|
@logger.catch
|
2022-12-29 20:14:28 +00:00
|
|
|
def get_artists(page=None, q=None, artist=None, album=None,
|
|
|
|
library=None, favourites=None, refresh=False, pg=None):
|
2022-11-08 17:58:27 +00:00
|
|
|
'''This function get artists by params'''
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'q': q,
|
|
|
|
'artist': artist,
|
|
|
|
'album': album,
|
2022-12-29 20:14:28 +00:00
|
|
|
'library': library,
|
2022-12-18 01:02:53 +00:00
|
|
|
'favourites': favourites,
|
|
|
|
'refresh': refresh
|
2022-11-08 17:58:27 +00:00
|
|
|
}
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-08 17:58:27 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/artists', params=params)
|
2022-11-03 23:45:40 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-08 17:58:27 +00:00
|
|
|
@logger.catch
|
2022-12-29 20:14:28 +00:00
|
|
|
def get_albums(page=None, q=None, artist=None, library=None, include_channels=None, refresh=False, pg=None):
|
2022-11-08 17:58:27 +00:00
|
|
|
'''This function get artists by params'''
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'q': q,
|
|
|
|
'artist': artist,
|
2022-12-29 20:14:28 +00:00
|
|
|
'library': library,
|
2022-12-18 01:02:53 +00:00
|
|
|
'include_channels': include_channels,
|
|
|
|
'refresh': refresh
|
2022-11-08 17:58:27 +00:00
|
|
|
}
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-08 17:58:27 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/albums', params=params)
|
2022-11-08 17:58:27 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-09 01:01:02 +00:00
|
|
|
@logger.catch
|
|
|
|
def get_channels(page=None, q=None, tag=None, pg=None):
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'q': q,
|
|
|
|
'tag': tag
|
2022-11-09 01:01:02 +00:00
|
|
|
}
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-09 01:01:02 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/channels', params=params)
|
2022-11-09 01:01:02 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-10 15:55:36 +00:00
|
|
|
@logger.catch
|
2022-11-15 00:40:58 +00:00
|
|
|
def get_playlists(page=None, page_size=None, q=None, ordering='-modification_date', pg=None):
|
2022-11-10 15:55:36 +00:00
|
|
|
'''List playlists'''
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'page_size': page_size,
|
|
|
|
'q': q,
|
|
|
|
'ordering': ordering
|
2022-11-10 15:55:36 +00:00
|
|
|
}
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-10 15:55:36 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/playlists', params=params)
|
2022-11-10 15:55:36 +00:00
|
|
|
r.raise_for_status()
|
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch
|
|
|
|
def get_playlist_tracks(playlist_id, pg=None):
|
|
|
|
'''Retrieve all tracks in the playlist'''
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-10 15:55:36 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/playlists/{playlist_id}/tracks')
|
2022-11-10 15:55:36 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-08 20:39:01 +00:00
|
|
|
@logger.catch
|
|
|
|
def list_libraries(page=None, page_size=None, q=None, scope='all', pg=None):
|
2022-11-08 00:29:44 +00:00
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'page': page,
|
|
|
|
'page_size': page_size,
|
|
|
|
'q': q,
|
|
|
|
'scope': scope,
|
2022-11-08 00:29:44 +00:00
|
|
|
}
|
2022-11-08 20:39:01 +00:00
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-08 20:39:01 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/libraries', params=params)
|
2022-11-08 00:29:44 +00:00
|
|
|
return r.json()
|
|
|
|
|
2022-12-18 01:02:53 +00:00
|
|
|
|
2022-11-30 00:17:18 +00:00
|
|
|
@logger.catch
|
|
|
|
def get_tags(q=None, pg=None):
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'q': q,
|
2022-11-30 00:17:18 +00:00
|
|
|
}
|
|
|
|
if pg:
|
2022-12-04 01:01:11 +00:00
|
|
|
r = current_instance.s.get(pg)
|
2022-11-30 00:17:18 +00:00
|
|
|
else:
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/tags', params=params)
|
2022-11-30 00:17:18 +00:00
|
|
|
return r.json()
|
|
|
|
|
2022-11-08 00:29:44 +00:00
|
|
|
|
2022-11-09 01:01:02 +00:00
|
|
|
@logger.catch
|
|
|
|
def federate_search_by_url(object):
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'object': object
|
2022-11-09 01:01:02 +00:00
|
|
|
}
|
2023-02-05 23:01:53 +00:00
|
|
|
for i in range(attempts_for_federate):
|
|
|
|
try:
|
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/federation/fetches', json=params)
|
|
|
|
r.raise_for_status()
|
|
|
|
break
|
|
|
|
except Exception as Err:
|
|
|
|
logger.error(f'Attempt {i}: {Err}')
|
|
|
|
time.sleep(3)
|
2022-11-09 01:01:02 +00:00
|
|
|
return r.json()
|
2022-12-18 01:02:53 +00:00
|
|
|
|
2022-12-07 23:36:45 +00:00
|
|
|
|
2022-12-29 20:14:28 +00:00
|
|
|
@logger.catch
|
|
|
|
def federate_remote_library(fid):
|
|
|
|
'''Fetch remote library for follow and scan'''
|
|
|
|
params = {
|
|
|
|
'fid': fid
|
|
|
|
}
|
2023-02-05 23:01:53 +00:00
|
|
|
for i in range(attempts_for_federate):
|
|
|
|
try:
|
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/federation/libraries/fetch', json=params)
|
|
|
|
r.raise_for_status()
|
|
|
|
break
|
|
|
|
except Exception as Err:
|
|
|
|
logger.error(f'Attempt {i}: {Err}')
|
|
|
|
time.sleep(3)
|
2022-12-29 20:14:28 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch
|
|
|
|
def scan_remote_library(uuid):
|
|
|
|
'''Scan remote library'''
|
2023-02-05 23:01:53 +00:00
|
|
|
for i in range(attempts_for_federate):
|
|
|
|
try:
|
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/federation/libraries/{uuid}')
|
|
|
|
r.raise_for_status()
|
|
|
|
break
|
|
|
|
except Exception as Err:
|
|
|
|
logger.error(f'Attempt {i}: {Err}')
|
|
|
|
time.sleep(3)
|
2022-12-29 20:14:28 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-12-07 23:36:45 +00:00
|
|
|
@logger.catch
|
|
|
|
def record_track_in_history(track_id):
|
|
|
|
params = {
|
2022-12-18 01:02:53 +00:00
|
|
|
'track': int(track_id)
|
2022-12-07 23:36:45 +00:00
|
|
|
}
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/history/listenings', json=params)
|
2022-12-07 23:36:45 +00:00
|
|
|
r.raise_for_status()
|
|
|
|
return r.json
|
2022-12-18 01:02:53 +00:00
|
|
|
|
2022-11-09 01:01:02 +00:00
|
|
|
|
2022-11-08 19:23:19 +00:00
|
|
|
@logger.catch
|
|
|
|
def favorite_track(track_id):
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/favorites/tracks', json={'track': int(track_id)})
|
2022-11-08 19:23:19 +00:00
|
|
|
r.raise_for_status()
|
|
|
|
return r.json
|
|
|
|
|
|
|
|
|
|
|
|
@logger.catch
|
|
|
|
def unfavorite_track(track_id):
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/favorites/tracks/delete', json={'track': int(track_id)})
|
2022-11-08 19:23:19 +00:00
|
|
|
r.raise_for_status()
|
2022-12-18 01:02:53 +00:00
|
|
|
return r.json
|
2022-11-08 19:23:19 +00:00
|
|
|
|
|
|
|
|
|
|
|
@logger.catch
|
|
|
|
def hide_content(content):
|
|
|
|
'''This function hide content (write permission)'''
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/moderation/content-filters/', json=content)
|
2022-11-08 19:23:19 +00:00
|
|
|
r.raise_for_status()
|
|
|
|
return r.json
|
|
|
|
|
|
|
|
|
2022-11-01 10:15:28 +00:00
|
|
|
# [FunkWhale radios]
|
|
|
|
def get_radios():
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.get(
|
|
|
|
f'https://{current_instance.instance}/api/v1/radios/radios/')
|
2022-11-01 10:15:28 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
|
|
|
def post_radio_session(requested_radio):
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/radios/sessions/', json=requested_radio)
|
2022-11-01 10:15:28 +00:00
|
|
|
return r.json()
|
|
|
|
|
|
|
|
|
2022-11-09 18:51:20 +00:00
|
|
|
@logger.catch
|
2022-11-01 10:15:28 +00:00
|
|
|
def get_track_radio(radio_session):
|
2022-12-18 01:02:53 +00:00
|
|
|
r = current_instance.s.post(
|
|
|
|
f'https://{current_instance.instance}/api/v1/radios/tracks/', json=radio_session)
|
2022-11-09 18:51:20 +00:00
|
|
|
return r.json()
|