frontend.py 3.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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. artists = ", ".join(sorted([a.name for a in track.artists]))
  20. artists_list = [a for a in track.artists]
  21. try:
  22. musicbrainz_artist_id = artists_list[0].musicbrainz_id
  23. except IndexError:
  24. musicbrainz_artist_id = None
  25. duration = track.length and track.length // 1000 or 0
  26. return {
  27. "name": track.name,
  28. "artist": artists,
  29. "album": track.album.name,
  30. "track_number": track.track_no,
  31. "run_time_ticks": track.length,
  32. "run_time": str(duration),
  33. "musicbrainz_track_id": track.musicbrainz_id,
  34. "musicbrainz_album_id": track.album.musicbrainz_id,
  35. "musicbrainz_artist_id": musicbrainz_artist_id,
  36. }
  37. def _post_update_to_webhooks(self, post_data: dict, status: str):
  38. post_data["status"] = status
  39. for index, webhook_url in enumerate(self.webhook_urls):
  40. token = ""
  41. headers = {}
  42. try:
  43. token = self.webhook_tokens[index]
  44. except IndexError:
  45. logger.info(f"No token found for Webhook URL: {webhook_url}")
  46. if token:
  47. headers["Authorization"] = "Token {token}"
  48. response = requests.post(
  49. webhook_url, json=json.dumps(post_data), headers=headers
  50. )
  51. logger.info(response)
  52. def track_playback_started(self, tl_track):
  53. track = tl_track.track
  54. artists = ", ".join(sorted([a.name for a in track.artists]))
  55. self.last_start_time = int(time.time())
  56. logger.debug(f"Now playing track: {artists} - {track.name}")
  57. post_data = self._build_post_data(tl_track.track)
  58. # Build post data to send to urls
  59. if not self.webhook_urls:
  60. logger.info("No webhook URLS are configured ")
  61. return
  62. logger.info(f"Scrobbling via webhooks: {artists} - {track.name}")
  63. self._post_update_to_webhooks(post_data, "started")
  64. def track_playback_ended(self, tl_track, time_position):
  65. track = tl_track.track
  66. artists = ", ".join(sorted([a.name for a in track.artists]))
  67. duration = track.length and track.length // 1000 or 0
  68. time_position = time_position // 1000
  69. post_data = self._build_post_data(tl_track.track)
  70. if time_position < duration // 2 and time_position < 240:
  71. logger.debug(
  72. "Track not played long enough to scrobble. (50% or 240s)"
  73. )
  74. return
  75. if self.last_start_time is None:
  76. self.last_start_time = int(time.time()) - duration
  77. logger.info(
  78. f"Scrobbling finished via webhooks: {artists} - {track.name}"
  79. )
  80. self._post_update_to_webhooks(post_data, "stopped")