diff --git a/dashmachine/platform/healthchecks.py b/dashmachine/platform/healthchecks.py
new file mode 100644
index 00000000..bd88cf97
--- /dev/null
+++ b/dashmachine/platform/healthchecks.py
@@ -0,0 +1,193 @@
+"""
+
+##### Healthchecks
+Display information from Healthchecks API
+```ini
+[variable_name]
+platform = healthchecks
+prefix = http://
+host = localhost
+port = 8080
+api_key = {{ Healthchecks project API Key }}
+project = {{ Healthchecks project name }}
+verify = true
+value_template = {{ value_template }}
+```
+> **Returns:** `value_template` as rendered string
+
+| Variable | Required | Description | Options |
+|-----------------|----------|-----------------------------------------------------------------|-------------------|
+| [variable_name] | Yes | Name for the data source. | [variable_name] |
+| platform | Yes | Name of the platform. | healthchecks |
+| prefix | No | The prefix for the app's url. | web prefix, e.g. http:// or https:// |
+| host | Yes | Healthchecks Host | url,ip |
+| port | No | Healthchecks Port | port |
+| api_key | Yes | ApiKey | api key |
+| project | No | Healthchecks project name | project |
+| verify | No | Turn TLS verification on or off, default is true | true,false |
+| value_template | Yes | Jinja template for how the returned data from API is displayed. | jinja template |
+
+
+###### **Available fields for value_template**
+
+* status
+* count_checks
+* count_up
+* count_down
+* count_grace
+* count_paused
+* error (for debug)
+
+> **Working example:**
+>```ini
+> [healthchecks-data]
+> platform = healthchecks
+> prefix = http://
+> host = 192.168.0.110
+> port = 8080
+> api_key = {{ API Key }}
+> project = {{ Project name }}
+> verify = False
+> value_template = {{error}}
fiber_manual_record{{count_up}}fiber_manual_record{{count_grace}}fiber_manual_record{{count_down}}
+>
+> [Healthchecks]
+> prefix = http://
+> url = 192.168.0.110
+> icon = static/images/apps/healthchecks.png
+> description = Healthchecks is a watchdog for your cron jobs. It's a web server that listens for pings from your cron jobs, plus a web interface.
+> open_in = this_tab
+> data_sources = healthchecks-data
+>```
+
+"""
+
+import json
+from flask import render_template_string
+import requests
+
+class Healthchecks(object):
+
+ def __init__(self,method, prefix, host, port, api_key, project, verify):
+ self.endpoint = "/api/v1/checks/"
+ self.method = method
+ self.prefix = prefix
+ self.host = host
+ self.port = port
+ self.api_key = api_key
+ self.project = project
+ self.verify = verify
+
+ # Initialize results
+ self.error = None
+ self.status = ""
+ self.count_checks = 0
+ self.count_up = 0
+ self.count_down = 0
+ self.count_grace = 0
+ self.count_paused = 0
+
+ def check(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ if 'error' in rawdata:
+ self.error = rawdata['error']
+
+
+ def getChecks(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ for check in rawdata['checks']:
+ self.count_checks += 1
+ if check['status'] == "up":
+ self.count_up += 1
+ if check['status'] == "down":
+ self.count_down += 1
+ if check['status'] == "grace":
+ self.count_grace += 1
+ if check['status'] == "paused":
+ self.count_paused += 1
+
+ if self.count_down > 0:
+ self.status = "down"
+ if self.count_down == 0 and self.count_grace > 0:
+ self.status = "grace"
+ if self.count_down == 0 and self.count_grace == 0:
+ self.status = "up"
+
+ def refresh(self):
+ self.check()
+ if self.error == None:
+ self.error = ''
+ self.getChecks()
+
+class Platform:
+ def __init__(self,*args,**kwargs):
+ # parse the user's options from the config entries
+ for key, value in kwargs.items():
+ self.__dict__[key] = value
+
+ # set defaults for omitted options
+ if not hasattr(self, "method"):
+ self.method = "GET"
+ if not hasattr(self, "prefix"):
+ self.prefix = "http://"
+ if not hasattr(self, "host"):
+ self.host = None
+ if not hasattr(self, "port"):
+ self.port = None
+ if not hasattr(self, "api_key"):
+ self.api_key = None
+ if not hasattr(self, "project"):
+ self.project = None
+ if not hasattr(self, "verify"):
+ self.verify = True
+
+ self.healthchecks = Healthchecks(self.method, self.prefix, self.host, self.port, self.api_key, self.project, self.verify)
+
+ def process(self):
+ if self.api_key == None:
+ return "api_key missing"
+ if self.host == None:
+ return "host missing"
+
+ self.healthchecks.refresh()
+ value_template = render_template_string(
+ self.value_template, **self.healthchecks.__dict__
+ )
+ return value_template
diff --git a/dashmachine/platform/radarr.py b/dashmachine/platform/radarr.py
new file mode 100644
index 00000000..f103c889
--- /dev/null
+++ b/dashmachine/platform/radarr.py
@@ -0,0 +1,263 @@
+"""
+
+##### Radarr
+Display information from Radarr API
+```ini
+[variable_name]
+platform = radarr
+prefix = http://
+host = localhost
+port = 7878
+api_key = my_api_key
+verify = true
+value_template = {{ value_template }}
+```
+> **Returns:** `value_template` as rendered string
+
+| Variable | Required | Description | Options |
+|-----------------|----------|-----------------------------------------------------------------|-------------------|
+| [variable_name] | Yes | Name for the data source. | [variable_name] |
+| platform | Yes | Name of the platform. | radarr |
+| prefix | No | The prefix for the app's url. | web prefix, e.g. http:// or https:// |
+| host | Yes | Radarr Host | url,ip |
+| port | No | Radarr Port | port |
+| api_key | Yes | ApiKey | api key |
+| verify | No | Turn TLS verification on or off, default is true | true,false |
+| value_template | Yes | Jinja template for how the returned data from API is displayed. | jinja template |
+
+
+###### **Available fields for value_template**
+
+* version
+* movies
+* queue
+* diskspace[x]['path']
+* diskspace[x]['total']
+* diskspace[x]['used']
+* diskspace[x]['free']
+* error (for debug)
+
+> **Working example:**
+>```ini
+> [radarr-data]
+> platform = radarr
+> prefix = http://
+> host = 192.168.0.110
+> port = 7878
+> api_key = {{ API Key }}
+> verify = False
+> value_template = {{error}}Movies : {{movies}}
Queue : {{queue}}
Free ({{diskspace[0]['path']}}) : {{diskspace[0]['free']}}
+>
+> [Radarr]
+> prefix = http://
+> url = 192.168.0.110:7878
+> icon = static/images/apps/radarr.png
+> sidebar_icon = static/images/apps/radarr.png
+> description = A fork of Sonarr to work with movies à la Couchpotato
+> open_in = this_tab
+> data_sources = radarr-data
+>```
+"""
+
+import json
+from flask import render_template_string
+import requests
+
+class Radarr(object):
+
+ def __init__(self,method, prefix, host, port, api_key, verify):
+ self.endpoint = "/api"
+ self.method = method
+ self.prefix = prefix
+ self.host = host
+ self.port = port
+ self.api_key = api_key
+ self.verify = verify
+
+ # Initialize results
+ self.error = None
+ self.version = '?'
+ self.movies = 0
+ self.queue = 0
+ self.diskspace = [{'path':'','total':'','free':'','used':''},{'path':'','total':'','free':'','used':''}]
+
+ def check(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/system/status"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ if 'error' in rawdata:
+ self.error = rawdata['error']
+
+ def getVersion(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/system/status"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.version = rawdata['version']
+
+ def getMovies(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/movie"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.movies = len(rawdata)
+
+ def getQueue(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/queue"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.queue = len((rawdata))
+
+ def getDiskspace(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/diskspace"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.diskspace = rawdata
+ for item in self.diskspace:
+ item['used'] = self.formatSize(item['totalSpace'] - item['freeSpace'])
+ item['total'] = self.formatSize(item['totalSpace'])
+ item['free'] = self.formatSize(item['freeSpace'])
+ item.pop('totalSpace', None)
+ item.pop('freeSpace', None)
+
+ def formatSize(self, size):
+ # 2**10 = 1024
+ power = 2**10
+ n = 0
+ power_labels = {0 : '', 1: 'KB', 2: 'MB', 3: 'GB', 4: 'TB'}
+ while size > power:
+ size /= power
+ n += 1
+ return str(round(size,1)) + ' ' + power_labels[n]
+
+ def refresh(self):
+ self.check()
+ if self.error == None:
+ self.error = ''
+ self.getVersion()
+ self.getMovies()
+ self.getQueue()
+ self.getDiskspace()
+
+
+class Platform:
+ def __init__(self,*args,**kwargs):
+ # parse the user's options from the config entries
+ for key, value in kwargs.items():
+ self.__dict__[key] = value
+
+ # set defaults for omitted options
+ if not hasattr(self, "method"):
+ self.method = "GET"
+ if not hasattr(self, "prefix"):
+ self.prefix = "http://"
+ if not hasattr(self, "host"):
+ self.host = None
+ if not hasattr(self, "port"):
+ self.port = None
+ if not hasattr(self, "api_key"):
+ self.api_key = None
+ if not hasattr(self, "verify"):
+ self.verify = True
+
+ self.radarr = Radarr(self.method, self.prefix, self.host, self.port, self.api_key, self.verify)
+
+ def process(self):
+ if self.api_key == None:
+ return "api_key missing"
+ if self.host == None:
+ return "host missing"
+
+ self.radarr.refresh()
+ value_template = render_template_string(
+ self.value_template, **self.radarr.__dict__
+ )
+ return value_template
diff --git a/dashmachine/platform/sonarr.py b/dashmachine/platform/sonarr.py
new file mode 100644
index 00000000..f362163b
--- /dev/null
+++ b/dashmachine/platform/sonarr.py
@@ -0,0 +1,263 @@
+"""
+
+##### Sonarr
+Display information from Sonarr API
+```ini
+[variable_name]
+platform = sonarr
+prefix = http://
+host = localhost
+port = 8989
+api_key = {{ Sonarr API Key }}
+verify = true
+value_template = {{ value_template }}
+```
+> **Returns:** `value_template` as rendered string
+
+| Variable | Required | Description | Options |
+|-----------------|----------|-----------------------------------------------------------------|-------------------|
+| [variable_name] | Yes | Name for the data source. | [variable_name] |
+| platform | Yes | Name of the platform. | sonarr |
+| prefix | No | The prefix for the app's url. | web prefix, e.g. http:// or https:// |
+| host | Yes | Sonarr Host | url,ip |
+| port | No | Sonarr Port | port |
+| api_key | Yes | ApiKey | api key |
+| verify | No | Turn TLS verification on or off, default is true | true,false |
+| value_template | Yes | Jinja template for how the returned data from API is displayed. | jinja template |
+
+
+###### **Available fields for value_template**
+
+* version
+* wanted_missing
+* queue
+* diskspace[x]['path']
+* diskspace[x]['total']
+* diskspace[x]['used']
+* diskspace[x]['free']
+* error (for debug)
+
+> **Working example:**
+>```ini
+> [sonarr-data]
+> platform = sonarr
+> prefix = http://
+> host = 192.168.0.110
+> port = 8989
+> api_key = {{ API Key }}
+> verify = False
+> value_template = {{error}}Missing : {{wanted_missing}}
Queue : {{queue}}
Free ({{diskspace[0]['path']}}) : {{diskspace[0]['free']}}
+>
+> [Sonarr]
+> prefix = http://
+> url = 192.168.0.110:8989
+> icon = static/images/apps/sonarr.png
+> sidebar_icon = static/images/apps/sonarr.png
+> description = Smart PVR for newsgroup and bittorrent users
+> open_in = this_tab
+> data_sources = sonarr-data
+>```
+"""
+
+import json
+from flask import render_template_string
+import requests
+
+class Sonarr(object):
+
+ def __init__(self,method, prefix, host, port, api_key, verify):
+ self.endpoint = "/api"
+ self.method = method
+ self.prefix = prefix
+ self.host = host
+ self.port = port
+ self.api_key = api_key
+ self.verify = verify
+
+ # Initialize results
+ self.error = None
+ self.version = '?'
+ self.wanted_missing = 0
+ self.queue = 0
+ self.diskspace = [{'path':'','total':'','free':'','used':''},{'path':'','total':'','free':'','used':''}]
+
+ def check(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/system/status"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ if 'error' in rawdata:
+ self.error = rawdata['error']
+
+ def getVersion(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/system/status"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.version = rawdata['version']
+
+ def getWanted(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/wanted/missing/"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.wanted_missing = rawdata['totalRecords']
+
+ def getQueue(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/queue"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.queue = len(rawdata)
+
+ def getDiskspace(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "/diskspace"
+ , headers=headers
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.diskspace = rawdata
+ for item in self.diskspace:
+ item['used'] = self.formatSize(item['totalSpace'] - item['freeSpace'])
+ item['total'] = self.formatSize(item['totalSpace'])
+ item['free'] = self.formatSize(item['freeSpace'])
+ item.pop('totalSpace', None)
+ item.pop('freeSpace', None)
+
+ def formatSize(self, size):
+ # 2**10 = 1024
+ power = 2**10
+ n = 0
+ power_labels = {0 : '', 1: 'KB', 2: 'MB', 3: 'GB', 4: 'TB'}
+ while size > power:
+ size /= power
+ n += 1
+ return str(round(size,1)) + ' ' + power_labels[n]
+
+ def refresh(self):
+ self.check()
+ if self.error == None:
+ self.error = ''
+ self.getVersion()
+ self.getWanted()
+ self.getQueue()
+ self.getDiskspace()
+
+
+class Platform:
+ def __init__(self,*args,**kwargs):
+ # parse the user's options from the config entries
+ for key, value in kwargs.items():
+ self.__dict__[key] = value
+
+ # set defaults for omitted options
+ if not hasattr(self, "method"):
+ self.method = "GET"
+ if not hasattr(self, "prefix"):
+ self.prefix = "http://"
+ if not hasattr(self, "host"):
+ self.host = None
+ if not hasattr(self, "port"):
+ self.port = None
+ if not hasattr(self, "api_key"):
+ self.api_key = None
+ if not hasattr(self, "verify"):
+ self.verify = True
+
+ self.sonarr = Sonarr(self.method, self.prefix, self.host, self.port, self.api_key, self.verify)
+
+ def process(self):
+ if self.api_key == None:
+ return "api_key missing"
+ if self.host == None:
+ return "host missing"
+
+ self.sonarr.refresh()
+ value_template = render_template_string(
+ self.value_template, **self.sonarr.__dict__
+ )
+ return value_template
diff --git a/dashmachine/platform/tautulli.py b/dashmachine/platform/tautulli.py
new file mode 100644
index 00000000..b26717e9
--- /dev/null
+++ b/dashmachine/platform/tautulli.py
@@ -0,0 +1,208 @@
+"""
+
+##### Tautulli
+Display information from Tautulli API
+```ini
+[variable_name]
+platform = tautulli
+prefix = http://
+host = localhost
+port = 8181
+api_key = {{ Tautulli API Key }}
+verify = true
+value_template = {{ value_template }}
+```
+> **Returns:** `value_template` as rendered string
+
+| Variable | Required | Description | Options |
+|-----------------|----------|-----------------------------------------------------------------|-------------------|
+| [variable_name] | Yes | Name for the data source. | [variable_name] |
+| platform | Yes | Name of the platform. | tautulli |
+| prefix | No | The prefix for the app's url. | web prefix, e.g. http:// or https:// |
+| host | Yes | Tautulli Host | url,ip |
+| port | No | Tautulli Port | port |
+| api_key | Yes | ApiKey | api key |
+| verify | No | Turn TLS verification on or off, default is true | true,false |
+| value_template | Yes | Jinja template for how the returned data from API is displayed. | jinja template |
+
+
+###### **Available fields for value_template**
+
+* stream_count
+* stream_count_direct_play
+* stream_count_direct_stream
+* stream_count_transcode
+* total_bandwidth
+* wan_bandwidth
+* update_available
+* update_message
+* error (for debug)
+
+> **Working example:**
+>```ini
+> [tautulli-data]
+> platform = tautulli
+> prefix = http://
+> host = 192.168.0.110
+> port = 8181
+> api_key = myApiKey
+> verify = False
+> value_template = {{error}}Active sessions : {{stream_count}}
+>
+> [Tautulli]
+> prefix = http://
+> url = 192.168.0.110:8181
+> icon = static/images/apps/tautulli.png
+> sidebar_icon = static/images/apps/tautulli.png
+> description = A Python based monitoring and tracking tool for Plex Media Server
+> open_in = this_tab
+> data_sources = tautulli-data
+>```
+"""
+
+import json
+from flask import render_template_string
+import requests
+
+class Tautulli(object):
+
+ def __init__(self,method, prefix, host, port, api_key, verify):
+ self.endpoint = "/api/v2"
+ self.method = method
+ self.prefix = prefix
+ self.host = host
+ self.port = port
+ self.api_key = api_key
+ self.verify = verify
+
+ # Initialize results
+ self.error = None
+ self.update_available = ''
+ self.update_message = ''
+ self.stream_count = ''
+
+ def check(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ headers = {'X-Api-Key': self.api_key}
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "?apikey="
+ + self.api_key
+ + "&cmd="
+ + "update_check"
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ if 'response' in rawdata and rawdata['response']['result'] == 'error':
+ self.error = rawdata['response']['message']
+
+ def getUpdate(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "?apikey="
+ + self.api_key
+ + "&cmd="
+ + "update_check"
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.update_message = rawdata['response']['message']
+ self.update_available = rawdata['response']['data']['update']
+
+ def getActivity(self):
+ verify = False if str(self.verify).lower() == "false" or str(self.prefix).lower() == "http://" else True
+ port = '' if self.port == None else ':' + self.port
+
+ if self.method.upper() == "GET":
+ try:
+ rawdata = requests.get(
+ self.prefix
+ + self.host
+ + port
+ + self.endpoint
+ + "?apikey="
+ + self.api_key
+ + "&cmd="
+ + "get_activity"
+ , verify=verify
+ , timeout=10
+ ).json()
+ except Exception as e:
+ rawdata = None
+ self.error = f"{e}"
+
+ if rawdata != None:
+ self.stream_count = rawdata['response']['data']['stream_count']
+ self.stream_count_direct_play = rawdata['response']['data']['stream_count_direct_play']
+ self.stream_count_direct_stream = rawdata['response']['data']['stream_count_direct_stream']
+ self.stream_count_transcode = rawdata['response']['data']['stream_count_transcode']
+ self.total_bandwidth = rawdata['response']['data']['total_bandwidth']
+ self.wan_bandwidth = rawdata['response']['data']['wan_bandwidth']
+
+
+ def refresh(self):
+ self.check()
+ if self.error == None:
+ self.error = ''
+ self.getUpdate()
+ self.getActivity()
+
+
+class Platform:
+ def __init__(self,*args,**kwargs):
+ # parse the user's options from the config entries
+ for key, value in kwargs.items():
+ self.__dict__[key] = value
+
+ # set defaults for omitted options
+ if not hasattr(self, "method"):
+ self.method = "GET"
+ if not hasattr(self, "prefix"):
+ self.prefix = "http://"
+ if not hasattr(self, "host"):
+ self.host = None
+ if not hasattr(self, "port"):
+ self.port = None
+ if not hasattr(self, "api_key"):
+ self.api_key = None
+ if not hasattr(self, "verify"):
+ self.verify = True
+
+ self.tautulli = Tautulli(self.method, self.prefix, self.host, self.port, self.api_key, self.verify)
+
+ def process(self):
+ if self.api_key == None:
+ return "api_key missing"
+ if self.host == None:
+ return "host missing"
+
+ self.tautulli.refresh()
+ value_template = render_template_string(
+ self.value_template, **self.tautulli.__dict__
+ )
+ return value_template