@tool class_name LanguageToolApiWrapper extends Node const BASE_URL := "https://api.languagetoolplus.com/v2" func _make_request(endpoint: String, method: HTTPClient.Method = HTTPClient.METHOD_GET, data: Dictionary = {}, headers: Dictionary = {}): var url = BASE_URL + endpoint var scheme_split = url.split("://") var scheme = scheme_split[0] var rest = scheme_split[1] var host_and_path = rest.split("/", false, 1) var host = host_and_path[0] var path = "/" + host_and_path[1] if host_and_path.size() > 1 else "/" var port = 443 if scheme == "https" else 80 var client = HTTPClient.new() var tlsOptions: TLSOptions = (TLSOptions.client() if scheme == "https" else null) var err = client.connect_to_host(host, port, tlsOptions) if err != OK: push_error("Failed to connect to host: " + str(err)) return null while client.get_status() in [HTTPClient.STATUS_CONNECTING, HTTPClient.STATUS_RESOLVING]: client.poll() OS.delay_msec(10) var header_array = [] for k in headers.keys(): header_array.append(str(k) + ": " + str(headers[k])) var body = "" if method == HTTPClient.METHOD_POST: body = "" if data.size() > 0: body = client.query_string_from_dict(data) header_array.append("Content-Type: application/x-www-form-urlencoded") header_array.append("Content-Length: " + str(body.length())) client.request(HTTPClient.METHOD_POST, path, header_array, body) else: if data.size() > 0: path += "?" + client.query_string_from_dict(data) client.request(HTTPClient.METHOD_GET, path, header_array) while client.get_status() == HTTPClient.STATUS_REQUESTING: client.poll() OS.delay_msec(10) var response = "" while client.get_status() == HTTPClient.STATUS_BODY or client.has_response(): client.poll() var chunk = client.read_response_body_chunk() if chunk.size() == 0: break response += chunk.get_string_from_utf8() OS.delay_msec(10) var resp_code = client.get_response_code() if resp_code != 200: push_error("HTTP error: " + str(resp_code) + "\\n" + response) return null var json = JSON.new() var json_err = json.parse(response) if json_err != OK: push_error("JSON parse error: " + str(json_err) + "\\n" + response) return null return json.get_data() func check(text: String, language: String = "auto", opts: Dictionary = {}) -> LanguageToolCheckResponse: var data = { "text": text, "language": language } for k in opts.keys(): data[k] = opts[k] print("Checking text: "+text) return LanguageToolCheckResponse.new(_make_request("/check", HTTPClient.METHOD_POST, data)) func get_languages(): return _make_request("/languages", HTTPClient.METHOD_GET) func list_words(username: String, apiKey: String, offset: int = 0, limit: int = 10, dicts: String = ""): var data = { "username": username, "apiKey": apiKey, "offset": offset, "limit": limit } if dicts != "": data["dicts"] = dicts return _make_request("/words", HTTPClient.METHOD_GET, data) func add_word(word: String, username: String, apiKey: String, dict: String = ""): var data = { "word": word, "username": username, "apiKey": apiKey } if dict != "": data["dict"] = dict return _make_request("/words/add", HTTPClient.METHOD_POST, data) func delete_word(word: String, username: String, apiKey: String, dict: String = ""): var data = { "word": word, "username": username, "apiKey": apiKey } if dict != "": data["dict"] = dict return _make_request("/words/delete", HTTPClient.METHOD_POST, data) static func percent_encode(text: String) -> String: return text.uri_encode() class LanguageToolCheckResponse: # Software info var software_name: String var software_version: String var software_build_date: String var software_api_version: int var software_status: String = "" var software_premium: bool = false # Language info var language_name: String var language_code: String var detected_language_name: String var detected_language_code: String # Match structure class Match: var message: String var short_message: String = "" var offset: int var length: int var replacements: Array[String] = [] var context_text: String var context_offset: int var context_length: int var sentence: String class Rule: var id: String var sub_id: String = "" var description: String var urls: Array[String] = [] var issue_type: String = "" class Category: var id: String var name: String var category: Category var rule: Rule var matches: Array[Match] = [] func _init(response: Variant) -> void: # Parse software var sw = response.software if response.has("software") else {} software_name = sw.name if sw.has("name") else "" software_version = sw.version if sw.has("version") else "" software_build_date = sw.buildDate if sw.has("buildDate") else "" software_api_version = sw.apiVersion if sw.has("apiVersion") else 0 software_status = sw.status if sw.has("status") else "" software_premium = sw.premium if sw.has("premium") else false # Parse language var lang = response.language if response.has("language") else {} language_name = lang.name if lang.has("name") else "" language_code = lang.code if lang.has("code") else "" var det_lang = lang.detectedLanguage if lang.has("detectedLanguage") else {} detected_language_name = det_lang.name if det_lang.has("name") else "" detected_language_code = det_lang.code if det_lang.has("code") else "" # Parse matches matches = [] var matches_arr = response.matches if response.has("matches") else [] for m in matches_arr: var _match = Match.new() _match.message = m.message if m.has("message") else "" _match.short_message = m.shortMessage if m.has("shortMessage") else "" _match.offset = m.offset if m.has("offset") else 0 _match.length = m.length if m.has("length") else 0 #_match.replacements = [] var replacements_arr = m.replacements if m.has("replacements") else [] for r in replacements_arr: _match.replacements.append(r.value if r.has("value") else "") var ctx = m.context if m.has("context") else {} _match.context_text = ctx.text if ctx.has("text") else "" _match.context_offset = ctx.offset if ctx.has("offset") else 0 _match.context_length = ctx.length if ctx.has("length") else 0 _match.sentence = m.sentence if m.has("sentence") else "" var rule_dict = m.rule if m.has("rule") else {} var rule = Match.Rule.new() rule.id = rule_dict.id if rule_dict.has("id") else "" rule.sub_id = rule_dict.subId if rule_dict.has("subId") else "" rule.description = rule_dict.description if rule_dict.has("description") else "" #rule.urls = [] var urls_arr = rule_dict.urls if rule_dict.has("urls") else [] for u in urls_arr: rule.urls.append(u.value if u.has("value") else "") rule.issue_type = rule_dict.issueType if rule_dict.has("issueType") else "" var cat = rule_dict.category if rule_dict.has("category") else {} var category = Match.Rule.Category.new() category.id = cat.id if cat.has("id") else "" category.name = cat.name if cat.has("name") else "" rule.category = category _match.rule = rule matches.append(_match)