You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
212 lines
7.0 KiB
212 lines
7.0 KiB
@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)
|
|
|