From 31bb2319ee24031b53427be661fd947255f4dfcc Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 07:47:40 -0700 Subject: [PATCH 01/49] Adding apiimage applet --- apps/apiimage/api_image.star | 141 +++++++++++++++++++++++++++++++++++ apps/apiimage/manifest.yaml | 6 ++ 2 files changed, 147 insertions(+) create mode 100644 apps/apiimage/api_image.star create mode 100644 apps/apiimage/manifest.yaml diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star new file mode 100644 index 000000000..ee66d88c7 --- /dev/null +++ b/apps/apiimage/api_image.star @@ -0,0 +1,141 @@ +""" +Applet: API image +Summary: API image display +Description: Display an image from an endpoint. +Author: Michael Yagi +""" + +load("render.star", "render") +load("http.star", "http") +load("schema.star", "schema") + +DEFAULT_API_URL = "https://dog.ceo/api/breeds/image/random" +DEFAULT_BASE_URL = "" +DEFAULT_APP_HEADERS = "" +DEFAULT_RESPONSE_PATH = "message" + +def main(config): + base_url = config.str("base_url", DEFAULT_BASE_URL) + api_url = config.str("api_url", DEFAULT_API_URL) + response_path = config.get("response_path", DEFAULT_RESPONSE_PATH) + api_headers = config.get("api_headers", DEFAULT_APP_HEADERS) + + # print("api_url") + # print(api_url) + # print("response_path") + # print(response_path) + + failure = False + + if api_url == "": + failure = True + # print("api_url must not be blank.") + else: + if api_headers != "" or api_headers != {}: + api_headers = api_headers.split(",") + headerMap = {} + for app_header in api_headers: + headerKeyValueArray = app_header.split(":") + if len(headerKeyValueArray) > 1: + headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() + + rep = http.get(api_url, headers=headerMap) + else: + rep = http.get(api_url) + + if rep.status_code != 200: + failure = True + # print("Request failed with status %d", rep.status_code) + else: + json = rep.json() + + if json.get("status") == "fail": + failure = True + + if failure == False or json != "" or response_path != []: + + responsePathArray = response_path + + responsePathArray = responsePathArray.split(",") + + for item in responsePathArray: + item = item.strip() + if item.isdigit(): + item = int(item) + # print("item") + # print(item) + # print(type(json)) + if (type(json) == "dict" and json.get(item) == None) or (type(json) == "list" and json[item] == None): + failure = True + # print("responsePathArray invalid. " + item + " does not exist") + break + else: + json = json[item] + + if type(json) == "string" and failure == False: + if json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + failure = True + # print("Invalide URL. Requires a base_url") + else: + if base_url != "": + img = http.get(base_url + json).body() + else: + img = http.get(json).body() + + return render.Root( + render.Row( + expanded=True, + main_align="space_evenly", + cross_align="center", + children = [render.Image(src = img, height = 32)] + ) + ) + else: + # print("Invalid path for image") + # print(json) + failure = True + else: + # print("Status failed") + # print(json) + failure = True + + if failure == True: + # fail() + print("Something went wrong") + + # return failure + +def get_schema(): + return schema.Schema( + version = "1", + fields = [ + schema.Text( + id = "base_url", + name = "Base URL", + desc = "The base URL if URLs are relative paths.", + icon = "", + default = "", + ), + schema.Text( + id = "api_url", + name = "URL", + desc = "The API url.", + icon = "", + default = "https://dog.ceo/api/breeds/image/random", + ), + schema.Text( + id = "response_path", + name = "Response path", + desc = "A comma separated path to the image in the response JSON. eg. `json_key1, 2, key_to_image_url`", + icon = "", + default = "message", + ), + schema.Text( + id = "api_headers", + name = "Request headers", + desc = "Comma separated key:value pairs to build the request headers. eg, `x-api-key:abc123,content-type:application/json`", + icon = "", + default = "", + ) + ], + ) \ No newline at end of file diff --git a/apps/apiimage/manifest.yaml b/apps/apiimage/manifest.yaml new file mode 100644 index 000000000..92de24782 --- /dev/null +++ b/apps/apiimage/manifest.yaml @@ -0,0 +1,6 @@ +--- +id: api-image +name: API Image +summary: Displays image from an API endpoint. +desc: Configure a URL, headers and the response path to the image to display. Best when using an endpoint that serves random images. +author: MichaelYagi From 6f5197f4bc0e95bd99fed097c7c8ab39627f78f8 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 07:54:45 -0700 Subject: [PATCH 02/49] Adding apiimage applet --- apps/apiimage/manifest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/manifest.yaml b/apps/apiimage/manifest.yaml index 92de24782..f3b65ceee 100644 --- a/apps/apiimage/manifest.yaml +++ b/apps/apiimage/manifest.yaml @@ -1,6 +1,6 @@ --- id: api-image name: API Image -summary: Displays image from an API endpoint. -desc: Configure a URL, headers and the response path to the image to display. Best when using an endpoint that serves random images. +summary: Pull image from an API. +desc: Configure a URL, headers and the response path to the image to display. author: MichaelYagi From 1952157d19c8dd9d4529b91db08340162cb836f9 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 07:57:30 -0700 Subject: [PATCH 03/49] Adding apiimage applet --- apps/apiimage/manifest.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/manifest.yaml b/apps/apiimage/manifest.yaml index f3b65ceee..c7e3ada99 100644 --- a/apps/apiimage/manifest.yaml +++ b/apps/apiimage/manifest.yaml @@ -1,6 +1,6 @@ --- id: api-image name: API Image -summary: Pull image from an API. -desc: Configure a URL, headers and the response path to the image to display. +summary: Pull image from an API +desc: Configure a URL, headers and the response path to the image to display author: MichaelYagi From 1c42b201b477ee26ff8a93b6540a00be81fd472d Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 07:58:31 -0700 Subject: [PATCH 04/49] Adding apiimage applet --- apps/apiimage/manifest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/manifest.yaml b/apps/apiimage/manifest.yaml index c7e3ada99..40ba7a769 100644 --- a/apps/apiimage/manifest.yaml +++ b/apps/apiimage/manifest.yaml @@ -2,5 +2,5 @@ id: api-image name: API Image summary: Pull image from an API -desc: Configure a URL, headers and the response path to the image to display +desc: Configure a URL, headers and the response path to the image to display. author: MichaelYagi From 46571942a2f552127793ac10d36e9b2ebc75781b Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 08:27:37 -0700 Subject: [PATCH 05/49] Adding apiimage applet --- apps/apiimage/api_image.star | 292 ++++++++++++++++++----------------- 1 file changed, 151 insertions(+), 141 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index ee66d88c7..b0ce273fc 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -1,141 +1,151 @@ -""" -Applet: API image -Summary: API image display -Description: Display an image from an endpoint. -Author: Michael Yagi -""" - -load("render.star", "render") -load("http.star", "http") -load("schema.star", "schema") - -DEFAULT_API_URL = "https://dog.ceo/api/breeds/image/random" -DEFAULT_BASE_URL = "" -DEFAULT_APP_HEADERS = "" -DEFAULT_RESPONSE_PATH = "message" - -def main(config): - base_url = config.str("base_url", DEFAULT_BASE_URL) - api_url = config.str("api_url", DEFAULT_API_URL) - response_path = config.get("response_path", DEFAULT_RESPONSE_PATH) - api_headers = config.get("api_headers", DEFAULT_APP_HEADERS) - - # print("api_url") - # print(api_url) - # print("response_path") - # print(response_path) - - failure = False - - if api_url == "": - failure = True - # print("api_url must not be blank.") - else: - if api_headers != "" or api_headers != {}: - api_headers = api_headers.split(",") - headerMap = {} - for app_header in api_headers: - headerKeyValueArray = app_header.split(":") - if len(headerKeyValueArray) > 1: - headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() - - rep = http.get(api_url, headers=headerMap) - else: - rep = http.get(api_url) - - if rep.status_code != 200: - failure = True - # print("Request failed with status %d", rep.status_code) - else: - json = rep.json() - - if json.get("status") == "fail": - failure = True - - if failure == False or json != "" or response_path != []: - - responsePathArray = response_path - - responsePathArray = responsePathArray.split(",") - - for item in responsePathArray: - item = item.strip() - if item.isdigit(): - item = int(item) - # print("item") - # print(item) - # print(type(json)) - if (type(json) == "dict" and json.get(item) == None) or (type(json) == "list" and json[item] == None): - failure = True - # print("responsePathArray invalid. " + item + " does not exist") - break - else: - json = json[item] - - if type(json) == "string" and failure == False: - if json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): - failure = True - # print("Invalide URL. Requires a base_url") - else: - if base_url != "": - img = http.get(base_url + json).body() - else: - img = http.get(json).body() - - return render.Root( - render.Row( - expanded=True, - main_align="space_evenly", - cross_align="center", - children = [render.Image(src = img, height = 32)] - ) - ) - else: - # print("Invalid path for image") - # print(json) - failure = True - else: - # print("Status failed") - # print(json) - failure = True - - if failure == True: - # fail() - print("Something went wrong") - - # return failure - -def get_schema(): - return schema.Schema( - version = "1", - fields = [ - schema.Text( - id = "base_url", - name = "Base URL", - desc = "The base URL if URLs are relative paths.", - icon = "", - default = "", - ), - schema.Text( - id = "api_url", - name = "URL", - desc = "The API url.", - icon = "", - default = "https://dog.ceo/api/breeds/image/random", - ), - schema.Text( - id = "response_path", - name = "Response path", - desc = "A comma separated path to the image in the response JSON. eg. `json_key1, 2, key_to_image_url`", - icon = "", - default = "message", - ), - schema.Text( - id = "api_headers", - name = "Request headers", - desc = "Comma separated key:value pairs to build the request headers. eg, `x-api-key:abc123,content-type:application/json`", - icon = "", - default = "", - ) - ], - ) \ No newline at end of file +""" +Applet: API image +Summary: API image display +Description: Display an image from an endpoint. +Author: Michael Yagi +""" + +load("http.star", "http") +load("render.star", "render") +load("schema.star", "schema") + +DEFAULT_API_URL = "https://dog.ceo/api/breeds/image/random" +DEFAULT_BASE_URL = "" +DEFAULT_APP_HEADERS = "" +DEFAULT_RESPONSE_PATH = "message" + +def main(config): + base_url = config.str("base_url", DEFAULT_BASE_URL) + api_url = config.str("api_url", DEFAULT_API_URL) + response_path = config.get("response_path", DEFAULT_RESPONSE_PATH) + api_headers = config.get("api_headers", DEFAULT_APP_HEADERS) + + # print("api_url") + # print(api_url) + # print("response_path") + # print(response_path) + + failure = False + + if api_url == "": + failure = True + # print("api_url must not be blank.") + + else: + if api_headers != "" or api_headers != {}: + api_headers = api_headers.split(",") + headerMap = {} + for app_header in api_headers: + headerKeyValueArray = app_header.split(":") + if len(headerKeyValueArray) > 1: + headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() + + rep = http.get(api_url, headers = headerMap) + else: + rep = http.get(api_url) + + if rep.status_code != 200: + failure = True + # print("Request failed with status %d", rep.status_code) + + else: + json = rep.json() + + if json.get("status") == "fail": + failure = True + + if failure == False or json != "" or response_path != []: + responsePathArray = response_path + + responsePathArray = responsePathArray.split(",") + + for item in responsePathArray: + item = item.strip() + if item.isdigit(): + item = int(item) + + # print("item") + # print(item) + # print(type(json)) + if (type(json) == "dict" and json.get(item) == None) or (type(json) == "list" and json[item] == None): + failure = True + + # print("responsePathArray invalid. " + item + " does not exist") + break + else: + json = json[item] + + if type(json) == "string" and failure == False: + if json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + failure = True + # print("Invalide URL. Requires a base_url") + + else: + if base_url != "": + img = http.get(base_url + json).body() + else: + img = http.get(json).body() + + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [render.Image(src = img, height = 32)], + ), + ) + else: + # print("Invalid path for image") + # print(json) + failure = True + else: + # print("Status failed") + # print(json) + failure = True + + # if failure == True: + # fail() + # print("Something went wrong") + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [render.Text("Could not get image.")], + ), + ) + +def get_schema(): + return schema.Schema( + version = "1", + fields = [ + schema.Text( + id = "base_url", + name = "Base URL", + desc = "The base URL if URLs are relative paths.", + icon = "", + default = "", + ), + schema.Text( + id = "api_url", + name = "URL", + desc = "The API url.", + icon = "", + default = "https://dog.ceo/api/breeds/image/random", + ), + schema.Text( + id = "response_path", + name = "Response path", + desc = "A comma separated path to the image in the response JSON. eg. `json_key1, 2, key_to_image_url`", + icon = "", + default = "message", + ), + schema.Text( + id = "api_headers", + name = "Request headers", + desc = "Comma separated key:value pairs to build the request headers. eg, `x-api-key:abc123,content-type:application/json`", + icon = "", + default = "", + ), + ], + ) From 781efc0a27d9632e01ec9106cd445c782f913433 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 08:36:01 -0700 Subject: [PATCH 06/49] I have read the CLA Document and I hereby sign the CLA --- apps/apiimage/manifest.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/manifest.yaml b/apps/apiimage/manifest.yaml index 40ba7a769..b28dae4c0 100644 --- a/apps/apiimage/manifest.yaml +++ b/apps/apiimage/manifest.yaml @@ -1,6 +1,6 @@ --- id: api-image name: API Image -summary: Pull image from an API +summary: Pull an image from an API desc: Configure a URL, headers and the response path to the image to display. author: MichaelYagi From 4f2c01de957c02d3d6974a27158fb0b4deab85b6 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 10:57:33 -0700 Subject: [PATCH 07/49] I have read the CLA Document and I hereby sign the CLA --- apps/apiimage/api_image.star | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index b0ce273fc..44c5b37d0 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -103,15 +103,16 @@ def main(config): # print(json) failure = True - # if failure == True: - # fail() - # print("Something went wrong") return render.Root( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [render.Text("Could not get image.")], + child = render.Box( + render.Row( + expanded=True, + main_align="space_evenly", + cross_align="center", + children = [ + render.WrappedText(content = "Could not get image", font = "5x8"), + ], + ), ), ) From 3251edd51bffe985f5442b94950a3bd3a09fdd58 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 10:59:51 -0700 Subject: [PATCH 08/49] I have read the CLA Document and I hereby sign the CLA --- apps/apiimage/api_image.star | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 44c5b37d0..a4bd87c29 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -106,9 +106,9 @@ def main(config): return render.Root( child = render.Box( render.Row( - expanded=True, - main_align="space_evenly", - cross_align="center", + expanded = True, + main_align = "space_evenly", + cross_align = "center", children = [ render.WrappedText(content = "Could not get image", font = "5x8"), ], From baef677ac7865c418dcda657cc78268c72f627b5 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 12:25:57 -0700 Subject: [PATCH 09/49] Updated TTL for API image app --- apps/apiimage/api_image.star | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index a4bd87c29..8f18555df 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -13,6 +13,7 @@ DEFAULT_API_URL = "https://dog.ceo/api/breeds/image/random" DEFAULT_BASE_URL = "" DEFAULT_APP_HEADERS = "" DEFAULT_RESPONSE_PATH = "message" +TTL_SECONDS = 60 def main(config): base_url = config.str("base_url", DEFAULT_BASE_URL) @@ -40,9 +41,9 @@ def main(config): if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() - rep = http.get(api_url, headers = headerMap) + rep = http.get(api_url, headers = headerMap, ttl_seconds = TTL_SECONDS) else: - rep = http.get(api_url) + rep = http.get(api_url, ttl_seconds = TTL_SECONDS) if rep.status_code != 200: failure = True @@ -82,9 +83,9 @@ def main(config): else: if base_url != "": - img = http.get(base_url + json).body() + img = http.get(base_url + json, ttl_seconds = TTL_SECONDS).body() else: - img = http.get(json).body() + img = http.get(json, ttl_seconds = TTL_SECONDS).body() return render.Root( render.Row( @@ -106,9 +107,9 @@ def main(config): return render.Root( child = render.Box( render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", + expanded=True, + main_align="space_evenly", + cross_align="center", children = [ render.WrappedText(content = "Could not get image", font = "5x8"), ], From 681b7c9186ddd4f29b965f79b8fd632740d64a8f Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 12:28:56 -0700 Subject: [PATCH 10/49] Updated TTL for API image app --- apps/apiimage/api_image.star | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 8f18555df..b71db9b25 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -107,9 +107,9 @@ def main(config): return render.Root( child = render.Box( render.Row( - expanded=True, - main_align="space_evenly", - cross_align="center", + expanded = True, + main_align = "space_evenly", + cross_align = "center", children = [ render.WrappedText(content = "Could not get image", font = "5x8"), ], From 20d132e17f69af738540fff17713359c6eca23e3 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 17:02:01 -0700 Subject: [PATCH 11/49] Updated caching in app --- apps/apiimage/api_image.star | 181 +++++++++++++++++++++-------------- 1 file changed, 107 insertions(+), 74 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index b71db9b25..286f895ce 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -5,118 +5,149 @@ Description: Display an image from an endpoint. Author: Michael Yagi """ +load("cache.star", "cache") +load("encoding/json.star", "json") load("http.star", "http") load("render.star", "render") load("schema.star", "schema") -DEFAULT_API_URL = "https://dog.ceo/api/breeds/image/random" -DEFAULT_BASE_URL = "" -DEFAULT_APP_HEADERS = "" -DEFAULT_RESPONSE_PATH = "message" -TTL_SECONDS = 60 +DEBUG = True def main(config): - base_url = config.str("base_url", DEFAULT_BASE_URL) - api_url = config.str("api_url", DEFAULT_API_URL) - response_path = config.get("response_path", DEFAULT_RESPONSE_PATH) - api_headers = config.get("api_headers", DEFAULT_APP_HEADERS) - - # print("api_url") - # print(api_url) - # print("response_path") - # print(response_path) + base_url = config.str("base_url", "") + api_url = config.str("api_url", "") + response_path = config.get("response_path", "") + api_headers = config.get("api_headers", "") + + if DEBUG: + print("api_url") + print(api_url) + print("response_path") + print(response_path) + print("api_headers") + print(api_headers) failure = False if api_url == "": failure = True - # print("api_url must not be blank.") + if DEBUG: + print("api_url must not be blank.") else: + headerMap = {} if api_headers != "" or api_headers != {}: api_headers = api_headers.split(",") - headerMap = {} + for app_header in api_headers: headerKeyValueArray = app_header.split(":") if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() - rep = http.get(api_url, headers = headerMap, ttl_seconds = TTL_SECONDS) - else: - rep = http.get(api_url, ttl_seconds = TTL_SECONDS) + json_body = get_cached(api_url, headerMap) + + decoded_json = json.decode(json_body) - if rep.status_code != 200: + if DEBUG: + print("Decoded JSON") + print(decoded_json) + + if decoded_json.get("status") == "fail": failure = True - # print("Request failed with status %d", rep.status_code) - else: - json = rep.json() + if failure == False or decoded_json != "" or response_path != []: + responsePathArray = response_path - if json.get("status") == "fail": - failure = True + responsePathArray = responsePathArray.split(",") - if failure == False or json != "" or response_path != []: - responsePathArray = response_path + for item in responsePathArray: + item = item.strip() + if item.isdigit(): + item = int(item) - responsePathArray = responsePathArray.split(",") + if DEBUG: + print("item") + print(item) + print(type(decoded_json)) - for item in responsePathArray: - item = item.strip() - if item.isdigit(): - item = int(item) + if (type(decoded_json) == "dict" and decoded_json.get(item) == None) or (type(decoded_json) == "list" and decoded_json[item] == None): + failure = True + if DEBUG: + print("responsePathArray invalid. " + item + " does not exist") + break + else: + decoded_json = decoded_json[item] - # print("item") - # print(item) - # print(type(json)) - if (type(json) == "dict" and json.get(item) == None) or (type(json) == "list" and json[item] == None): - failure = True + if type(decoded_json) == "string" and failure == False: + if decoded_json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + failure = True + if DEBUG: + print("Invalide URL. Requires a base_url") - # print("responsePathArray invalid. " + item + " does not exist") - break + else: + if base_url != "": + url = base_url + decoded_json else: - json = json[item] + url = decoded_json - if type(json) == "string" and failure == False: - if json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): - failure = True - # print("Invalide URL. Requires a base_url") + img = get_cached(url) - else: - if base_url != "": - img = http.get(base_url + json, ttl_seconds = TTL_SECONDS).body() - else: - img = http.get(json, ttl_seconds = TTL_SECONDS).body() - - return render.Root( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [render.Image(src = img, height = 32)], - ), - ) - else: - # print("Invalid path for image") - # print(json) - failure = True + if DEBUG: + print("URL: " + url) + + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [render.Image(src = img, height = 32)], + ), + ) else: - # print("Status failed") - # print(json) + if DEBUG: + print("Invalid path for image") + print(decoded_json) failure = True + else: + if DEBUG: + print("Status failed") + print(decoded_json) + failure = True return render.Root( child = render.Box( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [ - render.WrappedText(content = "Could not get image", font = "5x8"), - ], - ), + # render.Row( + # expanded=True, + # main_align="space_evenly", + # cross_align="center", + # children = [ + # render.WrappedText(content = "Could not get image", font = "5x8"), + # ], + # ), ), ) +def get_cached(url, headerMap = {}, ttl_seconds = 20): + data = cache.get(url) + if data: + return data + + if headerMap == {}: + res = http.get(url) + else: + res = http.get(url, headers = headerMap) + + if res.status_code != 200: + if DEBUG: + print("status %d from %s: %s" % (res.status_code, url, res.body())) + fail("status %d from %s: %s" % (res.status_code, url, res.body())) + + data = res.body() + + cache.set(url, data, ttl_seconds = ttl_seconds) + + return data + def get_schema(): return schema.Schema( version = "1", @@ -133,14 +164,16 @@ def get_schema(): name = "URL", desc = "The API url.", icon = "", - default = "https://dog.ceo/api/breeds/image/random", + default = "", + # default = "https://dog.ceo/api/breeds/image/random", ), schema.Text( id = "response_path", name = "Response path", desc = "A comma separated path to the image in the response JSON. eg. `json_key1, 2, key_to_image_url`", icon = "", - default = "message", + default = "", + # default = "message", ), schema.Text( id = "api_headers", From 2f9a3041f633d1651d6eee21d4753a2303352c87 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 17:12:11 -0700 Subject: [PATCH 12/49] Turn off debug flag --- apps/apiimage/api_image.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 286f895ce..67d0ebd16 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -11,7 +11,7 @@ load("http.star", "http") load("render.star", "render") load("schema.star", "schema") -DEBUG = True +DEBUG = False def main(config): base_url = config.str("base_url", "") From bfcef237c5f6766552c66061208b1fc9628a14db Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 19:36:44 -0700 Subject: [PATCH 13/49] Fixed header array bug --- apps/apiimage/api_image.star | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 67d0ebd16..2a78a9aff 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -11,7 +11,7 @@ load("http.star", "http") load("render.star", "render") load("schema.star", "schema") -DEBUG = False +DEBUG = True def main(config): base_url = config.str("base_url", "") @@ -27,6 +27,9 @@ def main(config): print("api_headers") print(api_headers) + return get_image(base_url, api_url, response_path, api_headers) + +def get_image(base_url, api_url, response_path, api_headers): failure = False if api_url == "": @@ -37,9 +40,9 @@ def main(config): else: headerMap = {} if api_headers != "" or api_headers != {}: - api_headers = api_headers.split(",") + api_headers_array = api_headers.split(",") - for app_header in api_headers: + for app_header in api_headers_array: headerKeyValueArray = app_header.split(":") if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() @@ -108,6 +111,7 @@ def main(config): print("Invalid path for image") print(decoded_json) failure = True + return get_image(base_url, api_url, response_path, api_headers) else: if DEBUG: print("Status failed") From 248fe585c933a4f4425069d1d29fbd36ba6c9d90 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 19:40:36 -0700 Subject: [PATCH 14/49] Turned off debug mode --- apps/apiimage/api_image.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 2a78a9aff..289682842 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -11,7 +11,7 @@ load("http.star", "http") load("render.star", "render") load("schema.star", "schema") -DEBUG = True +DEBUG = False def main(config): base_url = config.str("base_url", "") From 145b4e6d9810bd7ffe4182a884811ce51a7a41a5 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 21:14:28 -0700 Subject: [PATCH 15/49] Added debug toggle --- apps/apiimage/api_image.star | 178 ++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 74 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 289682842..86b81ed77 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -11,30 +11,34 @@ load("http.star", "http") load("render.star", "render") load("schema.star", "schema") -DEBUG = False - def main(config): base_url = config.str("base_url", "") api_url = config.str("api_url", "") response_path = config.get("response_path", "") api_headers = config.get("api_headers", "") + debug_output = config.bool("debug_output", False) - if DEBUG: + if debug_output: print("api_url") print(api_url) print("response_path") print(response_path) print("api_headers") print(api_headers) + print("debug_output") + print(debug_output) - return get_image(base_url, api_url, response_path, api_headers) + return get_image(base_url, api_url, response_path, api_headers, debug_output) -def get_image(base_url, api_url, response_path, api_headers): +def get_image(base_url, api_url, response_path, api_headers, debug_output): failure = False + message = "" if api_url == "": failure = True - if DEBUG: + message = "API URL must not be blank" + + if debug_output: print("api_url must not be blank.") else: @@ -47,91 +51,109 @@ def get_image(base_url, api_url, response_path, api_headers): if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() - json_body = get_cached(api_url, headerMap) - - decoded_json = json.decode(json_body) + json_body = get_cached(api_url, debug_output, headerMap) - if DEBUG: - print("Decoded JSON") - print(decoded_json) + if json_body != None: + decoded_json = json.decode(json_body) - if decoded_json.get("status") == "fail": - failure = True - - if failure == False or decoded_json != "" or response_path != []: - responsePathArray = response_path + if debug_output: + print("Decoded JSON") + print(decoded_json) - responsePathArray = responsePathArray.split(",") + if decoded_json.get("status") == "fail": + failure = True - for item in responsePathArray: - item = item.strip() - if item.isdigit(): - item = int(item) + if failure == False or decoded_json != "" or response_path != []: + responsePathArray = response_path - if DEBUG: - print("item") - print(item) - print(type(decoded_json)) + responsePathArray = responsePathArray.split(",") - if (type(decoded_json) == "dict" and decoded_json.get(item) == None) or (type(decoded_json) == "list" and decoded_json[item] == None): - failure = True - if DEBUG: - print("responsePathArray invalid. " + item + " does not exist") - break - else: - decoded_json = decoded_json[item] + for item in responsePathArray: + item = item.strip() + if item.isdigit(): + item = int(item) - if type(decoded_json) == "string" and failure == False: - if decoded_json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): - failure = True - if DEBUG: - print("Invalide URL. Requires a base_url") + if debug_output: + print("item") + print(item) + print(type(decoded_json)) - else: - if base_url != "": - url = base_url + decoded_json + if (type(decoded_json) == "dict" and decoded_json.get(item) == None) or (type(decoded_json) == "list" and decoded_json[item] == None): + failure = True + message = "Response path invalid. " + item + " does not exist" + if debug_output: + print("responsePathArray invalid. " + item + " does not exist") + break else: - url = decoded_json + decoded_json = decoded_json[item] - img = get_cached(url) + if type(decoded_json) == "string" and failure == False: + if decoded_json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + failure = True + message = "Base URL missing" + if debug_output: + print("Invalide URL. Requires a base_url") - if DEBUG: - print("URL: " + url) - - return render.Root( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [render.Image(src = img, height = 32)], - ), - ) + else: + if base_url != "": + url = base_url + decoded_json + else: + url = decoded_json + + img = get_cached(url, debug_output) + + if debug_output: + print("URL: " + url) + + if img != None: + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [render.Image(src = img, height = 32)], + ), + ) + else: + message = "Invalid image path" + if debug_output: + print("Invalid image path") + print(decoded_json) + failure = True + return get_image(base_url, api_url, response_path, api_headers, debug_output) else: - if DEBUG: - print("Invalid path for image") + message = "Something went wrong." + if debug_output: + print("Status failed") print(decoded_json) failure = True - return get_image(base_url, api_url, response_path, api_headers) else: - if DEBUG: - print("Status failed") - print(decoded_json) + message = "Something went wrong. Check header values." + if debug_output: + print(message) failure = True + if message == "": + message = "Could not get image" + + row = render.Row(children = []) + if debug_output == True: + row = render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [ + render.WrappedText(content = message, font = "5x8"), + ], + ) + return render.Root( child = render.Box( - # render.Row( - # expanded=True, - # main_align="space_evenly", - # cross_align="center", - # children = [ - # render.WrappedText(content = "Could not get image", font = "5x8"), - # ], - # ), + row, ), ) -def get_cached(url, headerMap = {}, ttl_seconds = 20): +def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): data = cache.get(url) if data: return data @@ -142,15 +164,16 @@ def get_cached(url, headerMap = {}, ttl_seconds = 20): res = http.get(url, headers = headerMap) if res.status_code != 200: - if DEBUG: + if debug_output: print("status %d from %s: %s" % (res.status_code, url, res.body())) - fail("status %d from %s: %s" % (res.status_code, url, res.body())) + else: + data = res.body() - data = res.body() + cache.set(url, data, ttl_seconds = ttl_seconds) - cache.set(url, data, ttl_seconds = ttl_seconds) + return data - return data + return None def get_schema(): return schema.Schema( @@ -186,5 +209,12 @@ def get_schema(): icon = "", default = "", ), + schema.Toggle( + id = "debug_output", + name = "Toggle debug messages", + desc = "Toggle debug message output.", + icon = "", + default = False, + ), ], ) From 5fddd109fbc4913491c1e390d4404a539d8ccfce Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sat, 21 Sep 2024 21:26:29 -0700 Subject: [PATCH 16/49] Fixed infinite loop bug --- apps/apiimage/api_image.star | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 86b81ed77..fc0b21975 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -120,7 +120,8 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): print("Invalid image path") print(decoded_json) failure = True - return get_image(base_url, api_url, response_path, api_headers, debug_output) + # return get_image(base_url, api_url, response_path, api_headers, debug_output) + else: message = "Something went wrong." if debug_output: @@ -128,7 +129,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): print(decoded_json) failure = True else: - message = "Something went wrong. Check header values." + message = "Something went wrong. Check URL and header values." if debug_output: print(message) failure = True From 7403f4647c5bcbb679c8f935f0928cb786af45c6 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 09:09:50 -0700 Subject: [PATCH 17/49] Added support for image types --- apps/apiimage/api_image.star | 129 ++++++++++++++++++----------------- 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index fc0b21975..4847ab1b0 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -51,83 +51,89 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() - json_body = get_cached(api_url, debug_output, headerMap) + output_body = get_cached(api_url, debug_output, headerMap) - if json_body != None: - decoded_json = json.decode(json_body) + if output_body != None and type(output_body) == "string": + output = json.decode(output_body, None) if debug_output: print("Decoded JSON") - print(decoded_json) + print(output) - if decoded_json.get("status") == "fail": - failure = True - - if failure == False or decoded_json != "" or response_path != []: - responsePathArray = response_path + if failure == False or output_body != "": + if response_path != "": + responsePathArray = response_path - responsePathArray = responsePathArray.split(",") + responsePathArray = responsePathArray.split(",") - for item in responsePathArray: - item = item.strip() - if item.isdigit(): - item = int(item) + for item in responsePathArray: + item = item.strip() + if item.isdigit(): + item = int(item) - if debug_output: - print("item") - print(item) - print(type(decoded_json)) - - if (type(decoded_json) == "dict" and decoded_json.get(item) == None) or (type(decoded_json) == "list" and decoded_json[item] == None): - failure = True - message = "Response path invalid. " + item + " does not exist" if debug_output: - print("responsePathArray invalid. " + item + " does not exist") - break - else: - decoded_json = decoded_json[item] - - if type(decoded_json) == "string" and failure == False: - if decoded_json.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): - failure = True - message = "Base URL missing" + print("item") + print(item) + print(type(output)) + + if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and output[item] == None): + failure = True + message = "Response path invalid. " + item + " does not exist" + if debug_output: + print("responsePathArray invalid. " + item + " does not exist") + break + elif output != None: + output = output[item] + + if failure == False: + img = None + if output != None and failure == False: if debug_output: - print("Invalide URL. Requires a base_url") + print("JSON from URL") + + if output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + failure = True + message = "Base URL missing" + if debug_output: + print("Invalide URL. Requires a base_url") - else: - if base_url != "": - url = base_url + decoded_json else: - url = decoded_json + if base_url != "": + url = base_url + output + else: + url = output - img = get_cached(url, debug_output) + img = get_cached(url, debug_output) + if debug_output: + print("URL: " + url) + + else: if debug_output: - print("URL: " + url) - - if img != None: - return render.Root( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [render.Image(src = img, height = 32)], - ), - ) - else: - message = "Invalid image path" - if debug_output: - print("Invalid image path") - print(decoded_json) - failure = True - # return get_image(base_url, api_url, response_path, api_headers, debug_output) + print("Image from URL") + img = output_body + + if img != None: + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [render.Image(src = img, height = 32)], + ), + ) + else: + failure = True + message = "Invalid image" else: - message = "Something went wrong." + message = "Invalid image path" if debug_output: - print("Status failed") - print(decoded_json) + print("Invalid image path") + print(output) failure = True + # return get_image(base_url, api_url, response_path, api_headers, debug_output) + else: message = "Something went wrong. Check URL and header values." if debug_output: @@ -140,11 +146,10 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): row = render.Row(children = []) if debug_output == True: row = render.Row( - expanded = True, main_align = "space_evenly", cross_align = "center", children = [ - render.WrappedText(content = message, font = "5x8"), + render.WrappedText(content = message, font = "tom-thumb"), ], ) @@ -190,14 +195,14 @@ def get_schema(): schema.Text( id = "api_url", name = "URL", - desc = "The API url.", + desc = "The API url. Supports JSON or image types.", icon = "", default = "", # default = "https://dog.ceo/api/breeds/image/random", ), schema.Text( id = "response_path", - name = "Response path", + name = "JSON response path", desc = "A comma separated path to the image in the response JSON. eg. `json_key1, 2, key_to_image_url`", icon = "", default = "", From eff3615db553a7b1c25c2381313d0463cdf720e8 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 09:20:44 -0700 Subject: [PATCH 18/49] Check if base URL needed --- apps/apiimage/api_image.star | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 4847ab1b0..e524d5f35 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -98,7 +98,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): print("Invalide URL. Requires a base_url") else: - if base_url != "": + if output.startswith("http") == False and base_url != "": url = base_url + output else: url = output @@ -203,7 +203,7 @@ def get_schema(): schema.Text( id = "response_path", name = "JSON response path", - desc = "A comma separated path to the image in the response JSON. eg. `json_key1, 2, key_to_image_url`", + desc = "A comma separated path to the image URL in the response JSON. eg. `json_key1, 2, key_to_image_url`", icon = "", default = "", # default = "message", From 3b32f969b9a2b18d93aab8125b128c449aec7ed1 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 09:26:58 -0700 Subject: [PATCH 19/49] Message cleanup --- apps/apiimage/api_image.star | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index e524d5f35..df52a17a2 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -93,9 +93,9 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): if output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): failure = True - message = "Base URL missing" + message = "Base URL required" if debug_output: - print("Invalide URL. Requires a base_url") + print("Invalid URL. Requires a base_url") else: if output.startswith("http") == False and base_url != "": @@ -122,14 +122,11 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): children = [render.Image(src = img, height = 32)], ), ) - else: - failure = True - message = "Invalid image" else: - message = "Invalid image path" + message = "Invalid image URL" if debug_output: - print("Invalid image path") + print(message) print(output) failure = True # return get_image(base_url, api_url, response_path, api_headers, debug_output) From 6c3a4df4167e34a24e692f121ff012d197937074 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 11:12:39 -0700 Subject: [PATCH 20/49] Added fit to screen option --- apps/apiimage/api_image.star | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index df52a17a2..97d89fa6e 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -17,6 +17,7 @@ def main(config): response_path = config.get("response_path", "") api_headers = config.get("api_headers", "") debug_output = config.bool("debug_output", False) + fit_screen = config.bool("fit_screen", False) if debug_output: print("api_url") @@ -27,10 +28,12 @@ def main(config): print(api_headers) print("debug_output") print(debug_output) + print("fit_screen") + print(fit_screen) - return get_image(base_url, api_url, response_path, api_headers, debug_output) + return get_image(base_url, api_url, response_path, api_headers, debug_output, fit_screen) -def get_image(base_url, api_url, response_path, api_headers, debug_output): +def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_screen): failure = False message = "" @@ -114,12 +117,23 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output): img = output_body if img != None: + imgRender = render.Image( + src = img, + height = 32, + ) + + if fit_screen == True: + imgRender = render.Image( + src = img, + width = 64, + ) + return render.Root( render.Row( expanded = True, main_align = "space_evenly", cross_align = "center", - children = [render.Image(src = img, height = 32)], + children = [imgRender], ), ) @@ -212,6 +226,13 @@ def get_schema(): icon = "", default = "", ), + schema.Toggle( + id = "fit_screen", + name = "Fit screen", + desc = "Fit image on screen.", + icon = "", + default = False, + ), schema.Toggle( id = "debug_output", name = "Toggle debug messages", From ccf1d8ace42b11408d044d2faa360c0dd44713a9 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 11:26:16 -0700 Subject: [PATCH 21/49] Reordered schema --- apps/apiimage/api_image.star | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 97d89fa6e..70dc25175 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -197,19 +197,19 @@ def get_schema(): version = "1", fields = [ schema.Text( - id = "base_url", - name = "Base URL", - desc = "The base URL if URLs are relative paths.", + id = "api_url", + name = "URL", + desc = "The API URL. Supports JSON or image types.", icon = "", default = "", + # default = "https://dog.ceo/api/breeds/image/random", ), schema.Text( - id = "api_url", - name = "URL", - desc = "The API url. Supports JSON or image types.", + id = "base_url", + name = "Base URL", + desc = "The base URL if response JSON contain relative paths.", icon = "", default = "", - # default = "https://dog.ceo/api/breeds/image/random", ), schema.Text( id = "response_path", From 45f4bbd51f83231ae2e30aff15e68bbaf9d01339 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 17:28:19 -0700 Subject: [PATCH 22/49] Removed direct imageURL support --- apps/apiimage/api_image.star | 52 +++++++++++++++++------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 70dc25175..7beb362c6 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -89,7 +89,6 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s output = output[item] if failure == False: - img = None if output != None and failure == False: if debug_output: print("JSON from URL") @@ -111,31 +110,30 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if debug_output: print("URL: " + url) - else: - if debug_output: - print("Image from URL") - img = output_body - - if img != None: - imgRender = render.Image( - src = img, - height = 32, - ) - - if fit_screen == True: - imgRender = render.Image( - src = img, - width = 64, - ) - - return render.Root( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [imgRender], - ), - ) + if img != None: + imgRender = render.Image( + src = img, + height = 32, + ) + + if fit_screen == True: + imgRender = render.Image( + src = img, + width = 64, + ) + + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [imgRender], + ), + ) + + else: # Only supports JSON responses + message = "No JSON response detected" + failure = True else: message = "Invalid image URL" @@ -199,7 +197,7 @@ def get_schema(): schema.Text( id = "api_url", name = "URL", - desc = "The API URL. Supports JSON or image types.", + desc = "The API URL. Only supports JSON responses.", icon = "", default = "", # default = "https://dog.ceo/api/breeds/image/random", From a4c2f04334c08f9e9aefba2e91e0ee86ba8e2b40 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 18:18:02 -0700 Subject: [PATCH 23/49] Readded direct image URLs --- apps/apiimage/api_image.star | 52 +++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 7beb362c6..70dc25175 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -89,6 +89,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s output = output[item] if failure == False: + img = None if output != None and failure == False: if debug_output: print("JSON from URL") @@ -110,30 +111,31 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if debug_output: print("URL: " + url) - if img != None: - imgRender = render.Image( - src = img, - height = 32, - ) - - if fit_screen == True: - imgRender = render.Image( - src = img, - width = 64, - ) - - return render.Root( - render.Row( - expanded = True, - main_align = "space_evenly", - cross_align = "center", - children = [imgRender], - ), - ) - - else: # Only supports JSON responses - message = "No JSON response detected" - failure = True + else: + if debug_output: + print("Image from URL") + img = output_body + + if img != None: + imgRender = render.Image( + src = img, + height = 32, + ) + + if fit_screen == True: + imgRender = render.Image( + src = img, + width = 64, + ) + + return render.Root( + render.Row( + expanded = True, + main_align = "space_evenly", + cross_align = "center", + children = [imgRender], + ), + ) else: message = "Invalid image URL" @@ -197,7 +199,7 @@ def get_schema(): schema.Text( id = "api_url", name = "URL", - desc = "The API URL. Only supports JSON responses.", + desc = "The API URL. Supports JSON or image types.", icon = "", default = "", # default = "https://dog.ceo/api/breeds/image/random", From d7971838f95b1eb17ef6488eb4c3fb24d7dc9d7c Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 19:51:55 -0700 Subject: [PATCH 24/49] Checking headers for content type --- apps/apiimage/api_image.star | 61 ++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 16 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 70dc25175..fff00ff81 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -58,6 +58,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if output_body != None and type(output_body) == "string": output = json.decode(output_body, None) + responsePathArray = [] if debug_output: print("Decoded JSON") @@ -90,26 +91,32 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if failure == False: img = None - if output != None and failure == False: - if debug_output: - print("JSON from URL") - - if output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): - failure = True - message = "Base URL required" + if output != None: + if len(responsePathArray) > 0: if debug_output: - print("Invalid URL. Requires a base_url") + print("JSON from URL") + + if output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + failure = True + message = "Base URL required" + if debug_output: + print("Invalid URL. Requires a base_url") - else: - if output.startswith("http") == False and base_url != "": - url = base_url + output else: - url = output + if output.startswith("http") == False and base_url != "": + url = base_url + output + else: + url = output - img = get_cached(url, debug_output) + img = get_cached(url, debug_output) + if debug_output: + print("URL: " + url) + else: + message = "Missing path for JSON" if debug_output: - print("URL: " + url) + print(message) + failure = True else: if debug_output: @@ -180,9 +187,31 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): else: res = http.get(url, headers = headerMap) - if res.status_code != 200: + headers = res.headers + isValidType = False + + if headers != None and (headers.get("Content-Type") != None or headers.get("content-type") != None or headers.get("CONTENT-TYPE") != None): + contentType = headers.get("Content-Type") + if contentType == None: + contentType = headers.get("content-type") + if contentType == None: + contentType = headers.get("CONTENT-TYPE") + + if contentType.find("json") != -1 or contentType.find("image") != -1: + isValidType = True + + if debug_output: + print("isValidType") + print(isValidType) + + if res.status_code != 200 or isValidType == False: if debug_output: - print("status %d from %s: %s" % (res.status_code, url, res.body())) + print("status ") + print(res.status_code) + print("url") + print(url) + print("isValidType") + print(isValidType) else: data = res.body() From 490fa77dfd6c453cfab6a64a472a0735bf3f2153 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 20:13:02 -0700 Subject: [PATCH 25/49] Added more checks for valid paths --- apps/apiimage/api_image.star | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index fff00ff81..6ad4feaa9 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -80,13 +80,19 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s print(item) print(type(output)) - if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and output[item] == None): + if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and output[item] == None) or type(output) == "string": failure = True message = "Response path invalid. " + item + " does not exist" if debug_output: print("responsePathArray invalid. " + item + " does not exist") break - elif output != None: + elif output != None and (type(output) == "string" or (type(output) == "dict" and output.get(item) == None)): + failure = True + message = "Response path invalid. " + item + " does not exist" + if debug_output: + print("responsePathArray invalid. " + item + " does not exist") + break + elif output != None and output.get(item) != None: output = output[item] if failure == False: @@ -96,13 +102,12 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if debug_output: print("JSON from URL") - if output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): + if type(output) == "string" and output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): failure = True message = "Base URL required" if debug_output: print("Invalid URL. Requires a base_url") - - else: + elif type(output) == "string": if output.startswith("http") == False and base_url != "": url = base_url + output else: @@ -112,6 +117,11 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if debug_output: print("URL: " + url) + else: + message = "Bad path for JSON" + if debug_output: + print(message) + failure = True else: message = "Missing path for JSON" if debug_output: From 829adfb0584d02e040b54c09c65a3c7bfba07b07 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 20:19:50 -0700 Subject: [PATCH 26/49] Added more checks for valid paths --- apps/apiimage/api_image.star | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 6ad4feaa9..66f59bd0c 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -82,9 +82,9 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and output[item] == None) or type(output) == "string": failure = True - message = "Response path invalid. " + item + " does not exist" + message = "Response path invalid. " + str(item) + " does not exist" if debug_output: - print("responsePathArray invalid. " + item + " does not exist") + print("responsePathArray invalid. " + str(item) + " does not exist") break elif output != None and (type(output) == "string" or (type(output) == "dict" and output.get(item) == None)): failure = True From 9c526296ca006f342ec1fed6819729aa45467fc2 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 20:54:37 -0700 Subject: [PATCH 27/49] Cleaning up messages --- apps/apiimage/api_image.star | 45 +++++++++++++----------------------- 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 66f59bd0c..6ea86f66b 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -20,16 +20,11 @@ def main(config): fit_screen = config.bool("fit_screen", False) if debug_output: - print("api_url") - print(api_url) - print("response_path") - print(response_path) - print("api_headers") - print(api_headers) - print("debug_output") - print(debug_output) - print("fit_screen") - print(fit_screen) + print("api_url: " + api_url) + print("response_path: " + response_path) + print("api_headers: " + api_headers) + print("debug_output: " + str(debug_output)) + print("fit_screen: " + str(fit_screen)) return get_image(base_url, api_url, response_path, api_headers, debug_output, fit_screen) @@ -42,7 +37,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s message = "API URL must not be blank" if debug_output: - print("api_url must not be blank.") + print(message) else: headerMap = {} @@ -61,8 +56,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s responsePathArray = [] if debug_output: - print("Decoded JSON") - print(output) + print("Decoded JSON: " + str(output)) if failure == False or output_body != "": if response_path != "": @@ -76,9 +70,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s item = int(item) if debug_output: - print("item") - print(item) - print(type(output)) + print("path array item: " + str(item) + " - type " + str(type(output))) if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and output[item] == None) or type(output) == "string": failure = True @@ -88,9 +80,9 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s break elif output != None and (type(output) == "string" or (type(output) == "dict" and output.get(item) == None)): failure = True - message = "Response path invalid. " + item + " does not exist" + message = "Response path invalid. " + str(item) + " does not exist" if debug_output: - print("responsePathArray invalid. " + item + " does not exist") + print("responsePathArray invalid. " + str(item) + " does not exist") break elif output != None and output.get(item) != None: output = output[item] @@ -100,7 +92,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if output != None: if len(responsePathArray) > 0: if debug_output: - print("JSON from URL") + print("Response type JSON from URL") if type(output) == "string" and output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): failure = True @@ -116,7 +108,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s img = get_cached(url, debug_output) if debug_output: - print("URL: " + url) + print("Image URL: " + url) else: message = "Bad path for JSON" if debug_output: @@ -130,7 +122,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s else: if debug_output: - print("Image from URL") + print("Response type image from URL") img = output_body if img != None: @@ -211,17 +203,12 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): isValidType = True if debug_output: - print("isValidType") - print(isValidType) + print("isValidType: " + str(isValidType)) if res.status_code != 200 or isValidType == False: if debug_output: - print("status ") - print(res.status_code) - print("url") - print(url) - print("isValidType") - print(isValidType) + print("status: " + str(res.status_code)) + print("Requested url: " + str(url)) else: data = res.body() From f2599086a9c7dcde6468e37212b7934f506dbd9f Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Sun, 22 Sep 2024 21:23:39 -0700 Subject: [PATCH 28/49] Better way of checking headers --- apps/apiimage/api_image.star | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 6ea86f66b..f4b75f95c 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -192,12 +192,11 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): headers = res.headers isValidType = False - if headers != None and (headers.get("Content-Type") != None or headers.get("content-type") != None or headers.get("CONTENT-TYPE") != None): - contentType = headers.get("Content-Type") - if contentType == None: - contentType = headers.get("content-type") - if contentType == None: - contentType = headers.get("CONTENT-TYPE") + headersStr = str(headers) + headersStr = headersStr.lower() + headers = json.decode(headersStr, None) + if headers != None and headers.get("content-type") != None: + contentType = headers.get("content-type") if contentType.find("json") != -1 or contentType.find("image") != -1: isValidType = True From 399e9ae04c8ca45e33d11fc6ff67b55074a55b81 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 07:31:19 -0700 Subject: [PATCH 29/49] Clarified debug messages --- apps/apiimage/api_image.star | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index f4b75f95c..6b671d7f2 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -92,7 +92,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s if output != None: if len(responsePathArray) > 0: if debug_output: - print("Response type JSON from URL") + print("Response content type JSON") if type(output) == "string" and output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): failure = True @@ -122,7 +122,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s else: if debug_output: - print("Response type image from URL") + print("Response content type image") img = output_body if img != None: @@ -190,7 +190,7 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): res = http.get(url, headers = headerMap) headers = res.headers - isValidType = False + isValidContentType = False headersStr = str(headers) headersStr = headersStr.lower() @@ -199,12 +199,12 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): contentType = headers.get("content-type") if contentType.find("json") != -1 or contentType.find("image") != -1: - isValidType = True + isValidContentType = True if debug_output: - print("isValidType: " + str(isValidType)) + print("isValidContentType: " + str(isValidContentType)) - if res.status_code != 200 or isValidType == False: + if res.status_code != 200 or isValidContentType == False: if debug_output: print("status: " + str(res.status_code)) print("Requested url: " + str(url)) From cee5841daa1274be0f7655b69002b02442f40d75 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 07:33:04 -0700 Subject: [PATCH 30/49] Clarified debug messages --- apps/apiimage/api_image.star | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 6b671d7f2..a439dc283 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -20,11 +20,11 @@ def main(config): fit_screen = config.bool("fit_screen", False) if debug_output: - print("api_url: " + api_url) - print("response_path: " + response_path) - print("api_headers: " + api_headers) - print("debug_output: " + str(debug_output)) - print("fit_screen: " + str(fit_screen)) + print("CONFIG - api_url: " + api_url) + print("CONFIG - response_path: " + response_path) + print("CONFIG - api_headers: " + api_headers) + print("CONFIG - debug_output: " + str(debug_output)) + print("CONFIG - fit_screen: " + str(fit_screen)) return get_image(base_url, api_url, response_path, api_headers, debug_output, fit_screen) From 392b42108ef5816c7bf8bb450443853152a65a5f Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 07:40:27 -0700 Subject: [PATCH 31/49] Renamed api_headers variable to request_headers for clarity --- apps/apiimage/api_image.star | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index a439dc283..ef47e5464 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -15,20 +15,20 @@ def main(config): base_url = config.str("base_url", "") api_url = config.str("api_url", "") response_path = config.get("response_path", "") - api_headers = config.get("api_headers", "") + request_headers = config.get("request_headers", "") debug_output = config.bool("debug_output", False) fit_screen = config.bool("fit_screen", False) if debug_output: print("CONFIG - api_url: " + api_url) print("CONFIG - response_path: " + response_path) - print("CONFIG - api_headers: " + api_headers) + print("CONFIG - request_headers: " + request_headers) print("CONFIG - debug_output: " + str(debug_output)) print("CONFIG - fit_screen: " + str(fit_screen)) - return get_image(base_url, api_url, response_path, api_headers, debug_output, fit_screen) + return get_image(base_url, api_url, response_path, request_headers, debug_output, fit_screen) -def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_screen): +def get_image(base_url, api_url, response_path, request_headers, debug_output, fit_screen): failure = False message = "" @@ -41,10 +41,10 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s else: headerMap = {} - if api_headers != "" or api_headers != {}: - api_headers_array = api_headers.split(",") + if request_headers != "" or request_headers != {}: + request_headers_array = request_headers.split(",") - for app_header in api_headers_array: + for app_header in request_headers_array: headerKeyValueArray = app_header.split(":") if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() @@ -152,7 +152,7 @@ def get_image(base_url, api_url, response_path, api_headers, debug_output, fit_s print(message) print(output) failure = True - # return get_image(base_url, api_url, response_path, api_headers, debug_output) + # return get_image(base_url, api_url, response_path, request_headers, debug_output) else: message = "Something went wrong. Check URL and header values." @@ -245,7 +245,7 @@ def get_schema(): # default = "message", ), schema.Text( - id = "api_headers", + id = "request_headers", name = "Request headers", desc = "Comma separated key:value pairs to build the request headers. eg, `x-api-key:abc123,content-type:application/json`", icon = "", From 3df513daaf924d6d5410e7eca2b247997f95f289 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 08:40:51 -0700 Subject: [PATCH 32/49] Don't print the JSON string --- apps/apiimage/api_image.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index ef47e5464..8fe6ffc14 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -56,7 +56,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f responsePathArray = [] if debug_output: - print("Decoded JSON: " + str(output)) + print("Decoded JSON length: " + str(len(str(output)))) if failure == False or output_body != "": if response_path != "": From 9d77fd013ab97388d3f21957676bfc86ac1f1bae Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 10:38:32 -0700 Subject: [PATCH 33/49] Updated debug message --- apps/apiimage/api_image.star | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 8fe6ffc14..0e8449b63 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -20,6 +20,7 @@ def main(config): fit_screen = config.bool("fit_screen", False) if debug_output: + print("------------------------------") print("CONFIG - api_url: " + api_url) print("CONFIG - response_path: " + response_path) print("CONFIG - request_headers: " + request_headers) @@ -202,7 +203,7 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): isValidContentType = True if debug_output: - print("isValidContentType: " + str(isValidContentType)) + print("isValidContentType for "+url+": " + str(isValidContentType)) if res.status_code != 200 or isValidContentType == False: if debug_output: From c383410cfa6a90c8f8530643747de5be17bae4d8 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 10:41:34 -0700 Subject: [PATCH 34/49] Updated debug message --- apps/apiimage/api_image.star | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 0e8449b63..82d410965 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -56,9 +56,6 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f output = json.decode(output_body, None) responsePathArray = [] - if debug_output: - print("Decoded JSON length: " + str(len(str(output)))) - if failure == False or output_body != "": if response_path != "": responsePathArray = response_path @@ -94,6 +91,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if len(responsePathArray) > 0: if debug_output: print("Response content type JSON") + print("Decoded JSON length: " + str(len(str(output)))) if type(output) == "string" and output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): failure = True From b476bd5d834a63ec168f97e55335efa34ed7dba0 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 10:46:07 -0700 Subject: [PATCH 35/49] Added content type debug message --- apps/apiimage/api_image.star | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 82d410965..4b5828674 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -194,6 +194,7 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): headersStr = str(headers) headersStr = headersStr.lower() headers = json.decode(headersStr, None) + contentType = "" if headers != None and headers.get("content-type") != None: contentType = headers.get("content-type") @@ -201,7 +202,7 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): isValidContentType = True if debug_output: - print("isValidContentType for "+url+": " + str(isValidContentType)) + print("isValidContentType for " + url + " content type " + contentType + ": " + str(isValidContentType)) if res.status_code != 200 or isValidContentType == False: if debug_output: From 63236c76704d20b67364b5f00d3595e7222f4341 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 13:41:42 -0700 Subject: [PATCH 36/49] Added convenience function when in debug mode --- apps/apiimage/api_image.star | 46 +++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 4b5828674..8249451bb 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -107,7 +107,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f img = get_cached(url, debug_output) if debug_output: - print("Image URL: " + url) + print("Image URL: " + convert_text(url)) else: message = "Bad path for JSON" if debug_output: @@ -178,6 +178,50 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f ), ) +def convert_text(text): + t = text + + specChars = { + "!": "%21", + '"': "%22", + "#": "%23", + "$": "%24", + "%": "%25", + "&": "%26", + "'": "%27", + "(": "%28", + ")": "%29", + "*": "%2A", + "+": "%2B", + ",": "%2C", + "-": "%2D", + ".": "%2E", + "/": "%2F", + ":": "%3A", + ";": "%3B", + "<": "%3C", + "=": "%3D", + ">": "%3E", + "?": "%3F", + "@": "%40", + "[": "%5B", + "\\": "%5C", + "]": "%5D", + "^": "%5E", + "_": "%5F", + "`": "%60", + "{": "%7B", + "|": "%7C", + "}": "%7D", + "~": "%7E", + " ": "%20", + } + + for specChar in specChars: + t = text.replace(specChar, specChars[specChar]) + + return t + def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): data = cache.get(url) if data: From 5055a64800898d30aaa225e7b95ff286386d6844 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Mon, 23 Sep 2024 14:04:49 -0700 Subject: [PATCH 37/49] Renamed config --- apps/apiimage/api_image.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 8249451bb..a479a9717 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -267,7 +267,7 @@ def get_schema(): fields = [ schema.Text( id = "api_url", - name = "URL", + name = "API URL", desc = "The API URL. Supports JSON or image types.", icon = "", default = "", From 57e48fcef9876b83a19cb20ac862d4b8b1f9fa3a Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Tue, 24 Sep 2024 06:41:25 -0700 Subject: [PATCH 38/49] Truncated json in debug output --- apps/apiimage/api_image.star | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index a479a9717..6661dee39 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -22,6 +22,7 @@ def main(config): if debug_output: print("------------------------------") print("CONFIG - api_url: " + api_url) + print("CONFIG - base_url: " + base_url) print("CONFIG - response_path: " + response_path) print("CONFIG - request_headers: " + request_headers) print("CONFIG - debug_output: " + str(debug_output)) @@ -57,6 +58,19 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f responsePathArray = [] if failure == False or output_body != "": + if debug_output: + outputStr = str(output) + outputLen = len(outputStr) + if outputLen >= 200: + outputLen = 200 + + outputStr = outputStr[0:outputLen] + if outputLen >= 200: + outputStr = outputStr + "..." + print("Decoded JSON truncated: " + outputStr) + else: + print("Decoded JSON: " + outputStr) + if response_path != "": responsePathArray = response_path @@ -91,7 +105,6 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if len(responsePathArray) > 0: if debug_output: print("Response content type JSON") - print("Decoded JSON length: " + str(len(str(output)))) if type(output) == "string" and output.startswith("http") == False and (base_url == "" or base_url.startswith("http") == False): failure = True From 1723e4a071c613c953e6c96baf700268a3a99ad1 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Tue, 24 Sep 2024 07:20:04 -0700 Subject: [PATCH 39/49] Updated schema --- apps/apiimage/api_image.star | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 6661dee39..3aab9e3f8 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -289,14 +289,14 @@ def get_schema(): schema.Text( id = "base_url", name = "Base URL", - desc = "The base URL if response JSON contain relative paths.", + desc = "The base URL if response JSON contains relative paths.", icon = "", default = "", ), schema.Text( id = "response_path", name = "JSON response path", - desc = "A comma separated path to the image URL in the response JSON. eg. `json_key1, 2, key_to_image_url`", + desc = "A comma separated path to the image URL in the response JSON. eg. `json_key_1, 2, json_key_to_image_url`", icon = "", default = "", # default = "message", @@ -318,7 +318,7 @@ def get_schema(): schema.Toggle( id = "debug_output", name = "Toggle debug messages", - desc = "Toggle debug message output.", + desc = "Toggle debug messages. Will display the messages on the display if enabled.", icon = "", default = False, ), From b228bbdda4acecbce1c30405f8c8bdb4649d032e Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Tue, 24 Sep 2024 18:58:36 -0700 Subject: [PATCH 40/49] Refactoring --- apps/apiimage/api_image.star | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 3aab9e3f8..2cba3e27d 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -1,7 +1,7 @@ """ Applet: API image Summary: API image display -Description: Display an image from an endpoint. +Description: Display an image from an API endpoint. Author: Michael Yagi """ @@ -57,7 +57,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f output = json.decode(output_body, None) responsePathArray = [] - if failure == False or output_body != "": + if output_body != "": if debug_output: outputStr = str(output) outputLen = len(outputStr) @@ -101,6 +101,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if failure == False: img = None + if output != None: if len(responsePathArray) > 0: if debug_output: From e10bba8c227e4f6a43947a459ed9ecfe49d921c9 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Tue, 24 Sep 2024 20:04:03 -0700 Subject: [PATCH 41/49] Clarified error message --- apps/apiimage/api_image.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 2cba3e27d..e06426a1a 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -168,7 +168,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f # return get_image(base_url, api_url, response_path, request_headers, debug_output) else: - message = "Something went wrong. Check URL and header values." + message = "Oops! Check URL and header values. URL must return JSON or image." if debug_output: print(message) failure = True From d36dcb13c5450819b1f823e74ae2045455eadaf8 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Tue, 24 Sep 2024 20:29:32 -0700 Subject: [PATCH 42/49] Clarified error message --- apps/apiimage/api_image.star | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index e06426a1a..4978b700d 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -123,12 +123,12 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if debug_output: print("Image URL: " + convert_text(url)) else: - message = "Bad path for JSON" + message = "Bad response path for JSON" if debug_output: print(message) failure = True else: - message = "Missing path for JSON" + message = "Missing response path for JSON" if debug_output: print(message) failure = True From d219d9193c51606df60658f49e739849553ed2a9 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Tue, 24 Sep 2024 20:35:11 -0700 Subject: [PATCH 43/49] Clarified error message --- apps/apiimage/api_image.star | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 4978b700d..41c210921 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -123,7 +123,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if debug_output: print("Image URL: " + convert_text(url)) else: - message = "Bad response path for JSON" + message = "Bad response path for JSON. Must point to an image URL." if debug_output: print(message) failure = True From 20331a7b0bcf0d2ffd1461d3692b0239490880cf Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Wed, 25 Sep 2024 07:03:40 -0700 Subject: [PATCH 44/49] Additional checks for response path lists --- apps/apiimage/api_image.star | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 41c210921..a3da22401 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -84,7 +84,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if debug_output: print("path array item: " + str(item) + " - type " + str(type(output))) - if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and output[item] == None) or type(output) == "string": + if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and type(item) == "int" and (item > len(output) - 1 or output[item] == None)) or type(output) == "string": failure = True message = "Response path invalid. " + str(item) + " does not exist" if debug_output: @@ -96,7 +96,9 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if debug_output: print("responsePathArray invalid. " + str(item) + " does not exist") break - elif output != None and output.get(item) != None: + elif output != None and type(item) == "string" and output.get(item) != None: + output = output[item] + elif output != None and type(item) == "int" and output[item] != None: output = output[item] if failure == False: From 84a96304c1b4443fb5575e7a26759259c838fb08 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Wed, 25 Sep 2024 08:23:54 -0700 Subject: [PATCH 45/49] Simplified path checks --- apps/apiimage/api_image.star | 60 +++++++++++++++++------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index a3da22401..ece32d1a1 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -71,41 +71,36 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f else: print("Decoded JSON: " + outputStr) - if response_path != "": - responsePathArray = response_path - - responsePathArray = responsePathArray.split(",") - - for item in responsePathArray: - item = item.strip() - if item.isdigit(): - item = int(item) - - if debug_output: - print("path array item: " + str(item) + " - type " + str(type(output))) - - if (type(output) == "dict" and output.get(item) == None) or (type(output) == "list" and type(item) == "int" and (item > len(output) - 1 or output[item] == None)) or type(output) == "string": - failure = True - message = "Response path invalid. " + str(item) + " does not exist" - if debug_output: - print("responsePathArray invalid. " + str(item) + " does not exist") - break - elif output != None and (type(output) == "string" or (type(output) == "dict" and output.get(item) == None)): - failure = True - message = "Response path invalid. " + str(item) + " does not exist" - if debug_output: - print("responsePathArray invalid. " + str(item) + " does not exist") - break - elif output != None and type(item) == "string" and output.get(item) != None: - output = output[item] - elif output != None and type(item) == "int" and output[item] != None: - output = output[item] - if failure == False: img = None if output != None: - if len(responsePathArray) > 0: + if response_path != "": + # Parse response path for JSON + if response_path != "": + responsePathArray = response_path + + responsePathArray = responsePathArray.split(",") + + for item in responsePathArray: + item = item.strip() + if item.isdigit(): + item = int(item) + + if debug_output: + print("path array item: " + str(item) + " - type " + str(type(output))) + + if output != None and type(output) == "dict" and type(item) == "string" and output.get(item) != None: + output = output[item] + elif output != None and type(output) == "list" and type(item) == "int" and item <= len(output) - 1 and output[item] != None: + output = output[item] + else: + failure = True + message = "Response path invalid. " + str(item) + " does not exist" + if debug_output: + print("responsePathArray invalid. " + str(item) + " does not exist") + break + if debug_output: print("Response content type JSON") @@ -125,7 +120,8 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if debug_output: print("Image URL: " + convert_text(url)) else: - message = "Bad response path for JSON. Must point to an image URL." + if message == "": + message = "Bad response path for JSON. Must point to an image URL." if debug_output: print(message) failure = True From df765a9e6147b670d099115a3315a38fb8a5d85d Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Wed, 25 Sep 2024 09:22:55 -0700 Subject: [PATCH 46/49] Code cleanup --- apps/apiimage/api_image.star | 46 +----------------------------------- 1 file changed, 1 insertion(+), 45 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index ece32d1a1..d829e8e1e 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -118,7 +118,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f img = get_cached(url, debug_output) if debug_output: - print("Image URL: " + convert_text(url)) + print("Image URL: " + url) else: if message == "": message = "Bad response path for JSON. Must point to an image URL." @@ -190,50 +190,6 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f ), ) -def convert_text(text): - t = text - - specChars = { - "!": "%21", - '"': "%22", - "#": "%23", - "$": "%24", - "%": "%25", - "&": "%26", - "'": "%27", - "(": "%28", - ")": "%29", - "*": "%2A", - "+": "%2B", - ",": "%2C", - "-": "%2D", - ".": "%2E", - "/": "%2F", - ":": "%3A", - ";": "%3B", - "<": "%3C", - "=": "%3D", - ">": "%3E", - "?": "%3F", - "@": "%40", - "[": "%5B", - "\\": "%5C", - "]": "%5D", - "^": "%5E", - "_": "%5F", - "`": "%60", - "{": "%7B", - "|": "%7C", - "}": "%7D", - "~": "%7E", - " ": "%20", - } - - for specChar in specChars: - t = text.replace(specChar, specChars[specChar]) - - return t - def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): data = cache.get(url) if data: From 3167ab4a9f9e13ac024f59f9ea7d8753cd0379cd Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Wed, 25 Sep 2024 11:01:55 -0700 Subject: [PATCH 47/49] Moved TTL to get --- apps/apiimage/api_image.star | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index d829e8e1e..a5b3dd5f5 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -196,9 +196,9 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): return data if headerMap == {}: - res = http.get(url) + res = http.get(url, ttl_seconds = ttl_seconds) else: - res = http.get(url, headers = headerMap) + res = http.get(url, headers = headerMap, ttl_seconds = ttl_seconds) headers = res.headers isValidContentType = False @@ -223,7 +223,7 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): else: data = res.body() - cache.set(url, data, ttl_seconds = ttl_seconds) + cache.set(url, data) return data From 8cd3da2ab6a1910ab49346787ae46063d9e14dc5 Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Thu, 26 Sep 2024 07:04:18 -0700 Subject: [PATCH 48/49] Added output on cache hit --- apps/apiimage/api_image.star | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index a5b3dd5f5..309284699 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -193,6 +193,8 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): data = cache.get(url) if data: + if debug_output: + print("Retrieved content from cache") return data if headerMap == {}: From 39b85a278ed6ccd74d596ee57d0062ab1b74840f Mon Sep 17 00:00:00 2001 From: Michael Yagi Date: Thu, 26 Sep 2024 08:22:54 -0700 Subject: [PATCH 49/49] Removed cache module --- apps/apiimage/api_image.star | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/apiimage/api_image.star b/apps/apiimage/api_image.star index 309284699..09a7f8dce 100644 --- a/apps/apiimage/api_image.star +++ b/apps/apiimage/api_image.star @@ -5,7 +5,6 @@ Description: Display an image from an API endpoint. Author: Michael Yagi """ -load("cache.star", "cache") load("encoding/json.star", "json") load("http.star", "http") load("render.star", "render") @@ -51,7 +50,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f if len(headerKeyValueArray) > 1: headerMap[headerKeyValueArray[0].strip()] = headerKeyValueArray[1].strip() - output_body = get_cached(api_url, debug_output, headerMap) + output_body = get_data(api_url, debug_output, headerMap) if output_body != None and type(output_body) == "string": output = json.decode(output_body, None) @@ -115,7 +114,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f else: url = output - img = get_cached(url, debug_output) + img = get_data(url, debug_output) if debug_output: print("Image URL: " + url) @@ -190,13 +189,7 @@ def get_image(base_url, api_url, response_path, request_headers, debug_output, f ), ) -def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): - data = cache.get(url) - if data: - if debug_output: - print("Retrieved content from cache") - return data - +def get_data(url, debug_output, headerMap = {}, ttl_seconds = 20): if headerMap == {}: res = http.get(url, ttl_seconds = ttl_seconds) else: @@ -225,8 +218,6 @@ def get_cached(url, debug_output, headerMap = {}, ttl_seconds = 20): else: data = res.body() - cache.set(url, data) - return data return None