Bugbot/Scripts/server_gitea_api.gd

246 lines
13 KiB
GDScript

class_name BugbotServerGiteaAPI
extends "res://addons/Bugbot/Scripts/server_api.gd"
#region Consts
const DEFAULT_SERVER : StringName = &"https://gitea.example.com"
const DEFAULT_BASE_URL : StringName = &"api/v1/"
const DEFAULT_OWNER_NAME : StringName = &"ProjectOwner"
const DEFAULT_REPO_NAME : StringName = &"ProjectName"
const DEFAULT_API_KEY : StringName = &"0123456789abcdef0123456789abcdef01234567"
const DEFAULT_BUG_LABEL : StringName = &"Kind/Bug"
const DEFAULT_STATUS_LABEL : StringName = &"Status/Need More Info"
const DEFAULT_VERSION_LABEL_PREFIX : StringName = &"Version/"
const DEFAULT_HARDWARE_LABEL_PREFIX : StringName = &"Hardware/"
const DEFAULT_OS_LABEL_PREFIX : StringName = &"OS/"
const DEFAULT_COMPONENT_LABEL_PREFIX : StringName = &"Component/"
const DEFAULT_PRIORITY_LABEL_PREFIX : StringName = &"Priority/"
const UNRESOLVED_TAG : StringName = &"Status/Unresolved"
const IN_PROGRESS_TAG : StringName = &"Status/In Progress"
const RESOLVED_TAG : StringName = &"Status/Resolved"
#endregion
func _return_list_of_bugs(callback:Callable) -> int:
return __start_thread_with_callback(__return_list_of_bugs_thread.bind(callback))
func _prepare_form(callback:Callable) -> int:
return __start_thread_with_callback(__prepare_form_thread.bind(callback))
func _send_form_data(callback:Callable) -> int:
return __start_thread_with_callback(__send_form_data_thread.bind(callback))
func __return_list_of_bugs_thread(callback:Callable) -> void:
var http_client : HTTPClient = HTTPClient.new()
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.")
return
var api_url : String = __build_url_string("issues")
api_url += "?state=all&labels=" + ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL).uri_encode()
var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
var response_string : String = __get_http_client_chunk_response(http_client)
var response_data := JSON.parse_string(response_string)
if __validate_server_response(response_data) != Error.OK:
return
var bug_array : Array
var resolved_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/resolved_statuses")
var in_progress_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/in_progress_statuses")
var unresolved_labels : Array = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/unresolved_statuses")
var show_resolved : bool = ProjectSettings.get_setting("bugbot/markers/resolved/show_resolved_bugs")
var show_in_progress : bool = ProjectSettings.get_setting("bugbot/markers/in_progress/show_in_progress_bugs")
var show_unresolved : bool = ProjectSettings.get_setting("bugbot/markers/unresolved/show_unresolved_bugs")
for bug_in:Dictionary in response_data:
var bug : BugbotBugData = BugbotBugData.new()
var bug_labels : Array = []
var resolved_tag_found : bool = false
var in_progress_tag_found : bool = false
var unresolved_tag_found : bool = false
# Find which resolution statuses apply to this bug.
bug.is_open = (bug_in["state"] == "open")
if not bug.is_open:
resolved_tag_found = true
else:
for labels:Dictionary in bug_in["labels"]:
bug_labels.append(labels["name"] as String)
for label:String in resolved_labels:
if bug_labels.has(label): resolved_tag_found = true
for label:String in in_progress_labels:
if bug_labels.has(label): in_progress_tag_found = true
for label:String in unresolved_labels:
if bug_labels.has(label): unresolved_tag_found = true
# Figure out which resolution tag to prioritise, and whether we should show the marker.
var show_marker : bool
if resolved_tag_found:
bug.resolution = RESOLVED_TAG
show_marker = show_resolved
elif in_progress_tag_found:
bug.resolution = IN_PROGRESS_TAG
show_marker = show_in_progress
elif unresolved_tag_found or unresolved_labels.is_empty():
bug.resolution = UNRESOLVED_TAG
show_marker = show_unresolved
if not show_marker: continue
bug.id = bug_in["id"]
bug.title = bug_in["title"]
bug.body = bug_in["body"]
bug.component = &"Unused"
bug.platform = &"Unused"
bug.operating_system = &"Unused"
bug.severity = "Severity will go here."
bug.status = bug_in["state"]
bug.duplicate_of = -1
bug.map_name = "Map name will go here."
bug.marker_location = "Marker location will go here."
bug_array.append(bug)
callback.call_deferred(bug_array)
__bugbot_server_thread.call_deferred("wait_to_finish")
func __prepare_form_thread(callback:Callable) -> void:
var http_client : HTTPClient = HTTPClient.new()
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.")
return
# Pull a list of issue labels so we can get the ones we care about.
var api_url : String = __build_url_string("labels")
var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
var response_string : String = __get_http_client_chunk_response(http_client)
var response_data := JSON.parse_string(response_string)
if __validate_server_response(response_data) != Error.OK:
return
var version_tags : Array
var hardware_tags : Array
var os_tags : Array
var component_tags : Array
var priority_tags : Array
var version_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/version_label_prefix", DEFAULT_VERSION_LABEL_PREFIX)
var hardware_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/hardware_label_prefix", DEFAULT_HARDWARE_LABEL_PREFIX)
var os_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/os_label_prefix", DEFAULT_OS_LABEL_PREFIX)
var component_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/component_label_prefix", DEFAULT_COMPONENT_LABEL_PREFIX)
var priority_prefix : String = ProjectSettings.get_setting("bugbot/reporting/gitea/status_labels/priority_label_prefix", DEFAULT_PRIORITY_LABEL_PREFIX)
for label_in:Dictionary in response_data:
if version_prefix and label_in["name"].begins_with(version_prefix):
version_tags.append(label_in)
if hardware_prefix and label_in["name"].begins_with(hardware_prefix):
hardware_tags.append(label_in)
if os_prefix and label_in["name"].begins_with(os_prefix):
os_tags.append(label_in)
if component_prefix and label_in["name"].begins_with(component_prefix):
component_tags.append(label_in)
if priority_prefix and label_in["name"].begins_with(priority_prefix):
priority_tags.append(label_in)
version_tags.sort_custom(func(a,b):return a["id"] < b["id"])
hardware_tags.sort_custom(func(a,b):return a["id"] < b["id"])
os_tags.sort_custom(func(a,b):return a["id"] < b["id"])
component_tags.sort_custom(func(a,b):return a["id"] < b["id"])
priority_tags.sort_custom(func(a,b): return a["id"] < b["id"])
var tag_lists : Array = [version_tags, hardware_tags, os_tags, component_tags, priority_tags]
callback.call_deferred(tag_lists)
__bugbot_server_thread.call_deferred("wait_to_finish")
func __send_form_data_thread(callback:Callable) -> void:
var http_client : HTTPClient = HTTPClient.new()
if __connect_to_server(http_client, DEFAULT_SERVER) != HTTPClient.STATUS_CONNECTED:
printerr("Could not connect to server.")
return
var api_url : String = __build_url_string("labels")
var header_data : Array = __create_header_data()
var error : int = http_client.request(HTTPClient.METHOD_GET, api_url, header_data)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
var response_string : String = __get_http_client_chunk_response(http_client)
var response_data := JSON.parse_string(response_string)
if __validate_server_response(response_data) != Error.OK:
return
var response_array : Array
var bug_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/bug_label", DEFAULT_BUG_LABEL)
var status_label : String = ProjectSettings.get_setting("bugbot/reporting/gitea/default_status_label", DEFAULT_STATUS_LABEL)
for label_in:Dictionary in response_data:
if label_in["name"] == bug_label or label_in["name"] == status_label:
response_array.append(label_in["id"])
api_url = __build_url_string("issues")
var post_data : Dictionary = {
"title": "This is a test bug. Here's some randomness just for fun: " + String.num(randf_range(0.0, 10000000.0)),
"body": "Fusce ornare ut felis quis aliquet. Nullam mollis dictum elit, vitae gravida metus blandit eu. Donec mi ipsum, luctus vel arcu in, suscipit hendrerit mi. Morbi imperdiet tellus pretium mi semper, vel lacinia risus mattis. Ut dapibus sed nibh eget suscipit. Vestibulum posuere pellentesque lectus, ac mollis odio congue tempus. Phasellus nisi nunc, tincidunt et bibendum non, ornare quis felis. Donec finibus mauris eu sollicitudin pharetra. Pellentesque interdum mi in augue imperdiet molestie. Nulla venenatis nec libero in feugiat. Donec nec mauris molestie, euismod magna nec, aliquet felis.\n\nAenean suscipit auctor nulla, ac aliquam purus porttitor ut. Curabitur lacinia ullamcorper ligula, sit amet tempor arcu volutpat et. Nulla eget nisi sem. Etiam pharetra at orci ut fermentum. In eu neque purus. Aliquam condimentum gravida porttitor. Nullam sem sapien, semper at hendrerit nec, lobortis sed magna. Duis non pharetra orci. Quisque faucibus, sem vitae laoreet suscipit, orci massa convallis lorem, ut malesuada dui felis ac eros.\n\nPellentesque felis lorem, volutpat eu ullamcorper eu, ultrices sed nulla. Proin ac nunc sit amet ex pellentesque sagittis non ut libero. Maecenas viverra, odio eu elementum convallis, erat purus tempor tortor, non suscipit est enim quis ligula. Praesent vestibulum orci nec enim vehicula, id commodo erat sollicitudin. Sed mauris eros, sollicitudin sit amet volutpat ac, ullamcorper dignissim erat. Aenean vitae turpis quis lorem ultrices varius. Donec pellentesque suscipit nulla id consectetur. Quisque nibh nisl, posuere in sapien eget, vehicula dapibus magna. Integer faucibus ligula ut metus sollicitudin viverra. Vestibulum elementum vitae leo sit amet ornare. Sed dapibus egestas nisi id tempus. Proin lorem erat, euismod quis porttitor ac, tincidunt faucibus nisl. Sed aliquam sem in vehicula mattis. Fusce eu libero ac eros tempus tempor ut eu nunc. Duis a turpis erat. Morbi rutrum gravida volutpat.",
"labels": response_array,
}
var post_data_string : String = JSON.stringify(post_data)
header_data = __create_header_data(post_data_string.length())
error = http_client.request(HTTPClient.METHOD_POST, api_url, header_data, post_data_string)
assert(error == Error.OK)
while http_client.get_status() == HTTPClient.STATUS_REQUESTING:
http_client.poll()
assert(http_client.get_status() == HTTPClient.STATUS_BODY or http_client.get_status() == HTTPClient.STATUS_CONNECTED)
response_string = __get_http_client_chunk_response(http_client)
callback.call_deferred([response_string])
__bugbot_server_thread.call_deferred("wait_to_finish")
func _current_server_api() -> String:
return "Gitea"
func __build_url_string(_api_suffix:String) -> String:
return "/" + \
ProjectSettings.get_setting("bugbot/reporting/gitea/base_URL", DEFAULT_BASE_URL) + \
"/repos/" + \
ProjectSettings.get_setting("bugbot/reporting/gitea/owner_name", DEFAULT_OWNER_NAME) + \
"/" + \
ProjectSettings.get_setting("bugbot/reporting/gitea/repo_name", DEFAULT_REPO_NAME) + \
"/" + _api_suffix
func __create_header_data(content_length:int = -1) -> Array:
var header : Array = [
"User-Agent: Pirulo/1.0 (Godot)",
"Accept: application/json",
]
header.append("Authorization: token " + ProjectSettings.get_setting("bugbot/reporting/gitea/API_key", DEFAULT_API_KEY))
if content_length >= 0:
header.append("Content-Type: application/json")
header.append("Content-Length: " + String.num_uint64(content_length))
return header
func __validate_server_response(_response:Variant) -> int:
# If the response is a dictionary and not an array, make the assumption
# that this is because the response was an error code.
if _response is Dictionary:
var error_data : BugbotErrorData = BugbotErrorData.new()
error_data.code = 1
error_data.message = _response["message"]
error_data.url = _response["url"]
printerr(error_data.message)
__bugbot_server_thread.call_deferred("wait_to_finish")
return Error.FAILED
return Error.OK