Varken/varken/structures.py
d-mcknight 7e03144365
Influxdb2 (#3)
* #203

* Update docker compose to specify influxdb:1.8.4

* Update requirements to use urllib3==1.26.5

* updated to support Radarr and Sonarr V3 Api

* bump requirements for requests

* Fix Sonarr & Radarr V3 API /queue endpoint (#220)

* Fix lint issues

* More lint fixes

* Update Sonarr structures

* Add Overseerr Support (#210)

* Remove duplicate structures

* update changelog to reflect v1.7.7 changes

* Add IP data to tautulli #202

* add missing ip address in tautulli

* Fixed: Streamlined API calls to Radarr and Sonarr (#221)

* Fixed: Sonarr Data pull issues (#222)

* Fix Sonarrr calendar

* Update lidarr structure (#225)

Added missing arguments to Lidarr structure

Fixes #223

* Clean up request totals. Upstream change sct/overseerr#2426

* Cleanup blank space

* Fix requested_date syntax.

* Fix requested_date for Overseerr tv and movie

* Fix overseerr config refernces

* Fix overseerr structures

* Update intparser to accommodate changes to config structure

* Cleanup overseerr data collection

* Fix SERVICES_ENABLED in varken.py to acomidate overseerr

* Fixed: Sonarr/Lidarr Queues (#227)

* Change sonarr queue structures to str

* Fixed: Multipage queue fetching

* Update historical tautulli import (#226)

* Fixed: Sonarr perams ordering

* Fixed: Proper warnings for missing data in sonarr and radarr

* Added: Overseerr ENVs to docker compose.

* Added: Logging to empty/no data returns

* Update Sonarr & Lidarr Structs to match latest API changes (#231)

* Add support for estimatedCompletionTime in LidarrQueue

* Add support for tvdbId in SonarrEpisode struct

* Fix typo in docker yml

* Rename example url for overseerr in docker yml

* Update radarr structures to inclue originalLanguage

* Update radarr structures to include addOptions

* Update radarr structures to include popularity

* fix(ombi): Update structures.py (#238)

* feat(docker): remove envs from example

* fix(logging): remove depreciation warning. Var for debug mode (#240)

* fix(build): bump schedule version to 1.1

* fix(build): bump docker python version

* fix(dep): update requests and urllib3

* fix(sonarr): ensure invalid sonarr queue items are just skipped over - fixes #239 (#243)

* add branch to build inputs

* update pipeline badge

* Update automation

* Add influxdb 2 client

* Add structure for influxdb 2 params

This contains all the data needed for connecting and writing to an InfluxDB2 server

* Parse influxdb 2 config data

* Add influxdb2 manager class

This stores the data needed for InfluxDB2, and has a single `write_points` function on this that takes an array of points to add to the database

* Use the correct db manager for varken

* Add influxdb2 to the example varken config file

* Create influx bucket if it doesn't exist

* Update InfluxDB type on README

* Clean up linting errors

* Wrap create bucket in try/catch

* Use bucket given in ini file

* Log exception to troubleshoot errors

* Allow configured influx2 address as URL (no port)

* Bypass validity check to troubleshoot

---------

Co-authored-by: mal5305 <malcolm.e.rogers@gmail.com>
Co-authored-by: samwiseg0 <2241731+samwiseg0@users.noreply.github.com>
Co-authored-by: Robin <19610103+RobinDadswell@users.noreply.github.com>
Co-authored-by: tigattack <10629864+tigattack@users.noreply.github.com>
Co-authored-by: Stewart Thomson <stewartthomson3@gmail.com>
Co-authored-by: Cameron Stephen <mail@cajs.co.uk>
Co-authored-by: MDHMatt <10845262+MDHMatt@users.noreply.github.com>
Co-authored-by: Nathan Adams <dinnerbone@dinnerbone.com>
Co-authored-by: Nicholas St. Germain <nick@cajun.pro>
Co-authored-by: Gabe Revells <gcrevell@mtu.edu>
2023-06-22 21:58:21 -07:00

659 lines
17 KiB
Python

from sys import version_info
from typing import NamedTuple
from logging import getLogger
logger = getLogger('temp')
# Check for python3.6 or newer to resolve erroneous typing.NamedTuple issues
if version_info < (3, 6, 2):
logger.error('Varken requires python3.6.2 or newer. You are on python%s.%s.%s - Exiting...',
version_info.major, version_info.minor, version_info.micro)
exit(1)
# Server Structures
class InfluxServer(NamedTuple):
password: str = 'root'
port: int = 8086
ssl: bool = False
url: str = 'localhost'
username: str = 'root'
verify_ssl: bool = False
class Influx2Server(NamedTuple):
url: str = 'localhost'
org: str = 'server'
token: str = 'TOKEN'
bucket: str = 'varken'
timeout: int = 10000
ssl: bool = False
verify_ssl: bool = False
class SonarrServer(NamedTuple):
api_key: str = None
future_days: int = 0
future_days_run_seconds: int = 30
id: int = None
missing_days: int = 0
missing_days_run_seconds: int = 30
queue: bool = False
queue_run_seconds: int = 30
url: str = None
verify_ssl: bool = False
class RadarrServer(NamedTuple):
api_key: str = None
get_missing: bool = False
get_missing_run_seconds: int = 30
id: int = None
queue: bool = False
queue_run_seconds: int = 30
url: str = None
verify_ssl: bool = False
class OmbiServer(NamedTuple):
api_key: str = None
id: int = None
issue_status_counts: bool = False
issue_status_run_seconds: int = 30
request_total_counts: bool = False
request_total_run_seconds: int = 30
request_type_counts: bool = False
request_type_run_seconds: int = 30
url: str = None
verify_ssl: bool = False
class OverseerrServer(NamedTuple):
api_key: str = None
id: int = None
url: str = None
verify_ssl: bool = False
get_request_total_counts: bool = False
request_total_run_seconds: int = 30
num_latest_requests_to_fetch: int = 10
num_latest_requests_seconds: int = 30
class TautulliServer(NamedTuple):
api_key: str = None
fallback_ip: str = None
get_activity: bool = False
get_activity_run_seconds: int = 30
get_stats: bool = False
get_stats_run_seconds: int = 30
id: int = None
url: str = None
verify_ssl: bool = None
maxmind_license_key: str = None
class SickChillServer(NamedTuple):
api_key: str = None
get_missing: bool = False
get_missing_run_seconds: int = 30
id: int = None
url: str = None
verify_ssl: bool = False
class UniFiServer(NamedTuple):
get_usg_stats_run_seconds: int = 30
id: int = None
password: str = 'ubnt'
site: str = None
url: str = 'unifi.domain.tld:8443'
username: str = 'ubnt'
usg_name: str = None
verify_ssl: bool = False
# Shared
class QueuePages(NamedTuple):
page: int = None
pageSize: int = None
sortKey: str = None
sortDirection: str = None
totalRecords: str = None
records: list = None
# Ombi Structures
class OmbiRequestCounts(NamedTuple):
approved: int = 0
available: int = 0
pending: int = 0
class OmbiIssuesCounts(NamedTuple):
inProgress: int = 0
pending: int = 0
resolved: int = 0
class OmbiTVRequest(NamedTuple):
background: str = None
childRequests: list = None
denied: bool = None
deniedReason: None = None
externalProviderId: str = None
id: int = None
imdbId: str = None
languageProfile: str = None
markedAsDenied: str = None
overview: str = None
posterPath: str = None
qualityOverride: None = None
releaseDate: str = None
rootFolder: None = None
status: str = None
title: str = None
totalSeasons: int = None
tvDbId: int = None
requestedByAlias: str = None
requestStatus: str = None
class OmbiMovieRequest(NamedTuple):
approved: bool = None
approved4K: bool = None
available: bool = None
available4K: bool = None
background: str = None
canApprove: bool = None
denied: bool = None
denied4K: None = None
deniedReason: None = None
deniedReason4K: None = None
digitalRelease: bool = None
digitalReleaseDate: None = None
has4KRequest: bool = None
id: int = None
imdbId: str = None
is4kRequest: bool = None
issueId: None = None
issues: None = None
langCode: str = None
languageCode: str = None
markedAsApproved: str = None
markedAsApproved4K: str = None
markedAsAvailable: None = None
markedAsAvailable4K: None = None
markedAsDenied: str = None
markedAsDenied4K: str = None
overview: str = None
posterPath: str = None
qualityOverride: int = None
released: bool = None
releaseDate: str = None
requestedByAlias: str = None
requestedDate: str = None
requestedDate4k: str = None
requestedUser: dict = None
requestedUserId: str = None
requestStatus: str = None
requestType: int = None
rootPathOverride: int = None
showSubscribe: bool = None
source: int = None
status: str = None
subscribed: bool = None
theMovieDbId: int = None
title: str = None
# Overseerr
class OverseerrRequestCounts(NamedTuple):
pending: int = None
approved: int = None
processing: int = None
available: int = None
total: int = None
movie: int = None
tv: int = None
declined: int = None
# 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
episodeFileId: int = None
episodeNumber: int = None
grabbed: bool = None
hasFile: bool = None
id: int = None
monitored: bool = None
overview: str = None
seasonNumber: int = None
seriesId: int = None
title: str = None
unverifiedSceneNumbering: bool = None
sceneAbsoluteEpisodeNumber: int = None
sceneEpisodeNumber: int = None
sceneSeasonNumber: int = None
series: SonarrTVShow = None
tvdbId: int = 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
errorMessage: str = None
outputPath: str = None
series: SonarrTVShow = None
episode: SonarrEpisode = None
timeleft: str = None
estimatedCompletionTime: str = None
# Radarr
class RadarrMovie(NamedTuple):
added: str = None
alternateTitles: list = None
certification: str = None
cleanTitle: str = None
collection: dict = None
digitalRelease: str = None
folderName: str = None
genres: list = None
hasFile: bool = None
id: int = None
images: list = None
imdbId: str = None
inCinemas: str = None
isAvailable: bool = None
minimumAvailability: str = None
monitored: bool = None
movieFile: dict = None
originalTitle: str = None
overview: str = None
path: str = None
physicalRelease: str = None
qualityProfileId: int = None
ratings: dict = None
runtime: int = None
secondaryYear: int = None
secondaryYearSourceId: int = None
sizeOnDisk: float = None
sortTitle: str = None
status: str = None
studio: str = None
tags: list = None
titleSlug: str = None
tmdbId: int = None
website: str = None
year: int = None
youTubeTrailerId: str = None
title: str = None
originalLanguage: str = None
addOptions: str = None
popularity: 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
timeleft: str = None
estimatedCompletionTime: str = None
errorMessage: str = None
outputPath: str = None
movie: RadarrMovie = None
timeleft: str = None
# Sickchill
class SickChillTVShow(NamedTuple):
airdate: str = None
airs: str = None
episode: int = None
ep_name: str = None
ep_plot: str = None
indexerid: int = None
network: str = None
paused: int = None
quality: str = None
season: int = None
show_name: str = None
show_status: str = None
tvdbid: int = None
weekday: int = None
# Tautulli
class TautulliStream(NamedTuple):
actors: list = None
added_at: str = None
allow_guest: int = None
art: str = None
aspect_ratio: str = None
audience_rating: str = None
audience_rating_image: str = None
audio_bitrate: str = None
audio_bitrate_mode: str = None
audio_channel_layout: str = None
audio_channels: str = None
audio_codec: str = None
audio_decision: str = None
audio_language: str = None
audio_language_code: str = None
audio_profile: str = None
audio_sample_rate: str = None
bandwidth: str = None
banner: str = None
bif_thumb: str = None
bitrate: str = None
channel_icon: str = None
channel_stream: int = None
channel_title: str = None
children_count: str = None
collections: list = None
container: str = None
content_rating: str = None
current_session: str = None
date: str = None
deleted_user: int = None
device: str = None
directors: list = None
do_notify: int = None
duration: str = None
email: str = None
extra_type: str = None
file: str = None
file_size: str = None
friendly_name: str = None
full_title: str = None
genres: list = None
grandparent_guid: str = None
grandparent_rating_key: str = None
grandparent_thumb: str = None
grandparent_title: str = None
group_count: int = None
group_ids: str = None
guid: str = None
height: str = None
id: str = None
indexes: int = None
ip_address: str = None
ip_address_public: str = None
is_admin: int = None
is_allow_sync: int = None
is_home_user: int = None
is_restricted: int = None
keep_history: int = None
labels: list = None
last_viewed_at: str = None
library_name: str = None
live: int = None
live_uuid: str = None
local: str = None
location: str = None
machine_id: str = None
media_index: str = None
media_type: str = None
optimized_version: int = None
optimized_version_profile: str = None
optimized_version_title: str = None
original_title: str = None
originally_available_at: str = None
parent_guid: str = None
parent_media_index: str = None
parent_rating_key: str = None
parent_thumb: str = None
parent_title: str = None
paused_counter: int = None
percent_complete: int = None
platform: str = None
platform_name: str = None
platform_version: str = None
player: str = None
pre_tautulli: str = None
product: str = None
product_version: str = None
profile: str = None
progress_percent: str = None
quality_profile: str = None
rating: str = None
rating_image: str = None
rating_key: str = None
reference_id: int = None
relay: int = None
relayed: int = None
row_id: int = None
section_id: str = None
secure: str = None
selected: int = None
session_id: str = None
session_key: str = None
shared_libraries: list = None
sort_title: str = None
started: int = None
state: str = None
stopped: int = None
stream_aspect_ratio: str = None
stream_audio_bitrate: str = None
stream_audio_bitrate_mode: str = None
stream_audio_channel_layout: str = None
stream_audio_channel_layout_: str = None
stream_audio_channels: str = None
stream_audio_codec: str = None
stream_audio_decision: str = None
stream_audio_language: str = None
stream_audio_language_code: str = None
stream_audio_sample_rate: str = None
stream_bitrate: str = None
stream_container: str = None
stream_container_decision: str = None
stream_duration: str = None
stream_subtitle_codec: str = None
stream_subtitle_container: str = None
stream_subtitle_decision: str = None
stream_subtitle_forced: int = None
stream_subtitle_format: str = None
stream_subtitle_language: str = None
stream_subtitle_language_code: str = None
stream_subtitle_location: str = None
stream_video_bit_depth: str = None
stream_video_bitrate: str = None
stream_video_codec: str = None
stream_video_codec_level: str = None
stream_video_decision: str = None
stream_video_dynamic_range: str = None
stream_video_framerate: str = None
stream_video_full_resolution: str = None
stream_video_height: str = None
stream_video_language: str = None
stream_video_language_code: str = None
stream_video_ref_frames: str = None
stream_video_resolution: str = None
stream_video_scan_type: str = None
stream_video_width: str = None
studio: str = None
sub_type: str = None
subtitle_codec: str = None
subtitle_container: str = None
subtitle_decision: str = None
subtitle_forced: int = None
subtitle_format: str = None
subtitle_language: str = None
subtitle_language_code: str = None
subtitle_location: str = None
subtitles: int = None
summary: str = None
synced_version: int = None
synced_version_profile: str = None
tagline: str = None
throttled: str = None
thumb: str = None
title: str = None
transcode_audio_channels: str = None
transcode_audio_codec: str = None
transcode_container: str = None
transcode_decision: str = None
transcode_height: str = None
transcode_hw_decode: str = None
transcode_hw_decode_title: str = None
transcode_hw_decoding: int = None
transcode_hw_encode: str = None
transcode_hw_encode_title: str = None
transcode_hw_encoding: int = None
transcode_hw_full_pipeline: int = None
transcode_hw_requested: int = None
transcode_key: str = None
transcode_progress: int = None
transcode_protocol: str = None
transcode_speed: str = None
transcode_throttled: int = None
transcode_video_codec: str = None
transcode_width: str = None
type: str = None
updated_at: str = None
user: str = None
user_id: int = None
user_rating: str = None
user_thumb: str = None
username: str = None
video_bit_depth: str = None
video_bitrate: str = None
video_codec: str = None
video_codec_level: str = None
video_decision: str = None
video_dynamic_range: str = None
video_frame_rate: str = None
video_framerate: str = None
video_full_resolution: str = None
video_height: str = None
video_language: str = None
video_language_code: str = None
video_profile: str = None
video_ref_frames: str = None
video_resolution: str = None
video_scan_type: str = None
video_width: str = None
view_offset: str = None
watched_status: int = None
width: str = None
writers: list = None
year: str = None
# Lidarr
class LidarrQueue(NamedTuple):
artistId: int = None
albumId: int = None
language: dict = None
quality: dict = None
size: float = None
title: str = None
timeleft: str = None
sizeleft: float = None
status: str = None
trackedDownloadStatus: str = None
trackedDownloadState: str = None
statusMessages: list = None
errorMessage: str = None
downloadId: str = None
protocol: str = None
downloadClient: str = None
indexer: str = None
outputPath: str = None
downloadForced: bool = None
id: int = None
estimatedCompletionTime: str = None
class LidarrAlbum(NamedTuple):
title: str = None
disambiguation: str = None
overview: str = None
artistId: int = None
foreignAlbumId: str = None
monitored: bool = None
anyReleaseOk: bool = None
profileId: int = None
duration: int = None
albumType: str = None
secondaryTypes: list = None
mediumCount: int = None
ratings: dict = None
releaseDate: str = None
releases: list = None
genres: list = None
media: list = None
artist: dict = None
images: list = None
links: list = None
statistics: dict = {}
id: int = None