updated to support Radarr and Sonarr V3 Api
This commit is contained in:
		
							parent
							
								
									c6b8dde29a
								
							
						
					
					
						commit
						57028cd26c
					
				
					 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 | ||||
|          | ||||
|         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) | ||||
|         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 queueItem in queueResponse: | ||||
|             try: | ||||
|             download_queue = [Queue(**movie) for movie in get] | ||||
|                 download_queue.append(RadarrQueue(**queueItem)) | ||||
|             except TypeError as e: | ||||
|             self.logger.error('TypeError has occurred : %s while creating Queue structure', 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 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -19,8 +19,32 @@ 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…
	
	Add table
		Add a link
		
	
		Reference in a new issue