diff --git a/.gitignore b/.gitignore index ae5f52b..3f35213 100644 --- a/.gitignore +++ b/.gitignore @@ -508,4 +508,3 @@ fabric.properties # Android studio 3.1+ serialized cache file .idea/caches/build_file_checksums.ser -.vscode/settings.json diff --git a/addons/sammi/lib/sammi_api.gd b/addons/sammi/lib/sammi_api.gd deleted file mode 100644 index 7e3f008..0000000 --- a/addons/sammi/lib/sammi_api.gd +++ /dev/null @@ -1,408 +0,0 @@ -extends Node -class_name SammiAPI - -signal request_completed(response: ApiResponse) - -@export_category("SAMMI Connection Information") -@export var host: String = "127.0.0.1" -@export var port: int = 9450 -@export var password: String = "" - -var client: SammiClient -var last_error: String = "" -var last_error_description: String = "" - -func _ready() -> void: - client = SammiClient.new() - client.host = host - client.port = port - client.password = password - client.request_completed.connect(_on_request_completed) - -func get_variable(name: String, button_id: String = "") -> Variant: - var api_path: String = "/api?request=getVariable&name=%s" % name - if button_id != "": - api_path += "&button_id=%s" % button_id - client.request(SammiClient.Method.GET, api_path, "") - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.contains("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return res - else: - return res["data"] - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return null - -func set_variable(name: String, value: Variant, button_id) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "setVariable", - "name": name, - "value": value, - "button_id": button_id - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: Invalid JSON Returned. Body: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func delete_variable(name: String, button_id) -> bool: - var api_path: String = "/api" % name - var req: Dictionary = { - "request": "deleteVariable", - "name": name, - "button_id": button_id - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func insert_array(name: String, position: int, value: Variant, button_id: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "insertArray", - "name": name, - "position": position, - "value": value, - "button_id": button_id - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func delete_array(name: String, position: int, button_id: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "deleteArray", - "name": name, - "position": position, - "button_id": button_id - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func get_deck_status(deck_id: String) -> bool: - var api_path: String = "/api?request=getDeckStatus&deck_id=%s" % deck_id - client.request(SammiClient.Method.GET, api_path, "") - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - return true - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func change_deck_status(deck_id: String, status: int) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "changeDeckStatus", - "deck_id": deck_id, - "status": status - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func trigger_button(button_id: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "triggerButton", - "button_id": button_id - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func release_button(button_id: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "releaseButton", - "button_id": button_id - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func modify_button(button_id: String, text: String = "", color: int = -1, image: String = "", border: int = -1) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "modifyButton", - "button_id": button_id, - } - if text != "": - req["text"] = text - if color != -1: - req["color"] = color - if image != "": - req["image"] = image - if border != -1: - req["border"] = border - - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func popup_message(message: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "popupMessage", - "message": message - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func alert_message(message: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "alertMessage", - "message": message - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - -func notification_message(message: String, title: String) -> bool: - var api_path: String = "/api" - var req: Dictionary = { - "request": "notificationMessage", - "message": message, - "title": title - } - client.request(SammiClient.Method.POST, api_path, JSON.stringify(req)) - var response: SammiClient.SammiResponse = await client.request_completed - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("data") and res["data"] == "Ok.": - return true - elif res.has("error"): - push_error("Error: %s: %s" % [res["Error"], res["Description"]]) - last_error = res["Error"] - last_error_description = res["Description"] - return false - else: - push_error("Error: %s" % response.body) - last_error = "Invalid JSON Returned" - last_error_description = response.body - return false - else: - push_error("Error: %d: %s" % [response.code, response.error_message]) - last_error = "HTTP Error: %d" % response.code - last_error_description = response.error_message - return false - - -func _on_request_completed(response: SammiClient.SammiResponse) -> void: - var resp: ApiResponse = ApiResponse.new() - if response.code == 200: - var res := JSON.parse_string(response.body) - if res.has("error"): - resp.error = res["Error"] - resp.error_description = res["Description"] - else: - resp.data = res["data"] - else: - resp.error = "HTTP Error: %d" % response.code - resp.error_description = response.error_message - request_completed.emit(resp) - - -class ApiResponse: - var data: Variant - var error: String - var error_description: String diff --git a/addons/sammi/lib/sammi_api.gd.uid b/addons/sammi/lib/sammi_api.gd.uid deleted file mode 100644 index 0ae3236..0000000 --- a/addons/sammi/lib/sammi_api.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://btwsi3vi072ku diff --git a/addons/sammi/lib/sammi_client.gd b/addons/sammi/lib/sammi_client.gd deleted file mode 100644 index eb96d35..0000000 --- a/addons/sammi/lib/sammi_client.gd +++ /dev/null @@ -1,162 +0,0 @@ -extends Node -class_name SammiClient - -## Creates a HTTP Client connection to communicate with SAMMI. Due to current restrictions -## Godot expects Content-Length or transfer-enoding: chunked headers to be set properly, otherwise -## Godot assumes there is no body, and doesn't read it. SAMMI's custom internal HTTP Server does -## not set the Content-Length header for response headers to the API. Hence it will fail with a -## normal Godot HTTPClient. - -signal request_completed(response: SammiResponse) - -@export_category("SAMMI Connection Information") -@export var host: String = "127.0.0.1" -@export var port: int = 9450 -@export var user_agent: String = "GodotSammi/0.1 (%s)" % OS.get_name() -@export_category("Authentication") -@export var password: String = "" - -var client: StreamPeerTCP -var state: State = State.CLOSED -var buffer: PackedByteArray -var headers: PackedStringArray -var response: SammiResponse -var query: String = "" -var method: Method = Method.GET -var body: String = "" - -enum State { - CONNECTING, - REQUESTING, - RESPONSE, - ERROR, - CLOSED -} - -enum Method { - GET, - POST, -} - -func request(method: Method, api_path: String, body: String) -> void: - assert(state == State.CLOSED, "A request is in the process of being made.") - - self.query = api_path - self.body = body - self.client = StreamPeerTCP.new() - self.client.connect_to_host(host, port) - self.state = State.CONNECTING - -func _process(_delta: float) -> void: - if not client: - return - - if state == State.CLOSED: - client.disconnect_from_host() - client = null - return - - client.poll() - if client.get_status() == StreamPeerTCP.Status.STATUS_CONNECTED and state == State.CONNECTING: - state = State.REQUESTING - _send_request() - elif client.get_status() == StreamPeerTCP.Status.STATUS_CONNECTED and state == State.REQUESTING: - state = State.RESPONSE - _read_response() - elif client.get_status() == StreamPeerTCP.Status.STATUS_CONNECTED and state == State.RESPONSE: - _read_response() - elif client.get_status() == StreamPeerTCP.Status.STATUS_ERROR: - state = State.ERROR - print("Error: ", client.get_error()) - client.disconnect_from_host() - client = null - -func _send_request() -> void: - var request_str = "" - if method == Method.GET: - request_str = "GET %s HTTP/1.1\r\n" % query - else: - request_str = "POST %s HTTP/1.1\r\n" % query - - - request_str += "Host: %s:%d\r\n" % [host, port] - request_str += "User-Agent: %s\r\n" % user_agent - request_str += "Accept: */*\r\n" - if password != "": - request_str += "Authorization: %s\r\n" % password - if method == Method.POST and body != "": - request_str += "Content-Type: application/json\r\n" - request_str += "Content-Length: %d\r\n" % body.length() - - request_str += "\r\n" - - if method == Method.POST and body != "": - request_str += body - client.put_data(request_str.to_utf8_buffer()) - -func _read_response() -> void: - client.poll() - - if headers.size() == 0: - while true: - var byte := client.get_partial_data(1) - if byte[0] == OK and byte[1].size() == 0: - await get_tree().process_frame - client.poll() - continue - elif byte[0] == OK: - buffer.push_back(byte[1][0]) - else: - state = State.ERROR - print("Error reading response headers.") - return - - if buffer.size() < 4: - await get_tree().process_frame - client.poll() - continue - - if (buffer[-2] == 10 and buffer[-1] == 10) or \ - (buffer[-4] == 13 and buffer[-3] == 10 and buffer[-2] == 13 and buffer[-1] == 10): - var data := buffer.get_string_from_utf8() - buffer = [] - headers = data.replace("\r", "").rstrip("\n\n").split("\n") - break - await get_tree().process_frame - client.poll() - - if headers.size() == 0: - return - - var chunk := client.get_partial_data(1024) - if chunk[0] == OK and chunk[1].size() > 0: - buffer.append_array(chunk[1]) - else: - response = SammiResponse.new(headers, buffer, query) - request_completed.emit(response) - state = State.CLOSED - - -class SammiResponse: - var code: int - var headers: Dictionary - var body: String - var query: String - var error_message: String - - func _init(p_headers: PackedStringArray, p_buffer: PackedByteArray, p_query: String) -> void: - body = p_buffer.get_string_from_utf8() - headers = {} - for line in p_headers: - if line.contains(": "): - var parts := line.split(": ") - headers[parts[0]] = parts[1] - else: - var parts := Array(line.split(" ")) - if parts.pop_front() == "HTTP/1.1": - code = int(parts.pop_front()) - error_message = " ".join(parts) - else: - code = 500 - error_message = "Unknown Error" - query = p_query \ No newline at end of file diff --git a/addons/sammi/lib/sammi_client.gd.uid b/addons/sammi/lib/sammi_client.gd.uid deleted file mode 100644 index 9fd6eb7..0000000 --- a/addons/sammi/lib/sammi_client.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://bwhiwlbct7ijv diff --git a/addons/sammi/plugin.cfg b/addons/sammi/plugin.cfg deleted file mode 100644 index e90dada..0000000 --- a/addons/sammi/plugin.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[plugin] - -name="Sammi Plugin" -description="Plugin to connect to the API for Sammi (https://sammi.solutions)" -author="Mario Steele" -version="0.1" -script="plugin.gd" diff --git a/addons/sammi/plugin.gd b/addons/sammi/plugin.gd deleted file mode 100644 index aa1b8e0..0000000 --- a/addons/sammi/plugin.gd +++ /dev/null @@ -1,12 +0,0 @@ -@tool -extends EditorPlugin - - -func _enter_tree() -> void: - # Initialization of the plugin goes here. - pass - - -func _exit_tree() -> void: - # Clean-up of the plugin goes here. - pass diff --git a/addons/sammi/plugin.gd.uid b/addons/sammi/plugin.gd.uid deleted file mode 100644 index c276c27..0000000 --- a/addons/sammi/plugin.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://b0yib03xttmn8 diff --git a/http_client.gd b/http_client.gd deleted file mode 100644 index 2c1151f..0000000 --- a/http_client.gd +++ /dev/null @@ -1,52 +0,0 @@ -extends Node2D - - -# Called when the node enters the scene tree for the first time. -func _ready() -> void: - var client := HTTPClient.new() - var res = client.connect_to_host("127.0.0.1",9450) - - assert(res == OK) - - while client.get_status() == HTTPClient.STATUS_CONNECTING or client.get_status() == HTTPClient.STATUS_RESOLVING: - client.poll() - print("Connecting...") - await get_tree().process_frame - - assert(client.get_status() == HTTPClient.STATUS_CONNECTED) - - res = client.request(HTTPClient.METHOD_GET, "/api?request=getVariable&name=twitch_default_channel", []) - assert(res == OK) - - while client.get_status() == HTTPClient.STATUS_REQUESTING: - client.poll() - print("Requesting...") - await get_tree().process_frame - - assert(client.get_status() == HTTPClient.STATUS_BODY or client.get_status() == HTTPClient.STATUS_CONNECTED) - - print("response? ", client.has_response()) - - if client.has_response(): - var headers := client.get_response_headers_as_dictionary() - print("code: ", client.get_response_code()) - print("**headers:\\n", headers) - - if client.is_response_chunked(): - print("Response is Chunked!") - else: - var bl := client.get_response_body_length() - print("Response Length: ", bl) - var rb := PackedByteArray() - - while client.get_status() == HTTPClient.STATUS_BODY: - client.poll() - var chunk = client.read_response_body_chunk() - if chunk.size() == 0: - await get_tree().process_frame - else: - rb = rb + chunk - - print("bytes got: ", rb.size()) - var text = rb.get_string_from_ascii() - print("Text: ", text) diff --git a/http_client.gd.uid b/http_client.gd.uid deleted file mode 100644 index 6292e7e..0000000 --- a/http_client.gd.uid +++ /dev/null @@ -1 +0,0 @@ -uid://d18wt8smvaeid diff --git a/http_client.tscn b/http_client.tscn deleted file mode 100644 index c0bafa2..0000000 --- a/http_client.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://d247bxhjaip8h"] - -[ext_resource type="Script" uid="uid://d18wt8smvaeid" path="res://http_client.gd" id="1_4bxm2"] - -[node name="HttpClient" type="Node2D"] -script = ExtResource("1_4bxm2") diff --git a/project.godot b/project.godot index 8cf0fce..7e5a388 100644 --- a/project.godot +++ b/project.godot @@ -14,7 +14,3 @@ config/name="HttpClientDebugger" config/description="Enter an interesting project description here!" config/features=PackedStringArray("4.4") config/icon="res://icon.png" - -[editor_plugins] - -enabled=PackedStringArray("res://addons/sammi/plugin.cfg")