Merge pull request #214 from RobinDadswell/RadarrAndSonarrV3Api
This commit is contained in:
commit
e3f2ee967c
3 changed files with 198 additions and 70 deletions
|
@ -2,7 +2,7 @@ from logging import getLogger
|
|||
from requests import Session, Request
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from varken.structures import RadarrMovie, Queue
|
||||
from varken.structures import QueuePages, RadarrMovie, RadarrQueue
|
||||
from varken.helpers import hashit, connection_handler
|
||||
|
||||
|
||||
|
@ -18,8 +18,19 @@ class RadarrAPI(object):
|
|||
def __repr__(self):
|
||||
return f"<radarr-{self.server.id}>"
|
||||
|
||||
def get_movie(self,id):
|
||||
endpoint = '/api/v3/movie/'
|
||||
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint + str(id)))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
|
||||
if not get:
|
||||
return
|
||||
|
||||
return RadarrMovie(**get)
|
||||
|
||||
def get_missing(self):
|
||||
endpoint = '/api/movie'
|
||||
endpoint = '/api/v3/movie'
|
||||
now = datetime.now(timezone.utc).astimezone().isoformat()
|
||||
influx_payload = []
|
||||
missing = []
|
||||
|
@ -37,7 +48,7 @@ class RadarrAPI(object):
|
|||
return
|
||||
|
||||
for movie in movies:
|
||||
if movie.monitored and not movie.downloaded:
|
||||
if movie.monitored and not movie.hasFile:
|
||||
if movie.isAvailable:
|
||||
ma = 0
|
||||
else:
|
||||
|
@ -69,32 +80,45 @@ class RadarrAPI(object):
|
|||
self.dbmanager.write_points(influx_payload)
|
||||
|
||||
def get_queue(self):
|
||||
endpoint = '/api/queue'
|
||||
endpoint = '/api/v3/queue'
|
||||
now = datetime.now(timezone.utc).astimezone().isoformat()
|
||||
influx_payload = []
|
||||
pageSize = 250
|
||||
params = {'pageSize': pageSize}
|
||||
queueResponse = []
|
||||
queue = []
|
||||
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint))
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint,params=params))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
|
||||
if not get:
|
||||
return
|
||||
|
||||
response = QueuePages(**get)
|
||||
queueResponse.extend(response.records)
|
||||
|
||||
for movie in get:
|
||||
try:
|
||||
movie['movie'] = RadarrMovie(**movie['movie'])
|
||||
except TypeError as e:
|
||||
self.logger.error('TypeError has occurred : %s while creating RadarrMovie structure', e)
|
||||
while response.totalRecords > response.page * response.pageSize:
|
||||
page = response.page + 1
|
||||
params = {'pageSize': pageSize, 'page': page}
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint,params=params))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
if not get:
|
||||
return
|
||||
|
||||
try:
|
||||
download_queue = [Queue(**movie) for movie in get]
|
||||
except TypeError as e:
|
||||
self.logger.error('TypeError has occurred : %s while creating Queue structure', e)
|
||||
response = QueuePages(**get)
|
||||
queueResponse.extend(response.records)
|
||||
|
||||
download_queue = []
|
||||
for queueItem in queueResponse:
|
||||
try:
|
||||
download_queue.append(RadarrQueue(**queueItem))
|
||||
except TypeError as e:
|
||||
self.logger.error('TypeError has occurred : %s while creating RadarrQueue structure', e)
|
||||
return
|
||||
if not download_queue:
|
||||
return
|
||||
|
||||
for queue_item in download_queue:
|
||||
movie = queue_item.movie
|
||||
movie = self.get_movie(queue_item.movieId)
|
||||
|
||||
name = f'{movie.title} ({movie.year})'
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from logging import getLogger
|
|||
from requests import Session, Request
|
||||
from datetime import datetime, timezone, date, timedelta
|
||||
|
||||
from varken.structures import Queue, SonarrTVShow
|
||||
from varken.structures import SonarrEpisode, SonarrQueue, QueuePages, SonarrTVShow
|
||||
from varken.helpers import hashit, connection_handler
|
||||
|
||||
|
||||
|
@ -18,9 +18,33 @@ class SonarrAPI(object):
|
|||
|
||||
def __repr__(self):
|
||||
return f"<sonarr-{self.server.id}>"
|
||||
|
||||
def get_series(self, id):
|
||||
endpoint = '/api/v3/series/'
|
||||
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint + str(id)))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
|
||||
if not get:
|
||||
return
|
||||
|
||||
return SonarrTVShow(**get)
|
||||
|
||||
def get_episode(self, id):
|
||||
endpoint = '/api/v3/episode'
|
||||
params = {'episodeIds': id}
|
||||
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint,params = params))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
|
||||
if not get:
|
||||
return
|
||||
|
||||
return SonarrEpisode(**get[0])
|
||||
|
||||
|
||||
def get_calendar(self, query="Missing"):
|
||||
endpoint = '/api/calendar/'
|
||||
endpoint = '/api/v3/calendar/'
|
||||
today = str(date.today())
|
||||
last_days = str(date.today() - timedelta(days=self.server.missing_days))
|
||||
future = str(date.today() + timedelta(days=self.server.future_days))
|
||||
|
@ -42,22 +66,23 @@ class SonarrAPI(object):
|
|||
tv_shows = []
|
||||
for show in get:
|
||||
try:
|
||||
tv_shows.append(SonarrTVShow(**show))
|
||||
tv_shows.append(SonarrEpisode(**show))
|
||||
except TypeError as e:
|
||||
self.logger.error('TypeError has occurred : %s while creating SonarrTVShow structure for show. Data '
|
||||
self.logger.error('TypeError has occurred : %s while creating SonarrEpisode structure for show. Data '
|
||||
'attempted is: %s', e, show)
|
||||
|
||||
for show in tv_shows:
|
||||
sxe = f'S{show.seasonNumber:0>2}E{show.episodeNumber:0>2}'
|
||||
if show.hasFile:
|
||||
for episode in tv_shows:
|
||||
tvShow = self.get_series(episode.seriesId)
|
||||
sxe = f'S{episode.seasonNumber:0>2}E{episode.episodeNumber:0>2}'
|
||||
if episode.hasFile:
|
||||
downloaded = 1
|
||||
else:
|
||||
downloaded = 0
|
||||
if query == "Missing":
|
||||
if show.monitored and not downloaded:
|
||||
missing.append((show.series['title'], downloaded, sxe, show.title, show.airDateUtc, show.id))
|
||||
if episode.monitored and not downloaded:
|
||||
missing.append((tvShow.title, downloaded, sxe, episode.title, episode.airDateUtc, episode.seriesId))
|
||||
else:
|
||||
air_days.append((show.series['title'], downloaded, sxe, show.title, show.airDateUtc, show.id))
|
||||
air_days.append((tvShow.title, downloaded, sxe, episode.title, episode.airDateUtc, episode.seriesId))
|
||||
|
||||
for series_title, dl_status, sxe, episode_title, air_date_utc, sonarr_id in (air_days or missing):
|
||||
hash_id = hashit(f'{self.server.id}{series_title}{sxe}')
|
||||
|
@ -85,41 +110,59 @@ class SonarrAPI(object):
|
|||
|
||||
def get_queue(self):
|
||||
influx_payload = []
|
||||
endpoint = '/api/queue'
|
||||
endpoint = '/api/v3/queue'
|
||||
now = datetime.now(timezone.utc).astimezone().isoformat()
|
||||
pageSize = 250
|
||||
params = {'pageSize': pageSize}
|
||||
queueResponse = []
|
||||
queue = []
|
||||
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint))
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint,params=params))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
|
||||
if not get:
|
||||
return
|
||||
|
||||
response = QueuePages(**get)
|
||||
queueResponse.extend(response.records)
|
||||
|
||||
while response.totalRecords > response.page * response.pageSize:
|
||||
page = response.page + 1
|
||||
params = {'pageSize': pageSize, 'page': page}
|
||||
req = self.session.prepare_request(Request('GET', self.server.url + endpoint,params=params))
|
||||
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||
if not get:
|
||||
return
|
||||
|
||||
response = QueuePages(**get)
|
||||
queueResponse.extend(response.records)
|
||||
|
||||
download_queue = []
|
||||
for show in get:
|
||||
for queueItem in queueResponse:
|
||||
try:
|
||||
download_queue.append(Queue(**show))
|
||||
download_queue.append(SonarrQueue(**queueItem))
|
||||
except TypeError as e:
|
||||
self.logger.error('TypeError has occurred : %s while creating Queue structure. Data attempted is: '
|
||||
'%s', e, show)
|
||||
'%s', e, queueItem)
|
||||
if not download_queue:
|
||||
return
|
||||
|
||||
for show in download_queue:
|
||||
for queueItem in download_queue:
|
||||
tvShow = self.get_series(queueItem.seriesId)
|
||||
episode = self.get_episode(queueItem.episodeId)
|
||||
try:
|
||||
sxe = f"S{show.episode['seasonNumber']:0>2}E{show.episode['episodeNumber']:0>2}"
|
||||
sxe = f"S{episode.seasonNumber:0>2}E{episode.episodeNumber:0>2}"
|
||||
except TypeError as e:
|
||||
self.logger.error('TypeError has occurred : %s while processing the sonarr queue. \
|
||||
Remove invalid queue entry. Data attempted is: %s', e, show)
|
||||
Remove invalid queue entry. Data attempted is: %s', e, queueItem)
|
||||
continue
|
||||
|
||||
if show.protocol.upper() == 'USENET':
|
||||
if queueItem.protocol.upper() == 'USENET':
|
||||
protocol_id = 1
|
||||
else:
|
||||
protocol_id = 0
|
||||
|
||||
queue.append((show.series['title'], show.episode['title'], show.protocol.upper(),
|
||||
protocol_id, sxe, show.id, show.quality['quality']['name']))
|
||||
queue.append((tvShow.title, episode.title, queueItem.protocol.upper(),
|
||||
protocol_id, sxe, queueItem.seriesId, queueItem.quality['quality']['name']))
|
||||
|
||||
for series_title, episode_title, protocol, protocol_id, sxe, sonarr_id, quality in queue:
|
||||
hash_id = hashit(f'{self.server.id}{series_title}{sxe}')
|
||||
|
|
|
@ -91,22 +91,13 @@ class UniFiServer(NamedTuple):
|
|||
|
||||
|
||||
# Shared
|
||||
class Queue(NamedTuple):
|
||||
downloadId: str = None
|
||||
episode: dict = None
|
||||
estimatedCompletionTime: str = None
|
||||
id: int = None
|
||||
movie: dict = None
|
||||
protocol: str = None
|
||||
quality: dict = None
|
||||
series: dict = None
|
||||
size: float = None
|
||||
sizeleft: float = None
|
||||
status: str = None
|
||||
statusMessages: list = None
|
||||
timeleft: str = None
|
||||
title: str = None
|
||||
trackedDownloadStatus: str = None
|
||||
class QueuePages(NamedTuple):
|
||||
page: int = None
|
||||
pageSize: int = None
|
||||
sortKey: str = None
|
||||
sortDirection: str = None
|
||||
totalRecords: str = None
|
||||
records: list = None
|
||||
|
||||
|
||||
# Ombi Structures
|
||||
|
@ -184,35 +175,88 @@ class OmbiMovieRequest(NamedTuple):
|
|||
|
||||
# Sonarr
|
||||
class SonarrTVShow(NamedTuple):
|
||||
added: str = None
|
||||
airTime: str = None
|
||||
alternateTitles: list = None
|
||||
certification: str = None
|
||||
cleanTitle: str = None
|
||||
ended: bool = None
|
||||
firstAired: str = None
|
||||
genres: list = None
|
||||
id: int = None
|
||||
images: list = None
|
||||
imdbId: str = None
|
||||
languageProfileId: int = None
|
||||
monitored: bool = None
|
||||
nextAiring: str = None
|
||||
network: str = None
|
||||
overview: str = None
|
||||
path: str = None
|
||||
previousAiring: str = None
|
||||
qualityProfileId: int = None
|
||||
ratings: dict = None
|
||||
rootFolderPath: str = None
|
||||
runtime: int = None
|
||||
seasonFolder: bool = None
|
||||
seasons: list = None
|
||||
seriesType: str = None
|
||||
sortTitle: str = None
|
||||
statistics: dict = None
|
||||
status: str = None
|
||||
tags: list = None
|
||||
title: str = None
|
||||
titleSlug: str = None
|
||||
tvdbId: int = None
|
||||
tvMazeId: int = None
|
||||
tvRageId: int = None
|
||||
useSceneNumbering: bool = None
|
||||
year: int = None
|
||||
|
||||
|
||||
class SonarrEpisode(NamedTuple):
|
||||
absoluteEpisodeNumber: int = None
|
||||
airDate: str = None
|
||||
airDateUtc: str = None
|
||||
episodeFile: dict = None
|
||||
episodeFileId: int = None
|
||||
episodeNumber: int = None
|
||||
grabbed: bool = None
|
||||
hasFile: bool = None
|
||||
id: int = None
|
||||
lastSearchTime: str = None
|
||||
monitored: bool = None
|
||||
overview: str = None
|
||||
sceneAbsoluteEpisodeNumber: int = None
|
||||
sceneEpisodeNumber: int = None
|
||||
sceneSeasonNumber: int = None
|
||||
seasonNumber: int = None
|
||||
series: dict = None
|
||||
seriesId: int = None
|
||||
title: str = None
|
||||
unverifiedSceneNumbering: bool = None
|
||||
|
||||
|
||||
class SonarrQueue(NamedTuple):
|
||||
downloadClient: str = None
|
||||
downloadId: str = None
|
||||
episodeId: int = None
|
||||
id: int = None
|
||||
indexer: str = None
|
||||
language: dict = None
|
||||
protocol: str = None
|
||||
quality: dict = None
|
||||
size: float = None
|
||||
sizeleft: float = None
|
||||
status: str = None
|
||||
statusMessages: list = None
|
||||
title: str = None
|
||||
trackedDownloadState: str = None
|
||||
trackedDownloadStatus: str = None
|
||||
seriesId: int = None
|
||||
|
||||
|
||||
# Radarr
|
||||
class RadarrMovie(NamedTuple):
|
||||
added: str = None
|
||||
addOptions: str = None
|
||||
alternativeTitles: list = None
|
||||
alternateTitles: list = None
|
||||
certification: str = None
|
||||
cleanTitle: str = None
|
||||
downloaded: bool = None
|
||||
collection: dict = None
|
||||
digitalRelease: str = None
|
||||
folderName: str = None
|
||||
genres: list = None
|
||||
hasFile: bool = None
|
||||
|
@ -221,32 +265,49 @@ class RadarrMovie(NamedTuple):
|
|||
imdbId: str = None
|
||||
inCinemas: str = None
|
||||
isAvailable: bool = None
|
||||
lastInfoSync: str = None
|
||||
minimumAvailability: str = None
|
||||
monitored: bool = None
|
||||
movieFile: dict = None
|
||||
originalTitle: str = None
|
||||
overview: str = None
|
||||
path: str = None
|
||||
pathState: str = None
|
||||
physicalRelease: str = None
|
||||
physicalReleaseNote: str = None
|
||||
profileId: int = None
|
||||
qualityProfileId: int = None
|
||||
ratings: dict = None
|
||||
runtime: int = None
|
||||
secondaryYear: str = None
|
||||
secondaryYear: int = None
|
||||
secondaryYearSourceId: int = None
|
||||
sizeOnDisk: int = None
|
||||
sizeOnDisk: float = None
|
||||
sortTitle: str = None
|
||||
status: str = None
|
||||
studio: str = None
|
||||
tags: list = None
|
||||
title: str = None
|
||||
titleSlug: str = None
|
||||
tmdbId: int = None
|
||||
website: str = None
|
||||
year: int = None
|
||||
youTubeTrailerId: str = None
|
||||
title: str = None
|
||||
|
||||
|
||||
# Radarr Queue
|
||||
class RadarrQueue(NamedTuple):
|
||||
customFormats: list = None
|
||||
downloadClient: str = None
|
||||
downloadId: str = None
|
||||
id: int = None
|
||||
indexer: str = None
|
||||
languages: list = None
|
||||
movieId: int = None
|
||||
protocol: str = None
|
||||
quality: dict = None
|
||||
size: float = None
|
||||
sizeleft: float = None
|
||||
status: str = None
|
||||
statusMessages: list = None
|
||||
title: str = None
|
||||
trackedDownloadState: str = None
|
||||
trackedDownloadStatus: str = None
|
||||
|
||||
|
||||
# Sickchill
|
||||
|
|
Loading…
Reference in a new issue