bazarr/bazarr/signalr_client.py

154 lines
5.6 KiB
Python
Raw Normal View History

# coding=utf-8
import logging
import gevent
import threading
from requests import Session
from signalr import Connection
from requests.exceptions import ConnectionError
from signalrcore.hub_connection_builder import HubConnectionBuilder
from config import settings, url_sonarr, url_radarr
from get_episodes import sync_episodes, sync_one_episode
from get_series import update_series, update_one_series
from get_movies import update_movies, update_one_movie
from scheduler import scheduler
from utils import get_sonarr_version
class SonarrSignalrClient(threading.Thread):
def __init__(self):
super(SonarrSignalrClient, self).__init__()
self.stopped = True
self.apikey_sonarr = None
self.session = Session()
self.connection = None
def stop(self):
self.connection.close()
self.stopped = True
logging.info('BAZARR SignalR client for Sonarr is now disconnected.')
def restart(self):
if not self.stopped:
self.stop()
if settings.general.getboolean('use_sonarr'):
self.run()
def run(self):
if get_sonarr_version().startswith('2.'):
logging.warning('BAZARR can only sync from Sonarr v3 SignalR feed to get real-time update. You should '
'consider upgrading.')
return
self.apikey_sonarr = settings.sonarr.apikey
self.connection = Connection(url_sonarr() + "/signalr", self.session)
self.connection.qs = {'apikey': self.apikey_sonarr}
sonarr_hub = self.connection.register_hub('') # Sonarr doesn't use named hub
sonarr_method = ['series', 'episode']
for item in sonarr_method:
sonarr_hub.client.on(item, dispatcher)
while True:
if not self.stopped:
return
if self.connection.started:
gevent.sleep(5)
else:
try:
logging.debug('BAZARR connecting to Sonarr SignalR feed...')
self.connection.start()
except ConnectionError:
logging.error('BAZARR connection to Sonarr SignalR feed has been lost. Reconnecting...')
gevent.sleep(15)
else:
self.stopped = False
logging.info('BAZARR SignalR client for Sonarr is connected and waiting for events.')
scheduler.execute_job_now('update_series')
scheduler.execute_job_now('sync_episodes')
gevent.sleep()
class RadarrSignalrClient(threading.Thread):
def __init__(self):
super(RadarrSignalrClient, self).__init__()
self.stopped = True
self.apikey_radarr = None
self.connection = None
def stop(self):
self.connection.stop()
self.stopped = True
logging.info('BAZARR SignalR client for Radarr is now disconnected.')
def restart(self):
if not self.stopped:
self.stop()
if settings.general.getboolean('use_radarr'):
self.run()
def run(self):
self.apikey_radarr = settings.radarr.apikey
self.connection = HubConnectionBuilder() \
.with_url(url_radarr() + "/signalr/messages?access_token={}".format(self.apikey_radarr),
options={
"verify_ssl": False
}).build()
self.connection.on_open(lambda: logging.debug("BAZARR SignalR client for Radarr is connected."))
self.connection.on_close(lambda: logging.debug("BAZARR SignalR client for Radarr is disconnected."))
self.connection.on_error(lambda data: logging.debug(f"BAZARR SignalR client for Radarr: An exception was thrown"
f" closed{data.error}"))
self.connection.on("receiveMessage", dispatcher)
while True:
if not self.stopped:
return
if self.connection.transport.state.value == 4:
# 0: 'connecting', 1: 'connected', 2: 'reconnecting', 4: 'disconnected'
try:
logging.debug('BAZARR connecting to Radarr SignalR feed...')
self.connection.start()
except ConnectionError:
logging.error('BAZARR connection to Radarr SignalR feed has been lost. Reconnecting...')
gevent.sleep(15)
pass
else:
self.stopped = False
logging.info('BAZARR SignalR client for Radarr is connected and waiting for events.')
scheduler.execute_job_now('update_movies')
gevent.sleep()
else:
gevent.sleep(5)
def dispatcher(data):
topic = media_id = action = None
if isinstance(data, dict):
topic = data['name']
try:
media_id = data['body']['resource']['id']
action = data['body']['action']
except KeyError:
return
elif isinstance(data, list):
topic = data[0]['name']
try:
media_id = data[0]['body']['resource']['id']
action = data[0]['body']['action']
except KeyError:
return
if topic == 'series':
update_one_series(series_id=media_id, action=action)
elif topic == 'episode':
sync_one_episode(episode_id=media_id)
elif topic == 'movie':
update_one_movie(movie_id=media_id, action=action)
else:
return
sonarr_signalr_client = SonarrSignalrClient()
radarr_signalr_client = RadarrSignalrClient()