diff --git a/dashmachine/platform/healthchecks.py b/dashmachine/platform/healthchecks.py
new file mode 100644
index 0000000..c768af5
--- /dev/null
+++ b/dashmachine/platform/healthchecks.py
@@ -0,0 +1,199 @@
+"""
+##### 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 0000000..3408c8d
--- /dev/null
+++ b/dashmachine/platform/radarr.py
@@ -0,0 +1,268 @@
+"""
+##### 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 0000000..aca722e
--- /dev/null
+++ b/dashmachine/platform/sonarr.py
@@ -0,0 +1,268 @@
+"""
+##### 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 0000000..ad2c265
--- /dev/null
+++ b/dashmachine/platform/tautulli.py
@@ -0,0 +1,224 @@
+"""
+##### 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
+>```
+"""
+
+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