frontend.py 3.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import logging
  2. import time
  3. import json
  4. import pykka
  5. import requests
  6. from mopidy.core import CoreListener
  7. logger = logging.getLogger(__name__)
  8. class WebhooksFrontend(pykka.ThreadingActor, CoreListener):
  9. def __init__(self, config, core):
  10. super().__init__()
  11. self.config = config
  12. self.webhook_urls = []
  13. self.last_start_time = None
  14. def on_start(self):
  15. logger.info("Parsing webhook URLs and tokens")
  16. self.webhook_urls = self.config["webhooks"]["urls"].split(",")
  17. self.webhook_tokens = self.config["webhooks"]["tokens"].split(",")
  18. def _build_post_data(self, track) -> dict:
  19. primary_artist = track.artists[0]
  20. duration = track.length and track.length // 1000 or 0
  21. return {
  22. "name": track.name,
  23. "artist": primary_artist.name,
  24. "album": track.album,
  25. "track_number": track.track_no,
  26. "run_time_ticks": track.length,
  27. "run_time": str(duration),
  28. "musicbrainz_track_id": track.musicbrainz_id,
  29. "musicbrainz_album_id": track.album.musicbrainz_id
  30. if track.album
  31. else None,
  32. "musicbrainz_artist_id": track.artist.musicbrainz_id
  33. if primary_artist
  34. else None,
  35. }
  36. def _post_update_to_webhooks(self, post_data: dict, status: str):
  37. post_data["status"] = status
  38. for index, webhook_url in enumerate(self.webhook_urls):
  39. token = ""
  40. headers = {}
  41. try:
  42. token = self.webhook_tokens[index]
  43. except IndexError:
  44. logger.info(f"No token found for Webhook URL: {webhook_url}")
  45. if token:
  46. headers["Authorization"] = "Token {token}"
  47. response = requests.post(
  48. webhook_url, json=json.dumps(post_data), headers=headers
  49. )
  50. logger.info(response)
  51. def track_playback_started(self, tl_track):
  52. track = tl_track.track
  53. self.last_start_time = int(time.time())
  54. logger.debug(f"Now playing track: {track.artists[0]} - {track.name}")
  55. post_data = self._build_post_data(tl_track.track)
  56. # Build post data to send to urls
  57. if not self.webhook_urls:
  58. logger.info("No webhook URLS are configured ")
  59. return
  60. self._post_update_to_webhooks(post_data, "started")
  61. def track_playback_ended(self, tl_track, time_position):
  62. track = tl_track.track
  63. duration = track.length and track.length // 1000 or 0
  64. time_position = time_position // 1000
  65. logger.debug(f"Now playing track: {track.artists[0]} - {track.name}")
  66. post_data = self._build_post_data(tl_track.track)
  67. if time_position < duration // 2 and time_position < 240:
  68. logger.debug(
  69. "Track not played long enough to scrobble. (50% or 240s)"
  70. )
  71. return
  72. if self.last_start_time is None:
  73. self.last_start_time = int(time.time()) - duration
  74. logger.debug(
  75. f"Sending scroble to webhooks for track: {track.artists} - {track.name}"
  76. )
  77. self._post_update_to_webhooks(post_data, "stopped")