123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135 |
- import logging
- import time
- import json
- from typing import Optional
- import pykka
- import requests
- from mopidy.core import CoreListener
- logger = logging.getLogger(__name__)
- class WebhooksFrontend(pykka.ThreadingActor, CoreListener):
- def __init__(self, config, core):
- super().__init__()
- self.config = config
- self.webhook_urls = []
- self.last_start_time = None
- def on_start(self):
- self.webhook_urls = self.config["webhooks"]["urls"].split(",")
- self.webhook_tokens = self.config["webhooks"]["tokens"].split(",")
- logger.info(f"Parsing webhook URLs and tokens: {self.webhook_urls}")
- def _build_post_data(self, track, time_position: Optional[int]=None) -> dict:
- artists = ", ".join(sorted([a.name for a in track.artists]))
- artists_list = [a for a in track.artists]
- try:
- musicbrainz_artist_id = artists_list[0].musicbrainz_id
- except IndexError:
- musicbrainz_artist_id = None
- duration = track.length and track.length // 1000 or 0
- album_name = ""
- if track.album:
- album_name = getattr(track.album, "name")
- return {
- "name": track.name,
- "artist": artists,
- "album": album_name,
- "track_number": track.track_no,
- "run_time_ticks": track.length,
- "run_time": str(duration),
- "playback_time_ticks": time_position,
- "musicbrainz_track_id": track.musicbrainz_id if track.album else "",
- "musicbrainz_album_id": track.album.musicbrainz_id if track.album else "",
- "musicbrainz_artist_id": musicbrainz_artist_id,
- "mopidy_uri": track.uri,
- }
- def _post_update_to_webhooks(self, post_data: dict, status: str):
- post_data["status"] = status
- for index, webhook_url in enumerate(self.webhook_urls):
- token = ""
- headers = {}
- try:
- token = self.webhook_tokens[index]
- except IndexError:
- logger.info(f"No token found for Webhook URL: {webhook_url}")
- if token:
- headers["Authorization"] = "Token f{token}"
- response = requests.post(
- webhook_url, json=json.dumps(post_data), headers=headers
- )
- logger.info(response)
- def track_playback_started(self, tl_track):
- track = tl_track.track
- artists = ", ".join(sorted([a.name for a in track.artists]))
- self.last_start_time = int(time.time())
- logger.debug(f"Now playing track: {artists} - {track.name}")
- post_data = self._build_post_data(tl_track.track, time_position=0)
- # Build post data to send to urls
- if not self.webhook_urls:
- logger.info("No webhook URLS are configured ")
- return
- logger.info(f"Scrobbling via webhooks: {artists} - {track.name}")
- self._post_update_to_webhooks(post_data, "started")
- def track_playback_ended(self, tl_track, time_position):
- track = tl_track.track
- artists = ", ".join(sorted([a.name for a in track.artists]))
- duration = track.length and track.length // 1000 or 0
- time_position_sec = time_position // 1000
- post_data = self._build_post_data(tl_track.track, time_position=time_position)
- if time_position_sec < duration // 2 and time_position_sec < 240:
- logger.debug(
- "Track not played long enough to scrobble. (50% or 240s)"
- )
- return
- if self.last_start_time is None:
- self.last_start_time = int(time.time()) - duration
- logger.info(
- f"Scrobbling finished via webhooks: {artists} - {track.name}"
- )
- self._post_update_to_webhooks(post_data, "stopped")
- def track_playback_paused(self, tl_track, time_position):
- track = tl_track.track
- artists = ", ".join(sorted([a.name for a in track.artists]))
- duration = track.length and track.length // 1000 or 0
- time_position_sec = time_position // 1000
- post_data = self._build_post_data(tl_track.track, time_position=time_position)
- if self.last_start_time is None:
- self.last_start_time = int(time.time()) - duration
- logger.info(
- f"Scrobbling paused via webhooks: {artists} - {track.name}"
- )
- self._post_update_to_webhooks(post_data, "paused")
- def track_playback_resumed(self, tl_track, time_position):
- track = tl_track.track
- artists = ", ".join(sorted([a.name for a in track.artists]))
- self.last_start_time = int(time.time())
- logger.debug(f"Now resuming track: {artists} - {track.name}")
- post_data = self._build_post_data(tl_track.track, time_position=time_position)
- # Build post data to send to urls
- if not self.webhook_urls:
- logger.info("No webhook URLS are configured ")
- return
- logger.info(f"Scrobbling via webhooks: {artists} - {track.name}")
- self._post_update_to_webhooks(post_data, "resumed")
|