v1.5 Merge
This commit is contained in:
commit
d9637aca73
12 changed files with 524 additions and 414 deletions
30
CHANGELOG.md
30
CHANGELOG.md
|
@ -1,6 +1,25 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## [v1.4](https://github.com/Boerderij/Varken/tree/v1.4) (2018-12-18)
|
## [v1.5](https://github.com/Boerderij/Varken/tree/v1.5) (2018-12-30)
|
||||||
|
[Full Changelog](https://github.com/Boerderij/Varken/compare/v1.4...v1.5)
|
||||||
|
|
||||||
|
**Implemented enhancements:**
|
||||||
|
|
||||||
|
- \[Feature Request\] Add issues from Ombi [\#70](https://github.com/Boerderij/Varken/issues/70)
|
||||||
|
- \[Feature Request\] Allow DNS Hostnames [\#66](https://github.com/Boerderij/Varken/issues/66)
|
||||||
|
- Replace static grafana configs with a Public Example [\#32](https://github.com/Boerderij/Varken/issues/32)
|
||||||
|
|
||||||
|
**Fixed bugs:**
|
||||||
|
|
||||||
|
- \[BUG\] unexpected keyword argument 'channel\_icon' [\#73](https://github.com/Boerderij/Varken/issues/73)
|
||||||
|
- \[BUG\] Unexpected keyword argument 'addOptions' [\#68](https://github.com/Boerderij/Varken/issues/68)
|
||||||
|
|
||||||
|
**Merged pull requests:**
|
||||||
|
|
||||||
|
- v1.5 Merge [\#75](https://github.com/Boerderij/Varken/pull/75) ([DirtyCajunRice](https://github.com/DirtyCajunRice))
|
||||||
|
- Add Ombi Issues [\#74](https://github.com/Boerderij/Varken/pull/74) ([anderssonoscar0](https://github.com/anderssonoscar0))
|
||||||
|
|
||||||
|
## [v1.4](https://github.com/Boerderij/Varken/tree/v1.4) (2018-12-19)
|
||||||
[Full Changelog](https://github.com/Boerderij/Varken/compare/v1.3-nightly...v1.4)
|
[Full Changelog](https://github.com/Boerderij/Varken/compare/v1.3-nightly...v1.4)
|
||||||
|
|
||||||
**Implemented enhancements:**
|
**Implemented enhancements:**
|
||||||
|
@ -92,10 +111,6 @@
|
||||||
## [v0.2-nightly](https://github.com/Boerderij/Varken/tree/v0.2-nightly) (2018-12-06)
|
## [v0.2-nightly](https://github.com/Boerderij/Varken/tree/v0.2-nightly) (2018-12-06)
|
||||||
[Full Changelog](https://github.com/Boerderij/Varken/compare/v0.1...v0.2-nightly)
|
[Full Changelog](https://github.com/Boerderij/Varken/compare/v0.1...v0.2-nightly)
|
||||||
|
|
||||||
**Implemented enhancements:**
|
|
||||||
|
|
||||||
- Tautulli - multiple server support? [\#25](https://github.com/Boerderij/Varken/issues/25)
|
|
||||||
|
|
||||||
**Closed issues:**
|
**Closed issues:**
|
||||||
|
|
||||||
- Create the DB if it does not exist. [\#38](https://github.com/Boerderij/Varken/issues/38)
|
- Create the DB if it does not exist. [\#38](https://github.com/Boerderij/Varken/issues/38)
|
||||||
|
@ -105,7 +120,12 @@
|
||||||
- use a config.ini instead of command-line flags [\#33](https://github.com/Boerderij/Varken/issues/33)
|
- use a config.ini instead of command-line flags [\#33](https://github.com/Boerderij/Varken/issues/33)
|
||||||
- Migrate crontab to python schedule package [\#31](https://github.com/Boerderij/Varken/issues/31)
|
- Migrate crontab to python schedule package [\#31](https://github.com/Boerderij/Varken/issues/31)
|
||||||
- Consolidate missing and missing\_days in sonarr.py [\#30](https://github.com/Boerderij/Varken/issues/30)
|
- Consolidate missing and missing\_days in sonarr.py [\#30](https://github.com/Boerderij/Varken/issues/30)
|
||||||
|
- Database Withou any scripts [\#29](https://github.com/Boerderij/Varken/issues/29)
|
||||||
|
- Grafana dashboard json doesn't match format of readme screenshot? [\#28](https://github.com/Boerderij/Varken/issues/28)
|
||||||
- Ombi something new \[Request\] [\#26](https://github.com/Boerderij/Varken/issues/26)
|
- Ombi something new \[Request\] [\#26](https://github.com/Boerderij/Varken/issues/26)
|
||||||
|
- Users Online not populating [\#24](https://github.com/Boerderij/Varken/issues/24)
|
||||||
|
- Missing dashboard [\#23](https://github.com/Boerderij/Varken/issues/23)
|
||||||
|
- Is there a Docker Image available for these scripts? [\#22](https://github.com/Boerderij/Varken/issues/22)
|
||||||
- Support for Linux without ASA [\#21](https://github.com/Boerderij/Varken/issues/21)
|
- Support for Linux without ASA [\#21](https://github.com/Boerderij/Varken/issues/21)
|
||||||
|
|
||||||
**Merged pull requests:**
|
**Merged pull requests:**
|
||||||
|
|
17
README.md
17
README.md
|
@ -10,14 +10,14 @@ from the Plex ecosystem into InfluxDB. Examples use Grafana for a
|
||||||
frontend
|
frontend
|
||||||
|
|
||||||
Requirements:
|
Requirements:
|
||||||
* Python3.6+
|
* Python3.6.7+
|
||||||
* Python3-pip
|
* Python3-pip
|
||||||
* [InfluxDB](https://www.influxdata.com/)
|
* [InfluxDB](https://www.influxdata.com/)
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
Example Dashboard
|
Example Dashboard
|
||||||
|
|
||||||
<img width="800" src="https://nickflix.io/sharex/firefox_NxdrqisVLF.png">
|
<img width="800" src="https://i.imgur.com/G5bnpjs.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
Supported Modules:
|
Supported Modules:
|
||||||
|
@ -104,8 +104,15 @@ named `varken`
|
||||||
|
|
||||||
### Grafana
|
### Grafana
|
||||||
[Grafana Installation Documentation](http://docs.grafana.org/installation/)
|
[Grafana Installation Documentation](http://docs.grafana.org/installation/)
|
||||||
|
[Official Example Dashboards](https://grafana.com/dashboards?search=Varken%20%5BOfficial%5D)
|
||||||
|
|
||||||
Grafana is used in our examples but not required, nor packaged as part of
|
Grafana is used in our examples but not required, nor packaged as part of
|
||||||
Varken. Panel example pictures are pinned in the grafana-panels channel of
|
Varken. Panel examples now exist in both nightly and tagged releases hosted
|
||||||
discord. Future releases may contain a json-generator, but it does not exist
|
on grafana.com (link above).
|
||||||
as varken stands today.
|
|
||||||
|
1. Use the link above, then click on your desired dashboard version
|
||||||
|
2. Click `Copy ID to Clipboard`
|
||||||
|
3. In grafana, click your dashboards menu dropdown, and then click `Import dashboard`
|
||||||
|
4. Paste the ID into the `Grafana.com Dashboard` field and then click into empty space on the screen. (This should change the screen to show `Importing Dashboard from Grafana.com`
|
||||||
|
5. Select your varken datasource name in the dropdown labeled `Varken`
|
||||||
|
6. Click Import!
|
|
@ -121,6 +121,8 @@ if __name__ == "__main__":
|
||||||
schedule.every(server.request_type_run_seconds).seconds.do(threaded, OMBI.get_request_counts)
|
schedule.every(server.request_type_run_seconds).seconds.do(threaded, OMBI.get_request_counts)
|
||||||
if server.request_total_counts:
|
if server.request_total_counts:
|
||||||
schedule.every(server.request_total_run_seconds).seconds.do(threaded, OMBI.get_all_requests)
|
schedule.every(server.request_total_run_seconds).seconds.do(threaded, OMBI.get_all_requests)
|
||||||
|
if server.issue_status_counts:
|
||||||
|
schedule.every(server.issue_status_run_seconds).seconds.do(threaded, OMBI.get_issue_counts)
|
||||||
|
|
||||||
if CONFIG.sickchill_enabled:
|
if CONFIG.sickchill_enabled:
|
||||||
for server in CONFIG.sickchill_servers:
|
for server in CONFIG.sickchill_servers:
|
||||||
|
|
|
@ -2,26 +2,28 @@
|
||||||
# - Sonarr + Radarr scripts support multiple servers. You can remove the second
|
# - Sonarr + Radarr scripts support multiple servers. You can remove the second
|
||||||
# server by putting a # in front of the lines and section name, and removing
|
# server by putting a # in front of the lines and section name, and removing
|
||||||
# that number from your server_ids list
|
# that number from your server_ids list
|
||||||
# - fallback_ip, This is used when there is no IP listed in tautulli.
|
# - fallback_ip, This is used when there is no IP listed in Tautulli.
|
||||||
# This can happen when you are streaming locally. This is usually your public IP.
|
# This can happen when you are streaming locally. Set this to your public IP.
|
||||||
|
# You do not need to change this value if your IP changes. This is only for
|
||||||
|
# location lookups when there is a failure.
|
||||||
|
|
||||||
[global]
|
[global]
|
||||||
sonarr_server_ids = 1,2
|
sonarr_server_ids = 1,2
|
||||||
radarr_server_ids = 1,2
|
radarr_server_ids = 1,2
|
||||||
tautulli_server_ids = 1
|
tautulli_server_ids = 1
|
||||||
ombi_server_ids = 1
|
ombi_server_ids = 1
|
||||||
ciscoasa_firewall_ids = false
|
ciscoasa_server_ids = false
|
||||||
sickchill_server_ids = false
|
sickchill_server_ids = false
|
||||||
|
|
||||||
[influxdb]
|
[influxdb]
|
||||||
url = influxdb.domain.tld
|
url = influxdb.domain.tld
|
||||||
port = 8086
|
port = 8086
|
||||||
username =
|
username = root
|
||||||
password =
|
password = root
|
||||||
|
|
||||||
[tautulli-1]
|
[tautulli-1]
|
||||||
url = tautulli.domain.tld:8181
|
url = tautulli.domain.tld:8181
|
||||||
fallback_ip = 0.0.0.0
|
fallback_ip = 1.1.1.1
|
||||||
apikey = xxxxxxxxxxxxxxxx
|
apikey = xxxxxxxxxxxxxxxx
|
||||||
ssl = false
|
ssl = false
|
||||||
verify_ssl = false
|
verify_ssl = false
|
||||||
|
@ -83,6 +85,8 @@ get_request_type_counts = true
|
||||||
request_type_run_seconds = 300
|
request_type_run_seconds = 300
|
||||||
get_request_total_counts = true
|
get_request_total_counts = true
|
||||||
request_total_run_seconds = 300
|
request_total_run_seconds = 300
|
||||||
|
get_issue_status_counts = true
|
||||||
|
issue_status_run_seconds = 300
|
||||||
|
|
||||||
[sickchill-1]
|
[sickchill-1]
|
||||||
url = sickchill.domain.tld:8081
|
url = sickchill.domain.tld:8081
|
||||||
|
@ -92,8 +96,6 @@ verify_ssl = false
|
||||||
get_missing = true
|
get_missing = true
|
||||||
get_missing_run_seconds = 300
|
get_missing_run_seconds = 300
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[ciscoasa-1]
|
[ciscoasa-1]
|
||||||
url = firewall.domain.tld
|
url = firewall.domain.tld
|
||||||
username = cisco
|
username = cisco
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
VERSION = 1.4
|
VERSION = 1.5
|
||||||
BRANCH = 'master'
|
BRANCH = 'master'
|
||||||
|
|
|
@ -27,17 +27,20 @@ class GeoIPHandler(object):
|
||||||
|
|
||||||
def lookup(self, ipaddress):
|
def lookup(self, ipaddress):
|
||||||
ip = ipaddress
|
ip = ipaddress
|
||||||
self.logger.debug('Getting lat/long for Tautulli stream')
|
self.logger.debug('Getting lat/long for Tautulli stream using ip with last octet ending in %s',
|
||||||
|
ip.split('.')[-1:])
|
||||||
return self.reader.city(ip)
|
return self.reader.city(ip)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
today = date.today()
|
today = date.today()
|
||||||
dbdate = None
|
|
||||||
try:
|
try:
|
||||||
dbdate = date.fromtimestamp(stat(self.dbfile).st_ctime)
|
dbdate = date.fromtimestamp(stat(self.dbfile).st_ctime)
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
self.logger.error("Could not find GeoLite2 DB as: %s", self.dbfile)
|
self.logger.error("Could not find GeoLite2 DB as: %s", self.dbfile)
|
||||||
self.download()
|
self.download()
|
||||||
|
dbdate = date.fromtimestamp(stat(self.dbfile).st_ctime)
|
||||||
|
|
||||||
first_wednesday_day = [week[2:3][0] for week in monthcalendar(today.year, today.month) if week[2:3][0] != 0][0]
|
first_wednesday_day = [week[2:3][0] for week in monthcalendar(today.year, today.month) if week[2:3][0] != 0][0]
|
||||||
first_wednesday_date = date(today.year, today.month, first_wednesday_day)
|
first_wednesday_date = date(today.year, today.month, first_wednesday_day)
|
||||||
|
|
||||||
|
@ -52,7 +55,6 @@ class GeoIPHandler(object):
|
||||||
else:
|
else:
|
||||||
self.logger.debug('Geolite2 DB will update in %s days', abs(td.days))
|
self.logger.debug('Geolite2 DB will update in %s days', abs(td.days))
|
||||||
|
|
||||||
|
|
||||||
def download(self):
|
def download(self):
|
||||||
tar_dbfile = abspath(join(self.data_folder, 'GeoLite2-City.tar.gz'))
|
tar_dbfile = abspath(join(self.data_folder, 'GeoLite2-City.tar.gz'))
|
||||||
url = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz'
|
url = 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz'
|
||||||
|
|
|
@ -59,15 +59,17 @@ class INIParser(object):
|
||||||
self.logger.error('Config file missing (varken.ini) in %s', self.data_folder)
|
self.logger.error('Config file missing (varken.ini) in %s', self.data_folder)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
def url_check(self, url=None, include_port=True):
|
def url_check(self, url=None, include_port=True, section=None):
|
||||||
url_check = url
|
url_check = url
|
||||||
|
module = section
|
||||||
inc_port = include_port
|
inc_port = include_port
|
||||||
|
|
||||||
search = (r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' # domain...
|
search = (r'(?:([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,}|' # domain...
|
||||||
r'localhost|' # localhost...
|
r'localhost|' # localhost...
|
||||||
|
r'^[a-zA-Z0-9_-]*|' # hostname only. My soul dies a little every time this is used...
|
||||||
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
|
||||||
)
|
)
|
||||||
|
# Include search for port if it is needed.
|
||||||
if inc_port:
|
if inc_port:
|
||||||
search = (search + r'(?::\d+)?' + r'(?:/?|[/?]\S+)$')
|
search = (search + r'(?::\d+)?' + r'(?:/?|[/?]\S+)$')
|
||||||
else:
|
else:
|
||||||
|
@ -78,28 +80,28 @@ class INIParser(object):
|
||||||
valid = match(regex, url_check) is not None
|
valid = match(regex, url_check) is not None
|
||||||
if not valid:
|
if not valid:
|
||||||
if inc_port:
|
if inc_port:
|
||||||
self.logger.error('%s is invalid! URL must host/IP and port if not 80 or 443. ie. localhost:8080',
|
self.logger.error('%s is invalid in module [%s]! URL must host/IP and '
|
||||||
url_check)
|
'port if not 80 or 443. ie. localhost:8080',
|
||||||
|
url_check, module)
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
self.logger.error('%s is invalid! URL must host/IP. ie. localhost', url_check)
|
self.logger.error('%s is invalid in module [%s]! URL must host/IP. ie. localhost', url_check, module)
|
||||||
exit(1)
|
exit(1)
|
||||||
else:
|
else:
|
||||||
self.logger.debug('%s is a valid URL in the config.', url_check)
|
self.logger.debug('%s is a valid URL in module [%s].', url_check, module)
|
||||||
return url_check
|
return url_check
|
||||||
|
|
||||||
def parse_opts(self):
|
def parse_opts(self):
|
||||||
self.read_file()
|
self.read_file()
|
||||||
# Parse InfluxDB options
|
# Parse InfluxDB options
|
||||||
url = self.url_check(self.config.get('influxdb', 'url'), include_port=False)
|
url = self.url_check(self.config.get('influxdb', 'url'), include_port=False, section='influxdb')
|
||||||
|
|
||||||
port = self.config.getint('influxdb', 'port')
|
port = self.config.getint('influxdb', 'port')
|
||||||
|
|
||||||
username = self.config.get('influxdb', 'username')
|
username = self.config.get('influxdb', 'username')
|
||||||
|
|
||||||
password = self.config.get('influxdb', 'password')
|
password = self.config.get('influxdb', 'password')
|
||||||
|
self.influx_server = InfluxServer(url=url, port=port, username=username, password=password)
|
||||||
self.influx_server = InfluxServer(url, port, username, password)
|
|
||||||
|
|
||||||
# Check for all enabled services
|
# Check for all enabled services
|
||||||
for service in self.services:
|
for service in self.services:
|
||||||
|
@ -111,7 +113,7 @@ class INIParser(object):
|
||||||
server = None
|
server = None
|
||||||
section = f"{service}-{server_id}"
|
section = f"{service}-{server_id}"
|
||||||
try:
|
try:
|
||||||
url = self.url_check(self.config.get(section, 'url'))
|
url = self.url_check(self.config.get(section, 'url'), section=section)
|
||||||
|
|
||||||
apikey = None
|
apikey = None
|
||||||
if service != 'ciscoasa':
|
if service != 'ciscoasa':
|
||||||
|
@ -137,9 +139,11 @@ class INIParser(object):
|
||||||
|
|
||||||
queue_run_seconds = self.config.getint(section, 'queue_run_seconds')
|
queue_run_seconds = self.config.getint(section, 'queue_run_seconds')
|
||||||
|
|
||||||
server = SonarrServer(server_id, scheme + url, apikey, verify_ssl, missing_days,
|
server = SonarrServer(id=server_id, url=scheme + url, api_key=apikey, verify_ssl=verify_ssl,
|
||||||
missing_days_run_seconds, future_days, future_days_run_seconds,
|
missing_days=missing_days, future_days=future_days,
|
||||||
queue, queue_run_seconds)
|
missing_days_run_seconds=missing_days_run_seconds,
|
||||||
|
future_days_run_seconds=future_days_run_seconds,
|
||||||
|
queue=queue, queue_run_seconds=queue_run_seconds)
|
||||||
|
|
||||||
if service == 'radarr':
|
if service == 'radarr':
|
||||||
queue = self.config.getboolean(section, 'queue')
|
queue = self.config.getboolean(section, 'queue')
|
||||||
|
@ -150,8 +154,9 @@ class INIParser(object):
|
||||||
|
|
||||||
get_missing_run_seconds = self.config.getint(section, 'get_missing_run_seconds')
|
get_missing_run_seconds = self.config.getint(section, 'get_missing_run_seconds')
|
||||||
|
|
||||||
server = RadarrServer(server_id, scheme + url, apikey, verify_ssl, queue, queue_run_seconds,
|
server = RadarrServer(id=server_id, url=scheme + url, api_key=apikey, verify_ssl=verify_ssl,
|
||||||
get_missing, get_missing_run_seconds)
|
queue_run_seconds=queue_run_seconds, get_missing=get_missing,
|
||||||
|
queue=queue, get_missing_run_seconds=get_missing_run_seconds)
|
||||||
|
|
||||||
if service == 'tautulli':
|
if service == 'tautulli':
|
||||||
fallback_ip = self.config.get(section, 'fallback_ip')
|
fallback_ip = self.config.get(section, 'fallback_ip')
|
||||||
|
@ -164,9 +169,11 @@ class INIParser(object):
|
||||||
|
|
||||||
get_stats_run_seconds = self.config.getint(section, 'get_stats_run_seconds')
|
get_stats_run_seconds = self.config.getint(section, 'get_stats_run_seconds')
|
||||||
|
|
||||||
server = TautulliServer(server_id, scheme + url, fallback_ip, apikey, verify_ssl,
|
server = TautulliServer(id=server_id, url=scheme + url, api_key=apikey,
|
||||||
get_activity, get_activity_run_seconds, get_stats,
|
verify_ssl=verify_ssl, get_activity=get_activity,
|
||||||
get_stats_run_seconds)
|
fallback_ip=fallback_ip, get_stats=get_stats,
|
||||||
|
get_activity_run_seconds=get_activity_run_seconds,
|
||||||
|
get_stats_run_seconds=get_stats_run_seconds)
|
||||||
|
|
||||||
if service == 'ombi':
|
if service == 'ombi':
|
||||||
request_type_counts = self.config.getboolean(section, 'get_request_type_counts')
|
request_type_counts = self.config.getboolean(section, 'get_request_type_counts')
|
||||||
|
@ -177,17 +184,26 @@ class INIParser(object):
|
||||||
|
|
||||||
request_total_run_seconds = self.config.getint(section, 'request_total_run_seconds')
|
request_total_run_seconds = self.config.getint(section, 'request_total_run_seconds')
|
||||||
|
|
||||||
server = OmbiServer(server_id, scheme + url, apikey, verify_ssl, request_type_counts,
|
issue_status_counts = self.config.getboolean(section, 'get_issue_status_counts')
|
||||||
request_type_run_seconds, request_total_counts,
|
|
||||||
request_total_run_seconds)
|
issue_status_run_seconds = self.config.getint(section, 'issue_status_run_seconds')
|
||||||
|
|
||||||
|
server = OmbiServer(id=server_id, url=scheme + url, api_key=apikey, verify_ssl=verify_ssl,
|
||||||
|
request_type_counts=request_type_counts,
|
||||||
|
request_type_run_seconds=request_type_run_seconds,
|
||||||
|
request_total_counts=request_total_counts,
|
||||||
|
request_total_run_seconds=request_total_run_seconds,
|
||||||
|
issue_status_counts=issue_status_counts,
|
||||||
|
issue_status_run_seconds=issue_status_run_seconds)
|
||||||
|
|
||||||
if service == 'sickchill':
|
if service == 'sickchill':
|
||||||
get_missing = self.config.getboolean(section, 'get_missing')
|
get_missing = self.config.getboolean(section, 'get_missing')
|
||||||
|
|
||||||
get_missing_run_seconds = self.config.getint(section, 'get_missing_run_seconds')
|
get_missing_run_seconds = self.config.getint(section, 'get_missing_run_seconds')
|
||||||
|
|
||||||
server = SickChillServer(server_id, scheme + url, apikey, verify_ssl,
|
server = SickChillServer(id=server_id, url=scheme + url, api_key=apikey,
|
||||||
get_missing, get_missing_run_seconds)
|
verify_ssl=verify_ssl, get_missing=get_missing,
|
||||||
|
get_missing_run_seconds=get_missing_run_seconds)
|
||||||
|
|
||||||
if service == 'ciscoasa':
|
if service == 'ciscoasa':
|
||||||
username = self.config.get(section, 'username')
|
username = self.config.get(section, 'username')
|
||||||
|
@ -198,8 +214,10 @@ class INIParser(object):
|
||||||
|
|
||||||
get_bandwidth_run_seconds = self.config.getint(section, 'get_bandwidth_run_seconds')
|
get_bandwidth_run_seconds = self.config.getint(section, 'get_bandwidth_run_seconds')
|
||||||
|
|
||||||
server = CiscoASAFirewall(server_id, scheme + url, username, password, outside_interface,
|
server = CiscoASAFirewall(id=server_id, url=scheme + url, verify_ssl=verify_ssl,
|
||||||
verify_ssl, get_bandwidth_run_seconds)
|
username=username, password=password,
|
||||||
|
outside_interface=outside_interface,
|
||||||
|
get_bandwidth_run_seconds=get_bandwidth_run_seconds)
|
||||||
|
|
||||||
getattr(self, f'{service}_servers').append(server)
|
getattr(self, f'{service}_servers').append(server)
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ from requests import Session, Request
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from varken.helpers import connection_handler, hashit
|
from varken.helpers import connection_handler, hashit
|
||||||
from varken.structures import OmbiRequestCounts, OmbiMovieRequest, OmbiTVRequest
|
from varken.structures import OmbiRequestCounts, OmbiIssuesCounts, OmbiMovieRequest, OmbiTVRequest
|
||||||
|
|
||||||
|
|
||||||
class OmbiAPI(object):
|
class OmbiAPI(object):
|
||||||
|
@ -65,14 +65,17 @@ class OmbiAPI(object):
|
||||||
# Request Type: Movie = 1, TV Show = 0
|
# Request Type: Movie = 1, TV Show = 0
|
||||||
for movie in movie_requests:
|
for movie in movie_requests:
|
||||||
hash_id = hashit(f'{movie.id}{movie.theMovieDbId}{movie.title}')
|
hash_id = hashit(f'{movie.id}{movie.theMovieDbId}{movie.title}')
|
||||||
status = None
|
|
||||||
# Denied = 0, Approved = 1, Completed = 2, Pending = 3
|
# Denied = 0, Approved = 1, Completed = 2, Pending = 3
|
||||||
if movie.denied:
|
if movie.denied:
|
||||||
status = 0
|
status = 0
|
||||||
|
|
||||||
elif movie.approved and movie.available:
|
elif movie.approved and movie.available:
|
||||||
status = 2
|
status = 2
|
||||||
|
|
||||||
elif movie.approved:
|
elif movie.approved:
|
||||||
status = 1
|
status = 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
status = 3
|
status = 3
|
||||||
|
|
||||||
|
@ -101,10 +104,13 @@ class OmbiAPI(object):
|
||||||
# Denied = 0, Approved = 1, Completed = 2, Pending = 3
|
# Denied = 0, Approved = 1, Completed = 2, Pending = 3
|
||||||
if show.childRequests[0]['denied']:
|
if show.childRequests[0]['denied']:
|
||||||
status = 0
|
status = 0
|
||||||
|
|
||||||
elif show.childRequests[0]['approved'] and show.childRequests[0]['available']:
|
elif show.childRequests[0]['approved'] and show.childRequests[0]['available']:
|
||||||
status = 2
|
status = 2
|
||||||
|
|
||||||
elif show.childRequests[0]['approved']:
|
elif show.childRequests[0]['approved']:
|
||||||
status = 1
|
status = 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
status = 3
|
status = 3
|
||||||
|
|
||||||
|
@ -156,3 +162,31 @@ class OmbiAPI(object):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.dbmanager.write_points(influx_payload)
|
self.dbmanager.write_points(influx_payload)
|
||||||
|
|
||||||
|
def get_issue_counts(self):
|
||||||
|
now = datetime.now(timezone.utc).astimezone().isoformat()
|
||||||
|
endpoint = '/api/v1/Issues/count'
|
||||||
|
|
||||||
|
req = self.session.prepare_request(Request('GET', self.server.url + endpoint))
|
||||||
|
get = connection_handler(self.session, req, self.server.verify_ssl)
|
||||||
|
|
||||||
|
if not get:
|
||||||
|
return
|
||||||
|
|
||||||
|
requests = OmbiIssuesCounts(**get)
|
||||||
|
influx_payload = [
|
||||||
|
{
|
||||||
|
"measurement": "Ombi",
|
||||||
|
"tags": {
|
||||||
|
"type": "Issues_Counts"
|
||||||
|
},
|
||||||
|
"time": now,
|
||||||
|
"fields": {
|
||||||
|
"pending": requests.pending,
|
||||||
|
"in_progress": requests.inProgress,
|
||||||
|
"resolved": requests.resolved
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
self.dbmanager.write_points(influx_payload)
|
||||||
|
|
|
@ -2,7 +2,7 @@ from logging import getLogger
|
||||||
from requests import Session, Request
|
from requests import Session, Request
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
|
|
||||||
from varken.structures import Movie, Queue
|
from varken.structures import RadarrMovie, Queue
|
||||||
from varken.helpers import hashit, connection_handler
|
from varken.helpers import hashit, connection_handler
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,9 +31,9 @@ class RadarrAPI(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
movies = [Movie(**movie) for movie in get]
|
movies = [RadarrMovie(**movie) for movie in get]
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
self.logger.error('TypeError has occurred : %s while creating Movie structure', e)
|
self.logger.error('TypeError has occurred : %s while creating RadarrMovie structure', e)
|
||||||
return
|
return
|
||||||
|
|
||||||
for movie in movies:
|
for movie in movies:
|
||||||
|
@ -82,9 +82,9 @@ class RadarrAPI(object):
|
||||||
|
|
||||||
for movie in get:
|
for movie in get:
|
||||||
try:
|
try:
|
||||||
movie['movie'] = Movie(**movie['movie'])
|
movie['movie'] = RadarrMovie(**movie['movie'])
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
self.logger.error('TypeError has occurred : %s while creating Movie structure', e)
|
self.logger.error('TypeError has occurred : %s while creating RadarrMovie structure', e)
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -2,7 +2,7 @@ from logging import getLogger
|
||||||
from requests import Session, Request
|
from requests import Session, Request
|
||||||
from datetime import datetime, timezone, date, timedelta
|
from datetime import datetime, timezone, date, timedelta
|
||||||
|
|
||||||
from varken.structures import Queue, TVShow
|
from varken.structures import Queue, SonarrTVShow
|
||||||
from varken.helpers import hashit, connection_handler
|
from varken.helpers import hashit, connection_handler
|
||||||
|
|
||||||
|
|
||||||
|
@ -34,11 +34,11 @@ class SonarrAPI(object):
|
||||||
if not get:
|
if not get:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Iteratively create a list of TVShow Objects from response json
|
# Iteratively create a list of SonarrTVShow Objects from response json
|
||||||
try:
|
try:
|
||||||
tv_shows = [TVShow(**show) for show in get]
|
tv_shows = [SonarrTVShow(**show) for show in get]
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
self.logger.error('TypeError has occurred : %s while creating TVShow structure', e)
|
self.logger.error('TypeError has occurred : %s while creating SonarrTVShow structure', e)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Add show to missing list if file does not exist
|
# Add show to missing list if file does not exist
|
||||||
|
@ -87,9 +87,9 @@ class SonarrAPI(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
tv_shows = [TVShow(**show) for show in get]
|
tv_shows = [SonarrTVShow(**show) for show in get]
|
||||||
except TypeError as e:
|
except TypeError as e:
|
||||||
self.logger.error('TypeError has occurred : %s while creating TVShow structure', e)
|
self.logger.error('TypeError has occurred : %s while creating SonarrTVShow structure', e)
|
||||||
return
|
return
|
||||||
|
|
||||||
for show in tv_shows:
|
for show in tv_shows:
|
||||||
|
@ -150,9 +150,9 @@ class SonarrAPI(object):
|
||||||
protocol_id = 0
|
protocol_id = 0
|
||||||
|
|
||||||
queue.append((show.series['title'], show.episode['title'], show.protocol.upper(),
|
queue.append((show.series['title'], show.episode['title'], show.protocol.upper(),
|
||||||
protocol_id, sxe, show.id))
|
protocol_id, sxe, show.id, show.quality['quality']['name']))
|
||||||
|
|
||||||
for series_title, episode_title, protocol, protocol_id, sxe, sonarr_id in queue:
|
for series_title, episode_title, protocol, protocol_id, sxe, sonarr_id, quality in queue:
|
||||||
hash_id = hashit(f'{self.server.id}{series_title}{sxe}')
|
hash_id = hashit(f'{self.server.id}{series_title}{sxe}')
|
||||||
influx_payload.append(
|
influx_payload.append(
|
||||||
{
|
{
|
||||||
|
@ -165,7 +165,8 @@ class SonarrAPI(object):
|
||||||
"epname": episode_title,
|
"epname": episode_title,
|
||||||
"sxe": sxe,
|
"sxe": sxe,
|
||||||
"protocol": protocol,
|
"protocol": protocol,
|
||||||
"protocol_id": protocol_id
|
"protocol_id": protocol_id,
|
||||||
|
"quality": quality
|
||||||
},
|
},
|
||||||
"time": now,
|
"time": now,
|
||||||
"fields": {
|
"fields": {
|
||||||
|
@ -173,5 +174,4 @@ class SonarrAPI(object):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
self.dbmanager.write_points(influx_payload)
|
self.dbmanager.write_points(influx_payload)
|
||||||
|
|
|
@ -4,418 +4,246 @@ from logging import getLogger
|
||||||
|
|
||||||
logger = getLogger('temp')
|
logger = getLogger('temp')
|
||||||
# Check for python3.6 or newer to resolve erroneous typing.NamedTuple issues
|
# Check for python3.6 or newer to resolve erroneous typing.NamedTuple issues
|
||||||
if version_info < (3, 6):
|
if version_info < (3, 6, 2):
|
||||||
logger.error('Varken requires python3.6 or newer. You are on python%s.%s - Exiting...',
|
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.major, version_info.minor, version_info.micro)
|
||||||
exit(1)
|
exit(1)
|
||||||
|
|
||||||
|
|
||||||
class Queue(NamedTuple):
|
# Server Structures
|
||||||
movie: dict = None
|
class InfluxServer(NamedTuple):
|
||||||
series: dict = None
|
password: str = 'root'
|
||||||
episode: dict = None
|
port: int = 8086
|
||||||
quality: dict = None
|
url: str = 'localhost'
|
||||||
size: float = None
|
username: str = 'root'
|
||||||
title: str = None
|
|
||||||
sizeleft: float = None
|
|
||||||
timeleft: str = None
|
|
||||||
estimatedCompletionTime: str = None
|
|
||||||
status: str = None
|
|
||||||
trackedDownloadStatus: str = None
|
|
||||||
statusMessages: list = None
|
|
||||||
downloadId: str = None
|
|
||||||
protocol: str = None
|
|
||||||
id: int = None
|
|
||||||
|
|
||||||
|
|
||||||
class SonarrServer(NamedTuple):
|
class SonarrServer(NamedTuple):
|
||||||
id: int = None
|
|
||||||
url: str = None
|
|
||||||
api_key: str = None
|
api_key: str = None
|
||||||
verify_ssl: bool = False
|
|
||||||
missing_days: int = 0
|
|
||||||
missing_days_run_seconds: int = 30
|
|
||||||
future_days: int = 0
|
future_days: int = 0
|
||||||
future_days_run_seconds: int = 30
|
future_days_run_seconds: int = 30
|
||||||
|
id: int = None
|
||||||
|
missing_days: int = 0
|
||||||
|
missing_days_run_seconds: int = 30
|
||||||
queue: bool = False
|
queue: bool = False
|
||||||
queue_run_seconds: int = 30
|
queue_run_seconds: int = 30
|
||||||
|
url: str = None
|
||||||
|
verify_ssl: bool = False
|
||||||
|
|
||||||
|
|
||||||
class RadarrServer(NamedTuple):
|
class RadarrServer(NamedTuple):
|
||||||
id: int = None
|
|
||||||
url: str = None
|
|
||||||
api_key: str = None
|
api_key: str = None
|
||||||
verify_ssl: bool = False
|
|
||||||
queue: bool = False
|
|
||||||
queue_run_seconds: int = 30
|
|
||||||
get_missing: bool = False
|
get_missing: bool = False
|
||||||
get_missing_run_seconds: int = 30
|
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):
|
class OmbiServer(NamedTuple):
|
||||||
id: int = None
|
|
||||||
url: str = None
|
|
||||||
api_key: str = None
|
api_key: str = None
|
||||||
verify_ssl: bool = False
|
id: int = None
|
||||||
request_type_counts: bool = False
|
issue_status_counts: bool = False
|
||||||
request_type_run_seconds: int = 30
|
issue_status_run_seconds: int = 30
|
||||||
request_total_counts: bool = False
|
request_total_counts: bool = False
|
||||||
request_total_run_seconds: int = 30
|
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 TautulliServer(NamedTuple):
|
class TautulliServer(NamedTuple):
|
||||||
id: int = None
|
|
||||||
url: str = None
|
|
||||||
fallback_ip: str = None
|
|
||||||
api_key: str = None
|
api_key: str = None
|
||||||
verify_ssl: bool = None
|
fallback_ip: str = None
|
||||||
get_activity: bool = False
|
get_activity: bool = False
|
||||||
get_activity_run_seconds: int = 30
|
get_activity_run_seconds: int = 30
|
||||||
get_stats: bool = False
|
get_stats: bool = False
|
||||||
get_stats_run_seconds: int = 30
|
get_stats_run_seconds: int = 30
|
||||||
|
id: int = None
|
||||||
|
url: str = None
|
||||||
class InfluxServer(NamedTuple):
|
verify_ssl: bool = None
|
||||||
url: str = 'localhost'
|
|
||||||
port: int = 8086
|
|
||||||
username: str = 'root'
|
|
||||||
password: str = 'root'
|
|
||||||
|
|
||||||
|
|
||||||
class SickChillServer(NamedTuple):
|
class SickChillServer(NamedTuple):
|
||||||
id: int = None
|
|
||||||
url: str = None
|
|
||||||
api_key: str = None
|
api_key: str = None
|
||||||
verify_ssl: bool = False
|
|
||||||
get_missing: bool = False
|
get_missing: bool = False
|
||||||
get_missing_run_seconds: int = 30
|
get_missing_run_seconds: int = 30
|
||||||
|
id: int = None
|
||||||
|
url: str = None
|
||||||
|
verify_ssl: bool = False
|
||||||
|
|
||||||
|
|
||||||
class CiscoASAFirewall(NamedTuple):
|
class CiscoASAFirewall(NamedTuple):
|
||||||
|
get_bandwidth_run_seconds: int = 30
|
||||||
id: int = None
|
id: int = None
|
||||||
|
outside_interface: str = None
|
||||||
|
password: str = 'cisco'
|
||||||
url: str = '192.168.1.1'
|
url: str = '192.168.1.1'
|
||||||
username: str = 'cisco'
|
username: str = 'cisco'
|
||||||
password: str = 'cisco'
|
|
||||||
outside_interface: str = None
|
|
||||||
verify_ssl: bool = False
|
verify_ssl: bool = False
|
||||||
get_bandwidth_run_seconds: int = 30
|
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
# Ombi Structures
|
||||||
class OmbiRequestCounts(NamedTuple):
|
class OmbiRequestCounts(NamedTuple):
|
||||||
pending: int = 0
|
|
||||||
approved: int = 0
|
approved: int = 0
|
||||||
available: int = 0
|
available: int = 0
|
||||||
|
pending: int = 0
|
||||||
|
|
||||||
|
|
||||||
class TautulliStream(NamedTuple):
|
class OmbiIssuesCounts(NamedTuple):
|
||||||
rating: str = None
|
inProgress: int = 0
|
||||||
transcode_width: str = None
|
pending: int = 0
|
||||||
labels: list = None
|
resolved: int = 0
|
||||||
stream_bitrate: str = None
|
|
||||||
bandwidth: str = None
|
|
||||||
optimized_version: int = None
|
|
||||||
video_language: str = None
|
|
||||||
parent_rating_key: str = None
|
|
||||||
rating_key: str = None
|
|
||||||
platform_version: str = None
|
|
||||||
transcode_hw_decoding: int = None
|
|
||||||
thumb: str = None
|
|
||||||
title: str = None
|
|
||||||
video_codec_level: str = None
|
|
||||||
tagline: str = None
|
|
||||||
last_viewed_at: str = None
|
|
||||||
audio_sample_rate: str = None
|
|
||||||
user_rating: str = None
|
|
||||||
platform: str = None
|
|
||||||
collections: list = None
|
|
||||||
location: str = None
|
|
||||||
transcode_container: str = None
|
|
||||||
audio_channel_layout: str = None
|
|
||||||
local: str = None
|
|
||||||
stream_subtitle_format: str = None
|
|
||||||
stream_video_ref_frames: str = None
|
|
||||||
transcode_hw_encode_title: str = None
|
|
||||||
stream_container_decision: str = None
|
|
||||||
audience_rating: str = None
|
|
||||||
full_title: str = None
|
|
||||||
ip_address: str = None
|
|
||||||
subtitles: int = None
|
|
||||||
stream_subtitle_language: str = None
|
|
||||||
channel_stream: int = None
|
|
||||||
video_bitrate: str = None
|
|
||||||
is_allow_sync: int = None
|
|
||||||
stream_video_bitrate: str = None
|
|
||||||
summary: str = None
|
|
||||||
stream_audio_decision: str = None
|
|
||||||
aspect_ratio: str = None
|
|
||||||
audio_bitrate_mode: str = None
|
|
||||||
transcode_hw_decode_title: str = None
|
|
||||||
stream_audio_channel_layout: str = None
|
|
||||||
deleted_user: int = None
|
|
||||||
library_name: str = None
|
|
||||||
art: str = None
|
|
||||||
stream_video_resolution: str = None
|
|
||||||
video_profile: str = None
|
|
||||||
sort_title: str = None
|
|
||||||
stream_video_codec_level: str = None
|
|
||||||
stream_video_height: str = None
|
|
||||||
year: str = None
|
|
||||||
stream_duration: str = None
|
|
||||||
stream_audio_channels: str = None
|
|
||||||
video_language_code: str = None
|
|
||||||
transcode_key: str = None
|
|
||||||
transcode_throttled: int = None
|
|
||||||
container: str = None
|
|
||||||
stream_audio_bitrate: str = None
|
|
||||||
user: str = None
|
|
||||||
selected: int = None
|
|
||||||
product_version: str = None
|
|
||||||
subtitle_location: str = None
|
|
||||||
transcode_hw_requested: int = None
|
|
||||||
video_height: str = None
|
|
||||||
state: str = None
|
|
||||||
is_restricted: int = None
|
|
||||||
email: str = None
|
|
||||||
stream_container: str = None
|
|
||||||
transcode_speed: str = None
|
|
||||||
video_bit_depth: str = None
|
|
||||||
stream_audio_sample_rate: str = None
|
|
||||||
grandparent_title: str = None
|
|
||||||
studio: str = None
|
|
||||||
transcode_decision: str = None
|
|
||||||
video_width: str = None
|
|
||||||
bitrate: str = None
|
|
||||||
machine_id: str = None
|
|
||||||
originally_available_at: str = None
|
|
||||||
video_frame_rate: str = None
|
|
||||||
synced_version_profile: str = None
|
|
||||||
friendly_name: str = None
|
|
||||||
audio_profile: str = None
|
|
||||||
optimized_version_title: str = None
|
|
||||||
platform_name: str = None
|
|
||||||
stream_video_language: str = None
|
|
||||||
keep_history: int = None
|
|
||||||
stream_audio_codec: str = None
|
|
||||||
stream_video_codec: str = None
|
|
||||||
grandparent_thumb: str = None
|
|
||||||
synced_version: int = None
|
|
||||||
transcode_hw_decode: str = None
|
|
||||||
user_thumb: str = None
|
|
||||||
stream_video_width: str = None
|
|
||||||
height: str = None
|
|
||||||
stream_subtitle_decision: str = None
|
|
||||||
audio_codec: str = None
|
|
||||||
parent_title: str = None
|
|
||||||
guid: str = None
|
|
||||||
audio_language_code: str = None
|
|
||||||
transcode_video_codec: str = None
|
|
||||||
transcode_audio_codec: str = None
|
|
||||||
stream_video_decision: str = None
|
|
||||||
user_id: int = None
|
|
||||||
transcode_height: str = None
|
|
||||||
transcode_hw_full_pipeline: int = None
|
|
||||||
throttled: str = None
|
|
||||||
quality_profile: str = None
|
|
||||||
width: str = None
|
|
||||||
live: int = None
|
|
||||||
stream_subtitle_forced: int = None
|
|
||||||
media_type: str = None
|
|
||||||
video_resolution: str = None
|
|
||||||
stream_subtitle_location: str = None
|
|
||||||
do_notify: int = None
|
|
||||||
video_ref_frames: str = None
|
|
||||||
stream_subtitle_language_code: str = None
|
|
||||||
audio_channels: str = None
|
|
||||||
stream_audio_language_code: str = None
|
|
||||||
optimized_version_profile: str = None
|
|
||||||
relay: int = None
|
|
||||||
duration: str = None
|
|
||||||
rating_image: str = None
|
|
||||||
is_home_user: int = None
|
|
||||||
is_admin: int = None
|
|
||||||
ip_address_public: str = None
|
|
||||||
allow_guest: int = None
|
|
||||||
transcode_audio_channels: str = None
|
|
||||||
stream_audio_channel_layout_: str = None
|
|
||||||
media_index: str = None
|
|
||||||
stream_video_framerate: str = None
|
|
||||||
transcode_hw_encode: str = None
|
|
||||||
grandparent_rating_key: str = None
|
|
||||||
original_title: str = None
|
|
||||||
added_at: str = None
|
|
||||||
banner: str = None
|
|
||||||
bif_thumb: str = None
|
|
||||||
parent_media_index: str = None
|
|
||||||
live_uuid: str = None
|
|
||||||
audio_language: str = None
|
|
||||||
stream_audio_bitrate_mode: str = None
|
|
||||||
username: str = None
|
|
||||||
subtitle_decision: str = None
|
|
||||||
children_count: str = None
|
|
||||||
updated_at: str = None
|
|
||||||
player: str = None
|
|
||||||
subtitle_format: str = None
|
|
||||||
file: str = None
|
|
||||||
file_size: str = None
|
|
||||||
session_key: str = None
|
|
||||||
id: str = None
|
|
||||||
subtitle_container: str = None
|
|
||||||
genres: list = None
|
|
||||||
stream_video_language_code: str = None
|
|
||||||
indexes: int = None
|
|
||||||
video_decision: str = None
|
|
||||||
stream_audio_language: str = None
|
|
||||||
writers: list = None
|
|
||||||
actors: list = None
|
|
||||||
progress_percent: str = None
|
|
||||||
audio_decision: str = None
|
|
||||||
subtitle_forced: int = None
|
|
||||||
profile: str = None
|
|
||||||
product: str = None
|
|
||||||
view_offset: str = None
|
|
||||||
type: str = None
|
|
||||||
audience_rating_image: str = None
|
|
||||||
audio_bitrate: str = None
|
|
||||||
section_id: str = None
|
|
||||||
stream_subtitle_codec: str = None
|
|
||||||
subtitle_codec: str = None
|
|
||||||
video_codec: str = None
|
|
||||||
device: str = None
|
|
||||||
stream_video_bit_depth: str = None
|
|
||||||
video_framerate: str = None
|
|
||||||
transcode_hw_encoding: int = None
|
|
||||||
transcode_protocol: str = None
|
|
||||||
shared_libraries: list = None
|
|
||||||
stream_aspect_ratio: str = None
|
|
||||||
content_rating: str = None
|
|
||||||
session_id: str = None
|
|
||||||
directors: list = None
|
|
||||||
parent_thumb: str = None
|
|
||||||
subtitle_language_code: str = None
|
|
||||||
transcode_progress: int = None
|
|
||||||
subtitle_language: str = None
|
|
||||||
stream_subtitle_container: str = None
|
|
||||||
sub_type: str = None
|
|
||||||
extra_type: str = None
|
|
||||||
|
|
||||||
|
|
||||||
class TVShow(NamedTuple):
|
|
||||||
seriesId: int = None
|
|
||||||
episodeFileId: int = None
|
|
||||||
seasonNumber: int = None
|
|
||||||
episodeNumber: int = None
|
|
||||||
title: str = None
|
|
||||||
airDate: str = None
|
|
||||||
airDateUtc: str = None
|
|
||||||
overview: str = None
|
|
||||||
episodeFile: dict = None
|
|
||||||
hasFile: bool = None
|
|
||||||
monitored: bool = None
|
|
||||||
unverifiedSceneNumbering: bool = None
|
|
||||||
absoluteEpisodeNumber: int = None
|
|
||||||
sceneAbsoluteEpisodeNumber: int = None
|
|
||||||
sceneEpisodeNumber: int = None
|
|
||||||
sceneSeasonNumber: int = None
|
|
||||||
series: dict = None
|
|
||||||
id: int = None
|
|
||||||
|
|
||||||
|
|
||||||
class Movie(NamedTuple):
|
|
||||||
title: str = None
|
|
||||||
alternativeTitles: list = None
|
|
||||||
secondaryYearSourceId: int = None
|
|
||||||
sortTitle: str = None
|
|
||||||
sizeOnDisk: int = None
|
|
||||||
status: str = None
|
|
||||||
overview: str = None
|
|
||||||
inCinemas: str = None
|
|
||||||
images: list = None
|
|
||||||
downloaded: bool = None
|
|
||||||
year: int = None
|
|
||||||
secondaryYear: str = None
|
|
||||||
hasFile: bool = None
|
|
||||||
youTubeTrailerId: str = None
|
|
||||||
studio: str = None
|
|
||||||
path: str = None
|
|
||||||
profileId: int = None
|
|
||||||
pathState: str = None
|
|
||||||
monitored: bool = None
|
|
||||||
minimumAvailability: str = None
|
|
||||||
isAvailable: bool = None
|
|
||||||
folderName: str = None
|
|
||||||
runtime: int = None
|
|
||||||
lastInfoSync: str = None
|
|
||||||
cleanTitle: str = None
|
|
||||||
imdbId: str = None
|
|
||||||
tmdbId: int = None
|
|
||||||
titleSlug: str = None
|
|
||||||
genres: list = None
|
|
||||||
tags: list = None
|
|
||||||
added: str = None
|
|
||||||
ratings: dict = None
|
|
||||||
movieFile: dict = None
|
|
||||||
qualityProfileId: int = None
|
|
||||||
physicalRelease: str = None
|
|
||||||
physicalReleaseNote: str = None
|
|
||||||
website: str = None
|
|
||||||
id: int = None
|
|
||||||
|
|
||||||
|
|
||||||
class OmbiMovieRequest(NamedTuple):
|
|
||||||
theMovieDbId: int = None
|
|
||||||
issueId: None = None
|
|
||||||
issues: None = None
|
|
||||||
subscribed: bool = None
|
|
||||||
showSubscribe: bool = None
|
|
||||||
rootPathOverride: int = None
|
|
||||||
qualityOverride: int = None
|
|
||||||
imdbId: str = None
|
|
||||||
overview: str = None
|
|
||||||
posterPath: str = None
|
|
||||||
releaseDate: str = None
|
|
||||||
digitalReleaseDate: None = None
|
|
||||||
status: str = None
|
|
||||||
background: str = None
|
|
||||||
released: bool = None
|
|
||||||
digitalRelease: bool = None
|
|
||||||
title: str = None
|
|
||||||
approved: bool = None
|
|
||||||
markedAsApproved: str = None
|
|
||||||
requestedDate: str = None
|
|
||||||
available: bool = None
|
|
||||||
markedAsAvailable: None = None
|
|
||||||
requestedUserId: str = None
|
|
||||||
denied: bool = None
|
|
||||||
markedAsDenied: str = None
|
|
||||||
deniedReason: None = None
|
|
||||||
requestType: int = None
|
|
||||||
requestedUser: dict = None
|
|
||||||
canApprove: bool = None
|
|
||||||
id: int = None
|
|
||||||
|
|
||||||
|
|
||||||
class OmbiTVRequest(NamedTuple):
|
class OmbiTVRequest(NamedTuple):
|
||||||
tvDbId: int = None
|
|
||||||
imdbId: str = None
|
|
||||||
qualityOverride: None = None
|
|
||||||
rootFolder: None = None
|
|
||||||
overview: str = None
|
|
||||||
title: str = None
|
|
||||||
posterPath: str = None
|
|
||||||
background: str = None
|
background: str = None
|
||||||
releaseDate: str = None
|
|
||||||
status: str = None
|
|
||||||
totalSeasons: int = None
|
|
||||||
childRequests: list = None
|
childRequests: list = None
|
||||||
|
denied: bool = None
|
||||||
|
deniedReason: None = None
|
||||||
id: int = None
|
id: int = None
|
||||||
|
imdbId: 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
|
||||||
|
|
||||||
|
|
||||||
|
class OmbiMovieRequest(NamedTuple):
|
||||||
|
approved: bool = None
|
||||||
|
available: bool = None
|
||||||
|
background: str = None
|
||||||
|
canApprove: bool = None
|
||||||
|
denied: bool = None
|
||||||
|
deniedReason: None = None
|
||||||
|
digitalRelease: bool = None
|
||||||
|
digitalReleaseDate: None = None
|
||||||
|
id: int = None
|
||||||
|
imdbId: str = None
|
||||||
|
issueId: None = None
|
||||||
|
issues: None = None
|
||||||
|
markedAsApproved: str = None
|
||||||
|
markedAsAvailable: None = None
|
||||||
|
markedAsDenied: str = None
|
||||||
|
overview: str = None
|
||||||
|
posterPath: str = None
|
||||||
|
qualityOverride: int = None
|
||||||
|
released: bool = None
|
||||||
|
releaseDate: str = None
|
||||||
|
requestedDate: str = None
|
||||||
|
requestedUser: dict = None
|
||||||
|
requestedUserId: str = None
|
||||||
|
requestType: int = None
|
||||||
|
rootPathOverride: int = None
|
||||||
|
showSubscribe: bool = None
|
||||||
|
status: str = None
|
||||||
|
subscribed: bool = None
|
||||||
|
theMovieDbId: int = None
|
||||||
|
title: str = None
|
||||||
|
|
||||||
|
|
||||||
|
# Sonarr
|
||||||
|
class SonarrTVShow(NamedTuple):
|
||||||
|
absoluteEpisodeNumber: int = None
|
||||||
|
airDate: str = None
|
||||||
|
airDateUtc: str = None
|
||||||
|
episodeFile: dict = None
|
||||||
|
episodeFileId: int = None
|
||||||
|
episodeNumber: int = 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
|
||||||
|
|
||||||
|
|
||||||
|
# Radarr
|
||||||
|
class RadarrMovie(NamedTuple):
|
||||||
|
added: str = None
|
||||||
|
addOptions: str = None
|
||||||
|
alternativeTitles: list = None
|
||||||
|
certification: str = None
|
||||||
|
cleanTitle: str = None
|
||||||
|
downloaded: bool = 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
|
||||||
|
lastInfoSync: str = None
|
||||||
|
minimumAvailability: str = None
|
||||||
|
monitored: bool = None
|
||||||
|
movieFile: dict = 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
|
||||||
|
secondaryYearSourceId: int = None
|
||||||
|
sizeOnDisk: int = 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
|
||||||
|
|
||||||
|
|
||||||
|
# Sickchill
|
||||||
class SickChillTVShow(NamedTuple):
|
class SickChillTVShow(NamedTuple):
|
||||||
airdate: str = None
|
airdate: str = None
|
||||||
airs: str = None
|
airs: str = None
|
||||||
|
episode: int = None
|
||||||
ep_name: str = None
|
ep_name: str = None
|
||||||
ep_plot: str = None
|
ep_plot: str = None
|
||||||
episode: int = None
|
|
||||||
indexerid: int = None
|
indexerid: int = None
|
||||||
network: str = None
|
network: str = None
|
||||||
paused: int = None
|
paused: int = None
|
||||||
|
@ -425,3 +253,198 @@ class SickChillTVShow(NamedTuple):
|
||||||
show_status: str = None
|
show_status: str = None
|
||||||
tvdbid: int = None
|
tvdbid: int = None
|
||||||
weekday: 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_channels: str = None
|
||||||
|
audio_channel_layout: 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
|
||||||
|
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_rating_key: str = None
|
||||||
|
grandparent_thumb: str = None
|
||||||
|
grandparent_title: 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
|
||||||
|
originally_available_at: str = None
|
||||||
|
original_title: str = None
|
||||||
|
parent_media_index: str = None
|
||||||
|
parent_rating_key: str = None
|
||||||
|
parent_thumb: str = None
|
||||||
|
parent_title: str = None
|
||||||
|
platform: str = None
|
||||||
|
platform_name: str = None
|
||||||
|
platform_version: str = None
|
||||||
|
player: 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
|
||||||
|
relay: int = None
|
||||||
|
section_id: str = None
|
||||||
|
selected: int = None
|
||||||
|
session_id: str = None
|
||||||
|
session_key: str = None
|
||||||
|
shared_libraries: list = None
|
||||||
|
sort_title: str = None
|
||||||
|
state: str = None
|
||||||
|
stream_aspect_ratio: str = None
|
||||||
|
stream_audio_bitrate: str = None
|
||||||
|
stream_audio_bitrate_mode: str = None
|
||||||
|
stream_audio_channels: str = None
|
||||||
|
stream_audio_channel_layout: str = None
|
||||||
|
stream_audio_channel_layout_: 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_bitrate: str = None
|
||||||
|
stream_video_bit_depth: str = None
|
||||||
|
stream_video_codec: str = None
|
||||||
|
stream_video_codec_level: str = None
|
||||||
|
stream_video_decision: str = None
|
||||||
|
stream_video_framerate: 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_width: str = None
|
||||||
|
studio: str = None
|
||||||
|
subtitles: int = 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
|
||||||
|
sub_type: str = 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
|
||||||
|
username: str = None
|
||||||
|
user_id: int = None
|
||||||
|
user_rating: str = None
|
||||||
|
user_thumb: str = None
|
||||||
|
video_bitrate: str = None
|
||||||
|
video_bit_depth: str = None
|
||||||
|
video_codec: str = None
|
||||||
|
video_codec_level: str = None
|
||||||
|
video_decision: str = None
|
||||||
|
video_framerate: str = None
|
||||||
|
video_frame_rate: 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_width: str = None
|
||||||
|
view_offset: str = None
|
||||||
|
width: str = None
|
||||||
|
writers: list = None
|
||||||
|
year: str = None
|
||||||
|
|
|
@ -108,6 +108,8 @@ class TautulliAPI(object):
|
||||||
"quality": quality,
|
"quality": quality,
|
||||||
"video_decision": video_decision.title(),
|
"video_decision": video_decision.title(),
|
||||||
"transcode_decision": decision.title(),
|
"transcode_decision": decision.title(),
|
||||||
|
"transcode_hw_decoding": session.transcode_hw_decoding,
|
||||||
|
"transcode_hw_encoding": session.transcode_hw_encoding,
|
||||||
"media_type": session.media_type.title(),
|
"media_type": session.media_type.title(),
|
||||||
"audio_codec": session.audio_codec.upper(),
|
"audio_codec": session.audio_codec.upper(),
|
||||||
"audio_profile": session.audio_profile.upper(),
|
"audio_profile": session.audio_profile.upper(),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue