feat(scrobble): send Subsonic scrobble on playback start (now-playing)
This commit is contained in:
35
subsonic.py
35
subsonic.py
@@ -571,3 +571,38 @@ async def stream(stream_id: str):
|
||||
logger.error("Failed to stream song: %s", await response.text())
|
||||
return None
|
||||
return str(response.url)
|
||||
|
||||
async def scrobble(song_id: str, *, submission: bool=True, timestamp: int=None) -> bool:
|
||||
''' Submit a scrobble event for a song to the Subsonic/Navidrome API.
|
||||
|
||||
Parameters:
|
||||
- song_id: The Subsonic song id to scrobble
|
||||
- submission: Whether this is a final submission (True) or a now-playing ping (False)
|
||||
- timestamp: Optional Unix epoch seconds for when the song was played
|
||||
'''
|
||||
|
||||
scrobble_params: dict[str, any] = {
|
||||
"id": song_id,
|
||||
"submission": "true" if submission else "false",
|
||||
}
|
||||
if timestamp is not None:
|
||||
scrobble_params["time"] = str(timestamp)
|
||||
|
||||
params = SUBSONIC_REQUEST_PARAMS | scrobble_params
|
||||
|
||||
try:
|
||||
session = await get_session()
|
||||
async with await session.get(f"{env.SUBSONIC_SERVER}/rest/scrobble.view", params=params) as response:
|
||||
response.raise_for_status()
|
||||
data = await response.json()
|
||||
if await check_subsonic_error(data):
|
||||
logger.warning("Scrobble returned a Subsonic error for song %s", song_id)
|
||||
return False
|
||||
logger.debug("Scrobble response: %s", data)
|
||||
return True
|
||||
except aiohttp.ClientError as e:
|
||||
logger.error("HTTP error during scrobble for song %s: %s", song_id, e)
|
||||
return False
|
||||
except Exception as e:
|
||||
logger.error("Unexpected error during scrobble for song %s: %s", song_id, e)
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user