//add a login callback associated with an instance of the API internal static void add_login_callback(KerbalXAPI api, AfterLoginCallback callback) { string key = api.client + "-" + api.client_version; after_login_callbacks.Remove(key); after_login_callbacks.Add(key, callback); }
internal void send(KerbalXAPI api, RequestCallback callback, bool authenticate = true) { if (String.IsNullOrEmpty(api.client_version) || String.IsNullOrEmpty(api.client)) { KXAPI.log("client info has not been set"); return; } if (authenticate) { if (api.logged_in) { set_header("token", KerbalXAPI.token); } else { KerbalXLoginUI.add_login_callback(api, (login_succsessful) => { if (login_succsessful) { this.send(api, callback, authenticate); } }); KerbalXLoginUI.open(); return; } } set_header("MODCLIENT", api.client); set_header("MODCLIENTVERSION", api.client_version); set_header("MODCLIENTSIGNITURE", api.client_signiture); set_header("KSPVERSION", Versioning.GetVersionString()); if (RequestHandler.instance == null) { KerbalXAPIHelper.instance.start_request_handler(); } RequestHandler.instance.send_request(api, request, callback); }
protected override void WindowContent(int win_id) { if (failed_to_connect) { error_dialog(() => { label("Unable to Connect to KerbalX.com!", "alert.h1"); label("Check your net connection and that you can reach KerbalX in a browser", "alert.h2"); }); } else if (upgrade_required) { error_dialog(() => { label("Upgrade Required", "h2"); label(upgrade_required_message); section(() => { section("dialog.section", () => { string url = "/KXAPI"; if (api_instance.client != "KerbalXAPI") { url += "/" + api_instance.client; } button("Goto KerbalX.com" + url + " for more info", "hyperlink.left", () => { Application.OpenURL(KerbalXAPI.site_url_to(url)); }); }); }); }, "Upgrade Required"); on_error(); } else if (error_message != null) { List <string> messages = new List <string>(); foreach (string s in error_message.Split(new string[] { Environment.NewLine }, StringSplitOptions.None)) { messages.Add(s); } string title = messages[0]; messages[0] = ""; error_dialog(() => { label(title, "alert.h2"); foreach (string message in messages) { if (message != "") { label(message); } } }, "KerbalX.com Error"); on_error(); } GameObject.Destroy(this); }
//Public Authentication methods //Login //usage: //KerbalXAPI api = new KerbalXAPI("mod name", "mod version"); //api.login((login_successful) => { // if(login_successful){ // //some action to run once logged in // } //}); //Can also be called without a callback: //api.login() // //If the API is already logged in, then the callback is called instantly with the argument given as True //If the API is not yet logged in, but a KerbalX.key (token) file exists, it authenticates the token with KerbalX and if it's valid the callback is called with True //If either the token is invalid or not present it opens the login UI. Once the user has logged in the callback is called with True. //The only time the callback will be called with False as the argument is if the user cancels the login process. public void login(AfterLoginCallback callback) { if (KerbalXAPIHelper.instance.on_main_menu) { if (logged_in) { callback(true); } else { KerbalXLoginUI.add_login_callback(this, callback); //callback is stashed in a Dictionary on the loginUI and will be called once login has completed or been canclled. } check_api_helper_state(); KerbalXLoginUI.open(); } else { if (logged_in) { callback(true); //call the callback instantly if the API is already logged in } else { KerbalXAPI kxapi = null; if (instances.ContainsKey("KerbalXAPI")) { kxapi = instances["KerbalXAPI"]; } else { kxapi = new KerbalXAPI("KerbalXAPI", KXAPI.version); } kxapi.login((resp, code) => { //validate the user's authentication token with KerbalX if (code == 200) { callback(true); //If the token is valid then call the callback } else { //If the token is either invalid or not present, trigger the LoginUI check_api_helper_state(); KerbalXLoginUI.add_login_callback(this, callback); //callback is stashed in a Dictionary on the loginUI and will be called once login has completed or been canclled. KerbalXLoginUI.open(); //Open the LoginUI (request made via the APIHelper which needs to have been started before this point). } }); } } }
internal void show_error_messages_for(KerbalXAPI api) { if (message_handler_instance != null) { GameObject.Destroy(message_handler_instance); } message_handler_instance = gameObject.AddOrGetComponent <MessageHandler>(); message_handler_instance.api_instance = api; message_handler_instance.failed_to_connect = api.failed_to_connect; message_handler_instance.upgrade_required = api.upgrade_required; message_handler_instance.upgrade_required_message = api.upgrade_required_message; message_handler_instance.error_message = api.server_error_message; api.failed_to_connect = false; api.upgrade_required = false; api.upgrade_required_message = null; api.server_error_message = null; }
//Internal Authentication POST requests //make request to site to authenticate username and password and get token back internal void login(string username, string password, RequestCallback callback) { KXAPI.log("Logging into KerbalX.com..."); NameValueCollection data = new NameValueCollection() { { "username", username }, { "password", password } }; RequestHandler.show_401_message = false; //don't show standard 401 error dialog HTTP.post(url_to("api/login"), data).send(this, (resp, code) => { if (code == 200) { KXAPI.log("Logged in"); var resp_data = JSON.Parse(resp); KerbalXAPI.token = resp_data["token"]; KerbalXAPI.save_token(resp_data["token"]); KerbalXAPI.kx_username = resp_data["username"]; } callback(resp, code); }, false); }
public string url_to(string path) { return(KerbalXAPI.site_url_to(path)); }
//Used in all interacton with KerbalX, called from a Coroutine and handles the response error codes from the site private IEnumerator transmit(KerbalXAPI api, UnityWebRequest request, RequestCallback callback) { // last_request = null; // last_callback = null; // api_instance = api; api.server_error_message = null; api.failed_to_connect = false; api.upgrade_required = false; KXAPI.log("sending request to: " + request.url); yield return(request.Send()); if (request.isNetworkError) //Request Failed, most likely due to being unable to get a response, therefore no status code { api.failed_to_connect = true; KXAPI.log("request failed: " + request.error); // last_request = new UnityWebRequest(request.url, request.method); // \ create a copy of the request which is about to be sent // if(request.method != "GET"){ // | if the request fails because of inability to connect to site // last_request.uploadHandler = new UploadHandlerRaw(request.uploadHandler.data); // < then try_again() can be used to fire the copied request // } // | and the user can carry on from where they were when connection was lost. // last_request.downloadHandler = request.downloadHandler; // | upload and download handlers have to be duplicated too // last_callback = callback; // / and the callback is also stuffed into a var for reuse. } else { int status_code = (int)request.responseCode; //server responded - get status code KXAPI.log("request returned " + status_code + " " + status_codes[status_code.ToString()]); if (status_code == 500) //KerbalX server error { string error_message = "KerbalX server error!!\n" + //default error message incase server doesn't come back with something more helpful "An error has occurred on KerbalX (it was probably Jebs fault)"; var resp_data = JSON.Parse(request.downloadHandler.text); //read response message and assuming there is one change the error_message if (!(resp_data["error"] == null || resp_data["error"] == "")) { error_message = "KerbalX server error!!\n" + resp_data["error"]; } KXAPI.log(error_message); api.server_error_message = error_message; //Set the error_message on KerbalX, any open window will pick this up and render error dialog callback(request.downloadHandler.text, status_code); //Still call the callback, assumption is all callbacks will test status code for 200 before proceeding, this allows for further handling if needed } else if (status_code == 426) //426 - Upgrade Required, only for a major version change that makes past versions incompatible with the site's API { api.upgrade_required = true; var resp_data = JSON.Parse(request.downloadHandler.text); api.upgrade_required_message = resp_data["message"]; callback("", status_code); } else if (status_code == 401) //401s (Unauthorized) - response to the user's token not being recognized. { if (RequestHandler.show_401_message == true) //In the case of login/authenticate, the 401 message is not shown (handled by login dialog) { api.server_error_message = "Login to KerbalX.com failed"; api.logout((resp, code) => {}); } callback(request.downloadHandler.text, status_code); } else if (status_code == 200 || status_code == 400 || status_code == 422) //Error codes returned for OK and failed validations which are handled by the requesting method { callback(request.downloadHandler.text, status_code); } else //Unhandled error codes - All other error codes. { api.server_error_message = "Error " + status_code + "\n"; var resp_data = JSON.Parse(request.downloadHandler.text); if (!(resp_data["error"] == null || resp_data["error"] == "")) { api.server_error_message += resp_data["error"]; } else if (!(resp_data["message"] == null || resp_data["message"] == "")) { api.server_error_message += resp_data["message"]; } else { api.server_error_message += request.downloadHandler.text; } callback(request.downloadHandler.text, status_code); } request.Dispose(); RequestHandler.show_401_message = true; } }
//Used in all requests to KerbalX internal void send_request(KerbalXAPI api, UnityWebRequest request, RequestCallback callback) { StartCoroutine(transmit(api, request, callback)); }