From e95652fc058a0931b1ec43d7cbb8be297f45eed5 Mon Sep 17 00:00:00 2001 From: Tobias Manske Date: Sat, 5 Jan 2019 19:34:21 +0100 Subject: [PATCH] [modules/spaceapi] format string to json parser Signed-off-by: Tobias Manske --- bumblebee/modules/spaceapi.py | 60 +++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/bumblebee/modules/spaceapi.py b/bumblebee/modules/spaceapi.py index 543e64e..89fd341 100644 --- a/bumblebee/modules/spaceapi.py +++ b/bumblebee/modules/spaceapi.py @@ -4,10 +4,11 @@ Requires the following libraries: * requests + * regex Parameters: * spaceapi.url: String representation of the api endpoint - * spaceapi.format: Format string for the output + * spaceapi.format: Format string for the output (refer to code) """ import bumblebee.input @@ -16,7 +17,40 @@ import bumblebee.engine import requests import threading -import sys +import re +from json.decoder import JSONDecodeError + + +def formatStringBuilder(s: str, json: dict) -> str: + """ + This function seems to be in dire need of some explanation so here it is: + It basically searches the format string for strings of the pattern + %%ITEM.IN.TREE[%IFTRUE%IFFALSE]%%. For example to query the state of + the space you'd write %%state.open%% as it's located in json[state][open] + according to the API specificaion. As the output of true or false doesn't + look to great you can specify the text you want to have shown so you'd + write %%state.open%Open%Closed%% to overwrite true/false with Open/Closed. + """ + identifiers = re.findall("%%.*?%%", s) + for i in identifiers: + ic = i[2:-2] # Discard %% + j = ic.split("%") + + if len(j) != 3 and len(j) != 1: + return "INVALID SYNTAX" + + arr = j[0].split(".") + repl = json + for a in arr: # Walk the JSON tree to find replacement + repl = repl[a] + + if len(j) == 1: + s = s.replace(i, repl) + elif repl: + s = s.replace(i, j[1]) + else: + s = s.replace(i, j[2]) + return s class Module(bumblebee.engine.Module): @@ -32,13 +66,15 @@ class Module(bumblebee.engine.Module): # The URL representing the api endpoint self._url = self.parameter("url", default="http://club.entropia.de/spaceapi") - self._format = self.parameter("format", default=" %%space%%: %%state%%") + self._format = self.parameter( + "format", default=" %%space%%: %%state.open%Open%Closed%%" + ) def state(self, widget): try: if self._error is not None: return ["critical"] - elif self._data['state']['open']: + elif self._data["state"]["open"]: return ["warning"] else: return [] @@ -59,27 +95,23 @@ class Module(bumblebee.engine.Module): text = self._error else: try: - text = text.replace("%%space%%", self._data['space']) - if self._data['state']['open']: - text = text.replace("%%state%%", "Open") - else: - text = text.replace("%%state%%", "Closed") + text = formatStringBuilder(self._format, self._data) except KeyError: text = "KeyError" return text def get_api_async(self): try: - with requests.get(self._url, timeout=10) as u: - self._data = u.json() + with requests.get(self._url, timeout=10) as request: + self._data = request.json() self._error = None except requests.exceptions.Timeout: self._error = "Timeout" except requests.exceptions.HTTPError: self._error = "HTTP Error" - # except Exception: - # self._error = "CRITICAL ERROR" + except JSONDecodeError: + self._error = "Not a JSON response" -# Author: Tobias Manske +# Author: Tobias Manske # vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4