From 9b196bb4f907bd6a89c2e1296b4cc2612806ad3c Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sat, 27 Aug 2022 14:19:25 -0500 Subject: [PATCH] Format GDScript files using Razoric's formatter + manual review --- addons/godot-firebase/auth/auth.gd | 232 +++++++++--------- addons/godot-firebase/auth/auth_provider.gd | 5 + .../godot-firebase/auth/providers/facebook.gd | 7 +- .../godot-firebase/auth/providers/github.gd | 3 +- .../godot-firebase/auth/providers/google.gd | 1 + .../godot-firebase/auth/providers/twitter.gd | 26 +- addons/godot-firebase/auth/user_data.gd | 30 ++- addons/godot-firebase/database/database.gd | 32 +-- addons/godot-firebase/database/reference.gd | 149 +++++------ addons/godot-firebase/database/resource.gd | 7 +- .../dynamiclinks/dynamiclinks.gd | 47 ++-- addons/godot-firebase/firebase/firebase.gd | 76 +++--- .../firestore/firestore_document.gd | 104 ++++---- .../godot-firebase/functions/function_task.gd | 25 +- addons/godot-firebase/plugin.gd | 2 + addons/godot-firebase/storage/storage.gd | 92 ++++--- .../storage/storage_reference.gd | 39 ++- addons/godot-firebase/storage/storage_task.gd | 20 +- addons/http-sse-client/HTTPSSEClient.gd | 27 +- .../http-sse-client/httpsseclient_plugin.gd | 2 + .../class_doc_generator.gd | 2 + .../doc_exporter/doc_exporter.gd | 3 +- .../doc_item/argument_doc_item.gd | 4 +- .../doc_item/class_doc_item.gd | 7 +- .../doc_item/constant_doc_item.gd | 3 +- .../doc_item/doc_item.gd | 3 +- .../doc_item/method_doc_item.gd | 3 +- .../doc_item/property_doc_item.gd | 4 +- .../doc_item/signal_doc_item.gd | 4 +- test/TestUtils.gd | 9 +- test/storage_stress_test.gd | 2 + test/unit/test_FirebaseDatabaseStore.gd | 21 +- test/unit/test_FirestoreDocument.gd | 79 ++---- 33 files changed, 582 insertions(+), 488 deletions(-) diff --git a/addons/godot-firebase/auth/auth.gd b/addons/godot-firebase/auth/auth.gd index 549d7de..bf3d98b 100644 --- a/addons/godot-firebase/auth/auth.gd +++ b/addons/godot-firebase/auth/auth.gd @@ -6,8 +6,9 @@ tool class_name FirebaseAuth extends HTTPRequest -const _API_VERSION : String = "v1" -const _INAPP_PLUGIN : String = "GodotSvc" + +const _API_VERSION: String = "v1" +const _INAPP_PLUGIN: String = "GodotSvc" # Emitted for each Auth request issued. # `result_code` -> Either `1` if auth succeeded or `error_code` if unsuccessful auth request @@ -23,137 +24,133 @@ signal token_exchanged(successful) signal token_refresh_succeeded(auth_result) signal logged_out() -const RESPONSE_SIGNUP : String = "identitytoolkit#SignupNewUserResponse" -const RESPONSE_SIGNIN : String = "identitytoolkit#VerifyPasswordResponse" -const RESPONSE_ASSERTION : String = "identitytoolkit#VerifyAssertionResponse" -const RESPONSE_USERDATA : String = "identitytoolkit#GetAccountInfoResponse" -const RESPONSE_CUSTOM_TOKEN : String = "identitytoolkit#VerifyCustomTokenResponse" +const RESPONSE_SIGNUP: String = "identitytoolkit#SignupNewUserResponse" +const RESPONSE_SIGNIN: String = "identitytoolkit#VerifyPasswordResponse" +const RESPONSE_ASSERTION: String = "identitytoolkit#VerifyAssertionResponse" +const RESPONSE_USERDATA: String = "identitytoolkit#GetAccountInfoResponse" +const RESPONSE_CUSTOM_TOKEN: String = "identitytoolkit#VerifyCustomTokenResponse" -var _base_url : String = "" +var _base_url: String = "" var _refresh_request_base_url = "" -var _signup_request_url : String = "accounts:signUp?key=%s" -var _signin_with_oauth_request_url : String = "accounts:signInWithIdp?key=%s" -var _signin_request_url : String = "accounts:signInWithPassword?key=%s" -var _signin_custom_token_url : String = "accounts:signInWithCustomToken?key=%s" -var _userdata_request_url : String = "accounts:lookup?key=%s" -var _oobcode_request_url : String = "accounts:sendOobCode?key=%s" -var _delete_account_request_url : String = "accounts:delete?key=%s" -var _update_account_request_url : String = "accounts:update?key=%s" - -var _refresh_request_url : String = "/v1/token?key=%s" -var _google_auth_request_url : String = "https://accounts.google.com/o/oauth2/v2/auth?" - -var _config : Dictionary = {} -var auth : Dictionary = {} -var _needs_refresh : bool = false -var is_busy : bool = false -var has_child : bool = false - - -var tcp_server : TCP_Server = TCP_Server.new() -var tcp_timer : Timer = Timer.new() -var tcp_timeout : float = 0.5 - -var _headers : PoolStringArray = [ +var _signup_request_url: String = "accounts:signUp?key=%s" +var _signin_with_oauth_request_url: String = "accounts:signInWithIdp?key=%s" +var _signin_request_url: String = "accounts:signInWithPassword?key=%s" +var _signin_custom_token_url: String = "accounts:signInWithCustomToken?key=%s" +var _userdata_request_url: String = "accounts:lookup?key=%s" +var _oobcode_request_url: String = "accounts:sendOobCode?key=%s" +var _delete_account_request_url: String = "accounts:delete?key=%s" +var _update_account_request_url: String = "accounts:update?key=%s" + +var _refresh_request_url: String = "/v1/token?key=%s" +var _google_auth_request_url: String = "https://accounts.google.com/o/oauth2/v2/auth?" + +var _config: Dictionary = {} +var auth: Dictionary = {} +var _needs_refresh: bool = false +var is_busy: bool = false +var has_child: bool = false + +var tcp_server: TCP_Server = TCP_Server.new() +var tcp_timer: Timer = Timer.new() +var tcp_timeout: float = 0.5 + +var _headers: PoolStringArray = [ "Content-Type: application/json", "Accept: application/json", ] -var requesting : int = -1 +var requesting: int = -1 enum Requests { NONE = -1, EXCHANGE_TOKEN, - LOGIN_WITH_OAUTH + LOGIN_WITH_OAUTH, } -var auth_request_type : int = -1 +var auth_request_type: int = -1 enum Auth_Type { - NONE = -1 + NONE = -1, LOGIN_EP, LOGIN_ANON, LOGIN_CT, LOGIN_OAUTH, - SIGNUP_EP + SIGNUP_EP, } -var _login_request_body : Dictionary = { - "email":"", - "password":"", +var _login_request_body: Dictionary = { + "email": "", + "password": "", "returnSecureToken": true, } -var _oauth_login_request_body : Dictionary = { - "postBody":"", - "requestUri":"", - "returnIdpCredential":false, - "returnSecureToken":true +var _oauth_login_request_body: Dictionary = { + "postBody": "", + "requestUri": "", + "returnIdpCredential": false, + "returnSecureToken": true, } -var _anonymous_login_request_body : Dictionary = { - "returnSecureToken":true +var _anonymous_login_request_body: Dictionary = { + "returnSecureToken": true, } -var _refresh_request_body : Dictionary = { - "grant_type":"refresh_token", - "refresh_token":"", +var _refresh_request_body: Dictionary = { + "grant_type": "refresh_token", + "refresh_token": "", } -var _custom_token_body : Dictionary = { - "token":"", - "returnSecureToken":true +var _custom_token_body: Dictionary = { + "token": "", + "returnSecureToken": true, } -var _password_reset_body : Dictionary = { - "requestType":"password_reset", - "email":"", +var _password_reset_body: Dictionary = { + "requestType": "password_reset", + "email": "", } - -var _change_email_body : Dictionary = { - "idToken":"", - "email":"", +var _change_email_body: Dictionary = { + "idToken": "", + "email": "", "returnSecureToken": true, } - -var _change_password_body : Dictionary = { - "idToken":"", - "password":"", +var _change_password_body: Dictionary = { + "idToken": "", + "password": "", "returnSecureToken": true, } - -var _account_verification_body : Dictionary = { - "requestType":"verify_email", - "idToken":"", +var _account_verification_body: Dictionary = { + "requestType": "verify_email", + "idToken": "", } - -var _update_profile_body : Dictionary = { - "idToken":"", - "displayName":"", - "photoUrl":"", - "deleteAttribute":"", - "returnSecureToken":true +var _update_profile_body: Dictionary = { + "idToken": "", + "displayName": "", + "photoUrl": "", + "deleteAttribute": "", + "returnSecureToken": true, } -var _local_port : int = 8060 -var _local_uri : String = "http://localhost:%s/"%_local_port -var _local_provider : AuthProvider = AuthProvider.new() +var _local_port: int = 8060 +var _local_uri: String = "http://localhost:%s/" % _local_port +var _local_provider: AuthProvider = AuthProvider.new() + func _ready() -> void: tcp_timer.wait_time = tcp_timeout tcp_timer.connect("timeout", self, "_tcp_stream_timer") - + if OS.get_name() == "HTML5": _local_uri += "tmp_js_export.html" # Sets the configuration needed for the plugin to talk to Firebase # These settings come from the Firebase.gd script automatically -func _set_config(config_json : Dictionary) -> void: +func _set_config(config_json: Dictionary) -> void: _config = config_json _signup_request_url %= _config.apiKey _signin_request_url %= _config.apiKey @@ -169,17 +166,17 @@ func _set_config(config_json : Dictionary) -> void: _check_emulating() -func _check_emulating() -> void : +func _check_emulating() -> void: ## Check emulating if not Firebase.emulating: - _base_url = "https://identitytoolkit.googleapis.com/{version}/".format({ version = _API_VERSION }) + _base_url = "https://identitytoolkit.googleapis.com/{version}/".format({version = _API_VERSION}) _refresh_request_base_url = "https://securetoken.googleapis.com" else: - var port : String = _config.emulators.ports.authentication + var port: String = _config.emulators.ports.authentication if port == "": Firebase._printerr("You are in 'emulated' mode, but the port for Authentication has not been configured.") else: - _base_url = "http://localhost:{port}/identitytoolkit.googleapis.com/{version}/".format({ version = _API_VERSION ,port = port }) + _base_url = "http://localhost:{port}/identitytoolkit.googleapis.com/{version}/".format({version = _API_VERSION, port = port}) _refresh_request_base_url = "http://localhost:{port}/securetoken.googleapis.com".format({port = port}) @@ -192,13 +189,15 @@ func _is_ready() -> bool: else: return true + # Function cleans the URI and replaces spaces with %20 # As of right now we only replace spaces # We may need to decide to use the percent_encode() String function func _clean_url(_url): - _url = _url.replace(' ','%20') + _url = _url.replace(" ", "%20") return _url + # Synchronous call to check if any user is already logged in. func is_logged_in() -> bool: return auth != null and auth.has("idtoken") @@ -206,7 +205,7 @@ func is_logged_in() -> bool: # Called with Firebase.Auth.signup_with_email_and_password(email, password) # You must pass in the email and password to this function for it to work correctly -func signup_with_email_and_password(email : String, password : String) -> void: +func signup_with_email_and_password(email: String, password: String) -> void: if _is_ready(): is_busy = true _login_request_body.email = email @@ -229,7 +228,7 @@ func login_anonymous() -> void: # Called with Firebase.Auth.login_with_email_and_password(email, password) # You must pass in the email and password to this function for it to work correctly # If the login fails it will return an error code through the function _on_FirebaseAuth_request_completed -func login_with_email_and_password(email : String, password : String) -> void: +func login_with_email_and_password(email: String, password: String) -> void: if _is_ready(): is_busy = true _login_request_body.email = email @@ -237,9 +236,10 @@ func login_with_email_and_password(email : String, password : String) -> void: auth_request_type = Auth_Type.LOGIN_EP request(_base_url + _signin_request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print(_login_request_body)) + # Login with a custom valid token # The token needs to be generated using an external service/function -func login_with_custom_token(token : String) -> void: +func login_with_custom_token(token: String) -> void: if _is_ready(): is_busy = true _custom_token_body.token = token @@ -250,7 +250,7 @@ func login_with_custom_token(token : String) -> void: # Open a web page in browser redirecting to Google oAuth2 page for the current project # Once given user's authorization, a token will be generated. # NOTE** the generated token will be automatically captured and a login request will be made if the token is correct -func get_auth_localhost(provider: AuthProvider = get_GoogleProvider(), port : int = _local_port): +func get_auth_localhost(provider: AuthProvider = get_GoogleProvider(), port: int = _local_port): get_auth_with_redirect(provider) yield(get_tree().create_timer(0.5),"timeout") if has_child == false: @@ -263,13 +263,13 @@ func get_auth_localhost(provider: AuthProvider = get_GoogleProvider(), port : in func get_auth_with_redirect(provider: AuthProvider) -> void: var url_endpoint: String = provider.redirect_uri for key in provider.params.keys(): - url_endpoint+=key+"="+provider.params[key]+"&" - url_endpoint += provider.params.redirect_type+"="+_local_uri + url_endpoint += key + "=" + provider.params[key] + "&" + url_endpoint += provider.params.redirect_type + "=" + _local_uri url_endpoint = _clean_url(url_endpoint) if OS.get_name() == "HTML5" and OS.has_feature("JavaScript"): JavaScript.eval('window.location.replace("' + url_endpoint + '")') elif Engine.has_singleton(_INAPP_PLUGIN) and OS.get_name() == "iOS": - #in app for ios if the iOS plugin exists + # in app for ios if the iOS plugin exists set_local_provider(provider) Engine.get_singleton(_INAPP_PLUGIN).popup(url_endpoint) else: @@ -282,7 +282,7 @@ func get_auth_with_redirect(provider: AuthProvider) -> void: # A token is automatically obtained using an authorization code using @get_google_auth() # @provider_id and @request_uri can be changed func login_with_oauth(_token: String, provider: AuthProvider) -> void: - var token : String = _token.percent_decode() + var token: String = _token.percent_decode() print(token) var is_successful: bool = true if provider.should_exchange: @@ -291,19 +291,18 @@ func login_with_oauth(_token: String, provider: AuthProvider) -> void: token = auth.accesstoken if is_successful and _is_ready(): is_busy = true - _oauth_login_request_body.postBody = "access_token="+token+"&providerId="+provider.provider_id + _oauth_login_request_body.postBody = "access_token=" + token + "&providerId=" + provider.provider_id _oauth_login_request_body.requestUri = _local_uri requesting = Requests.LOGIN_WITH_OAUTH auth_request_type = Auth_Type.LOGIN_OAUTH request(_base_url + _signin_with_oauth_request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print(_oauth_login_request_body)) - # Exchange the authorization oAuth2 code obtained from browser with a proper access id_token -func exchange_token(code : String, redirect_uri : String, request_url: String, _client_id: String, _client_secret: String) -> void: +func exchange_token(code: String, redirect_uri: String, request_url: String, _client_id: String, _client_secret: String) -> void: if _is_ready(): is_busy = true - var exchange_token_body : Dictionary = { + var exchange_token_body: Dictionary = { code = code, redirect_uri = redirect_uri, client_id = _client_id, @@ -312,7 +311,6 @@ func exchange_token(code : String, redirect_uri : String, request_url: String, _ } requesting = Requests.EXCHANGE_TOKEN request(request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print(exchange_token_body)) - # Open a web page in browser redirecting to Google oAuth2 page for the current project @@ -327,12 +325,12 @@ func get_google_auth_manual(provider: AuthProvider = _local_provider) -> void: func _tcp_stream_timer() -> void: var peer : StreamPeer = tcp_server.take_connection() if peer != null: - var raw_result : String = peer.get_utf8_string(400) + var raw_result: String = peer.get_utf8_string(400) if raw_result != "" and raw_result.begins_with("GET"): tcp_timer.stop() remove_child(tcp_timer) has_child = false - var token : String = "" + var token: String = "" for value in raw_result.split(" ")[1].lstrip("/?").split("&"): var splitted: PoolStringArray = value.split("=") if _local_provider.params.response_type in splitted[0]: @@ -353,8 +351,6 @@ func _tcp_stream_timer() -> void: yield(self, "login_succeeded") peer.disconnect_from_host() tcp_server.stop() - - # Function used to logout of the system, this will also remove the local encrypted auth file if there is one @@ -380,7 +376,7 @@ func manual_token_refresh(auth_data): # This function is called whenever there is an authentication request to Firebase # On an error, this function with emit the signal 'login_failed' and print the error to the console -func _on_FirebaseAuth_request_completed(result : int, response_code : int, headers : PoolStringArray, body : PoolByteArray) -> void: +func _on_FirebaseAuth_request_completed(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void: print_debug(JSON.parse(body.get_string_from_utf8()).result) is_busy = false var res @@ -439,7 +435,7 @@ func _on_FirebaseAuth_request_completed(result : int, response_code : int, heade # Function used to save the auth data provided by Firebase into an encrypted file # Note this does not work in HTML5 or UWP -func save_auth(auth : Dictionary) -> void: +func save_auth(auth: Dictionary) -> void: var encrypted_file = File.new() var err = encrypted_file.open_encrypted_with_pass("user://user.auth", File.WRITE, _config.apiKey) if err != OK: @@ -465,7 +461,7 @@ func load_auth() -> void: # Function used to remove the local encrypted auth file func remove_auth() -> void: var dir = Directory.new() - if (dir.file_exists("user://user.auth")): + if dir.file_exists("user://user.auth"): dir.remove("user://user.auth") else: Firebase._printerr("No encrypted auth file exists") @@ -475,7 +471,7 @@ func remove_auth() -> void: # If there is, the game will load it and refresh the token func check_auth_file() -> void: var dir = Directory.new() - if (dir.file_exists("user://user.auth")): + if dir.file_exists("user://user.auth"): # Will ensure "auth_request" emitted load_auth() else: @@ -484,7 +480,7 @@ func check_auth_file() -> void: # Function used to change the email account for the currently logged in user -func change_user_email(email : String) -> void: +func change_user_email(email: String) -> void: if _is_ready(): is_busy = true _change_email_body.email = email @@ -493,7 +489,7 @@ func change_user_email(email : String) -> void: # Function used to change the password for the currently logged in user -func change_user_password(password : String) -> void: +func change_user_password(password: String) -> void: if _is_ready(): is_busy = true _change_password_body.password = password @@ -502,7 +498,7 @@ func change_user_password(password : String) -> void: # User Profile handlers -func update_account(idToken : String, displayName : String, photoUrl : String, deleteAttribute : PoolStringArray, returnSecureToken : bool) -> void: +func update_account(idToken: String, displayName: String, photoUrl: String, deleteAttribute: PoolStringArray, returnSecureToken: bool) -> void: if _is_ready(): is_busy = true _update_profile_body.idToken = idToken @@ -523,7 +519,7 @@ func send_account_verification_email() -> void: # Function used to reset the password for a user who has forgotten in. # This will send the users account an email with a password reset link -func send_password_reset_email(email : String) -> void: +func send_password_reset_email(email: String) -> void: if _is_ready(): is_busy = true _password_reset_body.email = email @@ -539,14 +535,14 @@ func get_user_data() -> void: is_busy = false return - request(_base_url + _userdata_request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print({"idToken":auth.idtoken})) + request(_base_url + _userdata_request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print({"idToken": auth.idtoken})) # Function used to delete the account of the currently authenticated user func delete_user_account() -> void: if _is_ready(): is_busy = true - request(_base_url + _delete_account_request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print({"idToken":auth.idtoken})) + request(_base_url + _delete_account_request_url, _headers, true, HTTPClient.METHOD_POST, JSON.print({"idToken": auth.idtoken})) # Function is called when a new token is issued to a user. The function will yield until the token has expired, and then request a new one. @@ -582,21 +578,24 @@ func get_token_from_url(provider: AuthProvider): return null -func set_redirect_uri(redirect_uri : String) -> void: +func set_redirect_uri(redirect_uri: String) -> void: self._local_uri = redirect_uri -func set_local_provider(provider : AuthProvider) -> void: + +func set_local_provider(provider: AuthProvider) -> void: self._local_provider = provider + # This function is used to make all keys lowercase # This is only used to cut down on processing errors from Firebase # This is due to Google have inconsistencies in the API that we are trying to fix -func get_clean_keys(auth_result : Dictionary) -> Dictionary: +func get_clean_keys(auth_result: Dictionary) -> Dictionary: var cleaned = {} for key in auth_result.keys(): cleaned[key.replace("_", "").to_lower()] = auth_result[key] return cleaned + # -------------------- # PROVIDERS # -------------------- @@ -604,11 +603,14 @@ func get_clean_keys(auth_result : Dictionary) -> Dictionary: func get_GoogleProvider() -> GoogleProvider: return GoogleProvider.new(_config.clientId, _config.clientSecret) + func get_FacebookProvider() -> FacebookProvider: return FacebookProvider.new(_config.auth_providers.facebook_id, _config.auth_providers.facebook_secret) + func get_GitHubProvider() -> GitHubProvider: return GitHubProvider.new(_config.auth_providers.github_id, _config.auth_providers.github_secret) + func get_TwitterProvider() -> TwitterProvider: return TwitterProvider.new(_config.auth_providers.twitter_id, _config.auth_providers.twitter_secret) diff --git a/addons/godot-firebase/auth/auth_provider.gd b/addons/godot-firebase/auth/auth_provider.gd index ec0742d..2f0fd0b 100644 --- a/addons/godot-firebase/auth/auth_provider.gd +++ b/addons/godot-firebase/auth/auth_provider.gd @@ -2,6 +2,7 @@ tool class_name AuthProvider extends Reference + var redirect_uri: String = "" var access_token_uri: String = "" var provider_id: String = "" @@ -19,14 +20,18 @@ var should_exchange: bool = false func set_client_id(client_id: String) -> void: self.params.client_id = client_id + func set_client_secret(client_secret: String) -> void: self.client_secret = client_secret + func get_client_id() -> String: return self.params.client_id + func get_client_secret() -> String: return self.client_secret + func get_oauth_params() -> String: return "" diff --git a/addons/godot-firebase/auth/providers/facebook.gd b/addons/godot-firebase/auth/providers/facebook.gd index 32c1290..b5e59fb 100644 --- a/addons/godot-firebase/auth/providers/facebook.gd +++ b/addons/godot-firebase/auth/providers/facebook.gd @@ -1,11 +1,12 @@ -class_name FacebookProvider +class_name FacebookProvider extends AuthProvider + func _init(client_id: String, client_secret: String) -> void: randomize() set_client_id(client_id) set_client_secret(client_secret) - + self.redirect_uri = "https://www.facebook.com/v13.0/dialog/oauth?" self.access_token_uri = "https://graph.facebook.com/v13.0/oauth/access_token" self.provider_id = "facebook.com" @@ -17,5 +18,3 @@ func _init(client_id: String, client_secret: String) -> void: else: self.should_exchange = true self.params.response_type = "code" - - diff --git a/addons/godot-firebase/auth/providers/github.gd b/addons/godot-firebase/auth/providers/github.gd index 1716258..0c77272 100644 --- a/addons/godot-firebase/auth/providers/github.gd +++ b/addons/godot-firebase/auth/providers/github.gd @@ -1,6 +1,7 @@ -class_name GitHubProvider +class_name GitHubProvider extends AuthProvider + func _init(client_id: String, client_secret: String) -> void: randomize() set_client_id(client_id) diff --git a/addons/godot-firebase/auth/providers/google.gd b/addons/godot-firebase/auth/providers/google.gd index 48ad38f..15ac362 100644 --- a/addons/godot-firebase/auth/providers/google.gd +++ b/addons/godot-firebase/auth/providers/google.gd @@ -1,6 +1,7 @@ class_name GoogleProvider extends AuthProvider + func _init(client_id: String, client_secret: String) -> void: set_client_id(client_id) set_client_secret(client_secret) diff --git a/addons/godot-firebase/auth/providers/twitter.gd b/addons/godot-firebase/auth/providers/twitter.gd index b4c37b7..b7675c9 100644 --- a/addons/godot-firebase/auth/providers/twitter.gd +++ b/addons/godot-firebase/auth/providers/twitter.gd @@ -1,28 +1,29 @@ -class_name TwitterProvider +class_name TwitterProvider extends AuthProvider + var request_token_endpoint: String = "https://api.twitter.com/oauth/access_token?oauth_callback=" var oauth_header: Dictionary = { - oauth_callback="", - oauth_consumer_key="", - oauth_nonce="", - oauth_signature="", - oauth_signature_method="HMAC-SHA1", - oauth_timestamp="", - oauth_version="1.0" + oauth_callback = "", + oauth_consumer_key = "", + oauth_nonce = "", + oauth_signature = "", + oauth_signature_method = "HMAC-SHA1", + oauth_timestamp = "", + oauth_version = "1.0" } + func _init(client_id: String, client_secret: String) -> void: randomize() set_client_id(client_id) set_client_secret(client_secret) - + self.oauth_header.oauth_consumer_key = client_id self.oauth_header.oauth_nonce = OS.get_ticks_usec() self.oauth_header.oauth_timestamp = OS.get_ticks_msec() - - + self.should_exchange = true self.redirect_uri = "https://twitter.com/i/oauth2/authorize?" self.access_token_uri = "https://api.twitter.com/2/oauth2/token" @@ -32,8 +33,9 @@ func _init(client_id: String, client_secret: String) -> void: self.params.scope = "users.read" self.params.state = str(rand_range(0, 1)) + func get_oauth_params() -> String: var params: PoolStringArray = [] for key in self.oauth.keys(): - params.append(key+"="+self.oauth.get(key)) + params.append(key + "=" + self.oauth.get(key)) return params.join("&") diff --git a/addons/godot-firebase/auth/user_data.gd b/addons/godot-firebase/auth/user_data.gd index a5ddb85..62e0d57 100644 --- a/addons/godot-firebase/auth/user_data.gd +++ b/addons/godot-firebase/auth/user_data.gd @@ -6,19 +6,21 @@ tool class_name FirebaseUserData extends Reference -var local_id : String = "" # The uid of the current user. -var email : String = "" -var email_verified := false # Whether or not the account's email has been verified. -var password_updated_at : float = 0 # The timestamp, in milliseconds, that the account password was last changed. -var last_login_at : float = 0 # The timestamp, in milliseconds, that the account last logged in at. -var created_at : float = 0 # The timestamp, in milliseconds, that the account was created at. -var provider_user_info : Array = [] - -var provider_id : String = "" -var display_name : String = "" -var photo_url : String = "" - -func _init(p_userdata : Dictionary) -> void: + +var local_id: String = "" # The uid of the current user. +var email: String = "" +var email_verified := false # Whether or not the account's email has been verified. +var password_updated_at: float = 0 # The timestamp, in milliseconds, that the account password was last changed. +var last_login_at: float = 0 # The timestamp, in milliseconds, that the account last logged in at. +var created_at: float = 0 # The timestamp, in milliseconds, that the account was created at. +var provider_user_info: Array = [] + +var provider_id: String = "" +var display_name: String = "" +var photo_url: String = "" + + +func _init(p_userdata: Dictionary) -> void: local_id = p_userdata.get("localId", "") email = p_userdata.get("email", "") email_verified = p_userdata.get("emailVerified", false) @@ -32,9 +34,11 @@ func _init(p_userdata : Dictionary) -> void: photo_url = provider_user_info[0].get("photoUrl", "") display_name = provider_user_info[0].get("displayName", "") + func as_text() -> String: return _to_string() + func _to_string() -> String: var txt = "local_id : %s\n" % local_id txt += "email : %s\n" % email diff --git a/addons/godot-firebase/database/database.gd b/addons/godot-firebase/database/database.gd index 1d51b91..de736be 100644 --- a/addons/godot-firebase/database/database.gd +++ b/addons/godot-firebase/database/database.gd @@ -6,45 +6,49 @@ tool class_name FirebaseDatabase extends Node -var _base_url : String = "" -var _config : Dictionary = {} +var _base_url: String = "" -var _auth : Dictionary = {} +var _config: Dictionary = {} -func _set_config(config_json : Dictionary) -> void: +var _auth: Dictionary = {} + + +func _set_config(config_json: Dictionary) -> void: _config = config_json _check_emulating() -func _check_emulating() -> void : +func _check_emulating() -> void: ## Check emulating if not Firebase.emulating: _base_url = _config.databaseURL else: - var port : String = _config.emulators.ports.realtimeDatabase + var port: String = _config.emulators.ports.realtimeDatabase if port == "": Firebase._printerr("You are in 'emulated' mode, but the port for Realtime Database has not been configured.") else: _base_url = "http://localhost" - -func _on_FirebaseAuth_login_succeeded(auth_result : Dictionary) -> void: +func _on_FirebaseAuth_login_succeeded(auth_result: Dictionary) -> void: _auth = auth_result -func _on_FirebaseAuth_token_refresh_succeeded(auth_result : Dictionary) -> void: + +func _on_FirebaseAuth_token_refresh_succeeded(auth_result: Dictionary) -> void: _auth = auth_result + func _on_FirebaseAuth_logout() -> void: _auth = {} -func get_database_reference(path : String, filter : Dictionary = {}) -> FirebaseDatabaseReference: - var firebase_reference : FirebaseDatabaseReference = FirebaseDatabaseReference.new() - var pusher : HTTPRequest = HTTPRequest.new() - var listener : Node = Node.new() + +func get_database_reference(path: String, filter: Dictionary = {}) -> FirebaseDatabaseReference: + var firebase_reference: FirebaseDatabaseReference = FirebaseDatabaseReference.new() + var pusher: HTTPRequest = HTTPRequest.new() + var listener: Node = Node.new() listener.set_script(load("res://addons/http-sse-client/HTTPSSEClient.gd")) - var store : FirebaseDatabaseStore = FirebaseDatabaseStore.new() + var store: FirebaseDatabaseStore = FirebaseDatabaseStore.new() firebase_reference.set_db_path(path, filter) firebase_reference.set_auth_and_config(_auth, _config) firebase_reference.set_pusher(pusher) diff --git a/addons/godot-firebase/database/reference.gd b/addons/godot-firebase/database/reference.gd index b4ae5c8..464e5c1 100644 --- a/addons/godot-firebase/database/reference.gd +++ b/addons/godot-firebase/database/reference.gd @@ -6,6 +6,7 @@ tool class_name FirebaseDatabaseReference extends Node + signal new_data_update(data) signal patch_data_update(data) signal delete_data_update(data) @@ -13,59 +14,63 @@ signal delete_data_update(data) signal push_successful() signal push_failed() -const ORDER_BY : String = "orderBy" -const LIMIT_TO_FIRST : String = "limitToFirst" -const LIMIT_TO_LAST : String = "limitToLast" -const START_AT : String = "startAt" -const END_AT : String = "endAt" -const EQUAL_TO : String = "equalTo" - -var _pusher : HTTPRequest -var _listener : Node -var _store : FirebaseDatabaseStore -var _auth : Dictionary -var _config : Dictionary -var _filter_query : Dictionary -var _db_path : String -var _cached_filter : String -var _push_queue : Array = [] -var _update_queue : Array = [] -var _delete_queue : Array = [] -var _can_connect_to_host : bool = false - -const _put_tag : String = "put" -const _patch_tag : String = "patch" -const _delete_tag : String = "delete" -const _separator : String = "/" -const _json_list_tag : String = ".json" -const _query_tag : String = "?" -const _auth_tag : String = "auth=" -const _accept_header : String = "accept: text/event-stream" -const _auth_variable_begin : String = "[" -const _auth_variable_end : String = "]" -const _filter_tag : String = "&" -const _escaped_quote : String = '"' -const _equal_tag : String = "=" -const _key_filter_tag : String = "$key" - -var _headers : PoolStringArray = [] - -func set_db_path(path : String, filter_query_dict : Dictionary) -> void: +const ORDER_BY: String = "orderBy" +const LIMIT_TO_FIRST: String = "limitToFirst" +const LIMIT_TO_LAST: String = "limitToLast" +const START_AT: String = "startAt" +const END_AT: String = "endAt" +const EQUAL_TO: String = "equalTo" + +var _pusher: HTTPRequest +var _listener: Node +var _store: FirebaseDatabaseStore +var _auth: Dictionary +var _config: Dictionary +var _filter_query: Dictionary +var _db_path: String +var _cached_filter: String +var _push_queue: Array = [] +var _update_queue: Array = [] +var _delete_queue: Array = [] +var _can_connect_to_host: bool = false + +const _put_tag: String = "put" +const _patch_tag: String = "patch" +const _delete_tag: String = "delete" +const _separator: String = "/" +const _json_list_tag: String = ".json" +const _query_tag: String = "?" +const _auth_tag: String = "auth=" +const _accept_header: String = "accept: text/event-stream" +const _auth_variable_begin: String = "[" +const _auth_variable_end: String = "]" +const _filter_tag: String = "&" +const _escaped_quote: String = '"' +const _equal_tag: String = "=" +const _key_filter_tag: String = "$key" + +var _headers: PoolStringArray = [] + + +func set_db_path(path: String, filter_query_dict: Dictionary) -> void: _db_path = path _filter_query = filter_query_dict -func set_auth_and_config(auth_ref : Dictionary, config_ref : Dictionary) -> void: + +func set_auth_and_config(auth_ref: Dictionary, config_ref: Dictionary) -> void: _auth = auth_ref _config = config_ref -func set_pusher(pusher_ref : HTTPRequest) -> void: - if !_pusher: + +func set_pusher(pusher_ref: HTTPRequest) -> void: + if not _pusher: _pusher = pusher_ref add_child(_pusher) _pusher.connect("request_completed", self, "on_push_request_complete") -func set_listener(listener_ref : Node) -> void: - if !_listener: + +func set_listener(listener_ref: Node) -> void: + if not _listener: _listener = listener_ref add_child(_listener) _listener.connect("new_sse_event", self, "on_new_sse_event") @@ -76,7 +81,8 @@ func set_listener(listener_ref : Node) -> void: port = int(_config.emulators.ports.realtimeDatabase) _listener.connect_to_host(base_url, extended_url, port) -func on_new_sse_event(headers : Dictionary, event : String, data : Dictionary) -> void: + +func on_new_sse_event(headers: Dictionary, event: String, data: Dictionary) -> void: if data: var command = event if command and command != "keep-alive": @@ -93,12 +99,14 @@ func on_new_sse_event(headers : Dictionary, event : String, data : Dictionary) - emit_signal("delete_data_update", FirebaseResource.new(data.path, data.data)) pass -func set_store(store_ref : FirebaseDatabaseStore) -> void: - if !_store: + +func set_store(store_ref: FirebaseDatabaseStore) -> void: + if not _store: _store = store_ref add_child(_store) -func update(path : String, data : Dictionary) -> void: + +func update(path: String, data: Dictionary) -> void: path = path.strip_edges(true, true) if path == _separator: @@ -106,49 +114,52 @@ func update(path : String, data : Dictionary) -> void: var to_update = JSON.print(data) var status = _pusher.get_http_client_status() - if status == HTTPClient.STATUS_DISCONNECTED || status != HTTPClient.STATUS_REQUESTING: - var resolved_path = (_get_list_url() + _db_path + "/" + path + _get_remaining_path()) + if status == HTTPClient.STATUS_DISCONNECTED or status != HTTPClient.STATUS_REQUESTING: + var resolved_path = _get_list_url() + _db_path + "/" + path + _get_remaining_path() _pusher.request(resolved_path, _headers, true, HTTPClient.METHOD_PATCH, to_update) else: _update_queue.append({"path": path, "data": data}) -func push(data : Dictionary) -> void: + +func push(data: Dictionary) -> void: var to_push = JSON.print(data) if _pusher.get_http_client_status() == HTTPClient.STATUS_DISCONNECTED: _pusher.request(_get_list_url() + _db_path + _get_remaining_path(), _headers, true, HTTPClient.METHOD_POST, to_push) else: _push_queue.append(data) -func delete(reference : String) -> void: + +func delete(reference: String) -> void: if _pusher.get_http_client_status() == HTTPClient.STATUS_DISCONNECTED: _pusher.request(_get_list_url() + _db_path + _separator + reference + _get_remaining_path(), _headers, true, HTTPClient.METHOD_DELETE, "") else: _delete_queue.append(reference) -# -# Returns a deep copy of the current local copy of the data stored at this reference in the Firebase -# Realtime Database. -# + +## Returns a deep copy of the current local copy of the data stored at this reference in the Firebase +## Realtime Database. func get_data() -> Dictionary: if _store == null: - return { } + return {} return _store.get_data() -func _get_remaining_path(is_push : bool = true) -> String: + +func _get_remaining_path(is_push: bool = true) -> String: var remaining_path = "" - if !_filter_query or is_push: + if not _filter_query or is_push: remaining_path = _json_list_tag + _query_tag + _auth_tag + Firebase.Auth.auth.idtoken else: remaining_path = _json_list_tag + _query_tag + _get_filter() + _filter_tag + _auth_tag + Firebase.Auth.auth.idtoken if Firebase.emulating: - remaining_path += "&ns="+_config.projectId+"-default-rtdb" + remaining_path += "&ns=" + _config.projectId + "-default-rtdb" return remaining_path -func _get_list_url(with_port:bool = true) -> String: + +func _get_list_url(with_port: bool = true) -> String: var url = Firebase.Database._base_url.trim_suffix(_separator) if with_port and Firebase.emulating: url += ":" + _config.emulators.ports.realtimeDatabase @@ -156,10 +167,10 @@ func _get_list_url(with_port:bool = true) -> String: func _get_filter(): - if !_filter_query: + if not _filter_query: return "" # At the moment, this means you can't dynamically change your filter; I think it's okay to specify that in the rules. - if !_cached_filter: + if not _cached_filter: _cached_filter = "" if _filter_query.has(ORDER_BY): _cached_filter += ORDER_BY + _equal_tag + _escaped_quote + _filter_query[ORDER_BY] + _escaped_quote @@ -171,11 +182,10 @@ func _get_filter(): return _cached_filter -# -# Appropriately updates the current local copy of the data stored at this reference in the Firebase -# Realtime Database. -# -func _route_data(command : String, path : String, data) -> void: + +## Appropriately updates the current local copy of the data stored at this reference in the Firebase +## Realtime Database. +func _route_data(command: String, path: String, data) -> void: if command == _put_tag: _store.put(path, data) elif command == _patch_tag: @@ -183,7 +193,8 @@ func _route_data(command : String, path : String, data) -> void: elif command == _delete_tag: _store.delete(path, data) -func on_push_request_complete(result : int, response_code : int, headers : PoolStringArray, body : PoolByteArray) -> void: + +func on_push_request_complete(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void: if response_code == HTTPClient.RESPONSE_OK: emit_signal("push_successful") else: @@ -194,7 +205,7 @@ func on_push_request_complete(result : int, response_code : int, headers : PoolS return if _update_queue.size() > 0: var e = _update_queue.pop_front() - update(e['path'], e['data']) + update(e["path"], e["data"]) return if _delete_queue.size() > 0: delete(_delete_queue.pop_front()) diff --git a/addons/godot-firebase/database/resource.gd b/addons/godot-firebase/database/resource.gd index c273206..9b7e82d 100644 --- a/addons/godot-firebase/database/resource.gd +++ b/addons/godot-firebase/database/resource.gd @@ -5,12 +5,15 @@ tool class_name FirebaseResource extends Resource -var key : String + +var key: String var data -func _init(key : String, data) -> void: + +func _init(key: String, data) -> void: self.key = key.lstrip("/") self.data = data + func _to_string(): return "{ key:{key}, data:{data} }".format({key = key, data = data}) diff --git a/addons/godot-firebase/dynamiclinks/dynamiclinks.gd b/addons/godot-firebase/dynamiclinks/dynamiclinks.gd index fe6e4a3..d749458 100644 --- a/addons/godot-firebase/dynamiclinks/dynamiclinks.gd +++ b/addons/godot-firebase/dynamiclinks/dynamiclinks.gd @@ -7,29 +7,31 @@ tool class_name FirebaseDynamicLinks extends Node + signal dynamic_link_generated(link_result) signal generate_dynamic_link_error(error) -const _AUTHORIZATION_HEADER : String = "Authorization: Bearer " -const _API_VERSION : String = "v1" +const _AUTHORIZATION_HEADER: String = "Authorization: Bearer " +const _API_VERSION: String = "v1" -var request : int = -1 +var request: int = -1 -var _base_url : String = "" +var _base_url: String = "" -var _config : Dictionary = {} +var _config: Dictionary = {} -var _auth : Dictionary -var _request_list_node : HTTPRequest +var _auth: Dictionary +var _request_list_node: HTTPRequest -var _headers : PoolStringArray = [] +var _headers: PoolStringArray = [] enum Requests { NONE = -1, GENERATE - } +} + -func _set_config(config_json : Dictionary) -> void: +func _set_config(config_json: Dictionary) -> void: _config = config_json _request_list_node = HTTPRequest.new() _request_list_node.connect("request_completed", self, "_on_request_completed") @@ -37,20 +39,20 @@ func _set_config(config_json : Dictionary) -> void: _check_emulating() -func _check_emulating() -> void : +func _check_emulating() -> void: ## Check emulating if not Firebase.emulating: _base_url = "https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=%s" _base_url %= _config.apiKey else: - var port : String = _config.emulators.ports.dynamicLinks + var port: String = _config.emulators.ports.dynamicLinks if port == "": Firebase._printerr("You are in 'emulated' mode, but the port for Dynamic Links has not been configured.") else: - _base_url = "http://localhost:{port}/{version}/".format({ version = _API_VERSION, port = port }) + _base_url = "http://localhost:{port}/{version}/".format({version = _API_VERSION, port = port}) -var _link_request_body : Dictionary = { +var _link_request_body: Dictionary = { "dynamicLinkInfo": { "domainUriPrefix": "", "link": "", @@ -60,16 +62,17 @@ var _link_request_body : Dictionary = { "iosInfo": { "iosBundleId": "" } - }, + }, "suffix": { "option": "" } - } +} + ## @args log_link, APN, IBI, is_unguessable ## This function is used to generate a dynamic link using the Firebase REST API ## It will return a JSON with the shortened link -func generate_dynamic_link(long_link : String, APN : String, IBI : String, is_unguessable : bool) -> void: +func generate_dynamic_link(long_link: String, APN: String, IBI: String, is_unguessable: bool) -> void: if not _config.domainUriPrefix or _config.domainUriPrefix == "": emit_signal("generate_dynamic_link_error", "You're missing the domainUriPrefix in config file! Error!") Firebase._printerr("You're missing the domainUriPrefix in config file! Error!") @@ -86,7 +89,8 @@ func generate_dynamic_link(long_link : String, APN : String, IBI : String, is_un _link_request_body.suffix.option = "SHORT" _request_list_node.request(_base_url, _headers, true, HTTPClient.METHOD_POST, JSON.print(_link_request_body)) -func _on_request_completed(result : int, response_code : int, headers : PoolStringArray, body : PoolByteArray) -> void: + +func _on_request_completed(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void: var result_body = JSON.parse(body.get_string_from_utf8()) if result_body.error: emit_signal("generate_dynamic_link_error", result_body.error_string) @@ -97,11 +101,14 @@ func _on_request_completed(result : int, response_code : int, headers : PoolStri emit_signal("dynamic_link_generated", result_body.shortLink) request = Requests.NONE -func _on_FirebaseAuth_login_succeeded(auth_result : Dictionary) -> void: + +func _on_FirebaseAuth_login_succeeded(auth_result: Dictionary) -> void: _auth = auth_result -func _on_FirebaseAuth_token_refresh_succeeded(auth_result : Dictionary) -> void: + +func _on_FirebaseAuth_token_refresh_succeeded(auth_result: Dictionary) -> void: _auth = auth_result + func _on_FirebaseAuth_logout() -> void: _auth = {} diff --git a/addons/godot-firebase/firebase/firebase.gd b/addons/godot-firebase/firebase/firebase.gd index d53d0b7..e8cd0ec 100644 --- a/addons/godot-firebase/firebase/firebase.gd +++ b/addons/godot-firebase/firebase/firebase.gd @@ -11,40 +11,41 @@ tool extends Node -const _ENVIRONMENT_VARIABLES : String = "firebase/environment_variables" -const _EMULATORS_PORTS : String = "firebase/emulators/ports" -const _AUTH_PROVIDERS : String = "firebase/auth_providers" + +const _ENVIRONMENT_VARIABLES: String = "firebase/environment_variables" +const _EMULATORS_PORTS: String = "firebase/emulators/ports" +const _AUTH_PROVIDERS: String = "firebase/auth_providers" ## @type FirebaseAuth ## The Firebase Authentication API. -onready var Auth : FirebaseAuth = $Auth +onready var Auth: FirebaseAuth = $Auth ## @type FirebaseFirestore ## The Firebase Firestore API. -onready var Firestore : FirebaseFirestore = $Firestore +onready var Firestore: FirebaseFirestore = $Firestore ## @type FirebaseDatabase ## The Firebase Realtime Database API. -onready var Database : FirebaseDatabase = $Database +onready var Database: FirebaseDatabase = $Database ## @type FirebaseStorage ## The Firebase Storage API. -onready var Storage : FirebaseStorage = $Storage +onready var Storage: FirebaseStorage = $Storage ## @type FirebaseDynamicLinks ## The Firebase Dynamic Links API. -onready var DynamicLinks : FirebaseDynamicLinks = $DynamicLinks +onready var DynamicLinks: FirebaseDynamicLinks = $DynamicLinks ## @type FirebaseFunctions ## The Firebase Cloud Functions API -onready var Functions : FirebaseFunctions = $Functions +onready var Functions: FirebaseFunctions = $Functions -export var emulating : bool = false +export var emulating: bool = false # Configuration used by all files in this project # These values can be found in your Firebase Project # See the README on Github for how to access -var _config : Dictionary = { +var _config: Dictionary = { "apiKey": "", "authDomain": "", "databaseURL": "", @@ -54,41 +55,43 @@ var _config : Dictionary = { "appId": "", "measurementId": "", "clientId": "", - "clientSecret" : "", - "domainUriPrefix" : "", - "functionsGeoZone" : "", - "cacheLocation":"user://.firebase_cache", + "clientSecret": "", + "domainUriPrefix": "", + "functionsGeoZone": "", + "cacheLocation": "user://.firebase_cache", "emulators": { - "ports" : { - "authentication" : "", - "firestore" : "", - "realtimeDatabase" : "", - "functions" : "", - "storage" : "", - "dynamicLinks" : "" + "ports": { + "authentication": "", + "firestore": "", + "realtimeDatabase": "", + "functions": "", + "storage": "", + "dynamicLinks": "" } }, - "workarounds":{ + "workarounds": { "database_connection_closed_issue": false, # fixes https://github.com/firebase/firebase-tools/issues/3329 }, "auth_providers": { - "facebook_id":"", - "facebook_secret":"", - "github_id":"", - "github_secret":"", - "twitter_id":"", - "twitter_secret":"" + "facebook_id": "", + "facebook_secret": "", + "github_id": "", + "github_secret": "", + "twitter_id": "", + "twitter_secret": "" } } + func _ready() -> void: _load_config() -func set_emulated(emulating : bool = true) -> void: +func set_emulated(emulating: bool = true) -> void: self.emulating = emulating _check_emulating() + func _check_emulating() -> void: if emulating: print("[Firebase] You are now in 'emulated' mode: the services you are using will try to connect to your local emulators, if available.") @@ -96,6 +99,7 @@ func _check_emulating() -> void: if module.has_method("_check_emulating"): module._check_emulating() + func _load_config() -> void: if _config.apiKey != "" and _config.authDomain != "": pass @@ -111,7 +115,7 @@ func _load_config() -> void: for provider in _config[key].keys(): _config[key][provider] = env.get_value(_AUTH_PROVIDERS, provider) else: - var value : String = env.get_value(_ENVIRONMENT_VARIABLES, key, "") + var value: String = env.get_value(_ENVIRONMENT_VARIABLES, key, "") if value == "": _print("The value for `%s` is not configured. If you are not planning to use it, ignore this message." % key) else: @@ -121,6 +125,7 @@ func _load_config() -> void: _setup_modules() + func _setup_modules() -> void: for module in get_children(): module._set_config(_config) @@ -134,8 +139,9 @@ func _setup_modules() -> void: # ------------- -func _printerr(error : String) -> void: - printerr("[Firebase Error] >> "+error) +func _printerr(error: String) -> void: + printerr("[Firebase Error] >> " + error) + -func _print(msg : String) -> void: - print("[Firebase] >> "+msg) +func _print(msg: String) -> void: + print("[Firebase] >> " + msg) diff --git a/addons/godot-firebase/firestore/firestore_document.gd b/addons/godot-firebase/firestore/firestore_document.gd index 87e7e51..3411eba 100644 --- a/addons/godot-firebase/firestore/firestore_document.gd +++ b/addons/godot-firebase/firestore/firestore_document.gd @@ -6,17 +6,18 @@ tool class_name FirestoreDocument extends Reference + # A FirestoreDocument objects that holds all important values for a Firestore Document, # @doc_name = name of the Firestore Document, which is the request PATH # @doc_fields = fields held by Firestore Document, in APIs format # created when requested from a `collection().get()` call +var document: Dictionary # the Document itself +var doc_fields: Dictionary # only .fields +var doc_name: String # only .name +var create_time: String # createTime -var document : Dictionary # the Document itself -var doc_fields : Dictionary # only .fields -var doc_name : String # only .name -var create_time : String # createTime -func _init(doc : Dictionary = {}, _doc_name : String = "", _doc_fields : Dictionary = {}) -> void: +func _init(doc: Dictionary = {}, _doc_name: String = "", _doc_fields: Dictionary = {}) -> void: self.document = doc self.doc_name = doc.name if self.doc_name.count("/") > 2: @@ -24,12 +25,13 @@ func _init(doc : Dictionary = {}, _doc_name : String = "", _doc_fields : Diction self.doc_fields = fields2dict(self.document) self.create_time = doc.createTime + # Pass a dictionary { 'key' : 'value' } to format it in a APIs usable .fields # Field Path using the "dot" (`.`) notation are supported: # ex. { "PATH.TO.SUBKEY" : "VALUE" } ==> { "PATH" : { "TO" : { "SUBKEY" : "VALUE" } } } -static func dict2fields(dict : Dictionary) -> Dictionary: - var fields : Dictionary = {} - var var_type : String = "" +static func dict2fields(dict: Dictionary) -> Dictionary: + var fields: Dictionary = {} + var var_type: String = "" for field in dict.keys(): var field_value = dict[field] if "." in field: @@ -37,7 +39,7 @@ static func dict2fields(dict : Dictionary) -> Dictionary: field = keys.pop_front() keys.invert() for key in keys: - field_value = { key : field_value } + field_value = {key: field_value} match typeof(field_value): TYPE_NIL: var_type = "nullValue" TYPE_BOOL: var_type = "booleanValue" @@ -59,36 +61,38 @@ static func dict2fields(dict : Dictionary) -> Dictionary: for key in field_value["fields"].keys(): fields[field]["mapValue"]["fields"][key] = field_value["fields"][key] else: - fields[field] = { var_type : field_value } - return {'fields' : fields} + fields[field] = {var_type: field_value} + return {"fields": fields} + # Pass the .fields inside a Firestore Document to print out the Dictionary { 'key' : 'value' } -static func fields2dict(doc : Dictionary) -> Dictionary: - var dict : Dictionary = {} +static func fields2dict(doc: Dictionary) -> Dictionary: + var dict: Dictionary = {} if doc.has("fields"): - for field in (doc.fields).keys(): - if (doc.fields)[field].has("mapValue"): - dict[field] = fields2dict((doc.fields)[field].mapValue) - elif (doc.fields)[field].has("timestampValue"): - dict[field] = timestamp2dict((doc.fields)[field].timestampValue) - elif (doc.fields)[field].has("arrayValue"): - dict[field] = fields2array((doc.fields)[field].arrayValue) - elif (doc.fields)[field].has("integerValue"): - dict[field] = (doc.fields)[field].values()[0] as int - elif (doc.fields)[field].has("doubleValue"): - dict[field] = (doc.fields)[field].values()[0] as float - elif (doc.fields)[field].has("booleanValue"): - dict[field] = (doc.fields)[field].values()[0] as bool - elif (doc.fields)[field].has("nullValue"): + for field in doc.fields.keys(): + if doc.fields[field].has("mapValue"): + dict[field] = fields2dict(doc.fields[field].mapValue) + elif doc.fields[field].has("timestampValue"): + dict[field] = timestamp2dict(doc.fields[field].timestampValue) + elif doc.fields[field].has("arrayValue"): + dict[field] = fields2array(doc.fields[field].arrayValue) + elif doc.fields[field].has("integerValue"): + dict[field] = doc.fields[field].values()[0] as int + elif doc.fields[field].has("doubleValue"): + dict[field] = doc.fields[field].values()[0] as float + elif doc.fields[field].has("booleanValue"): + dict[field] = doc.fields[field].values()[0] as bool + elif doc.fields[field].has("nullValue"): dict[field] = null else: - dict[field] = (doc.fields)[field].values()[0] + dict[field] = doc.fields[field].values()[0] return dict + # Pass an Array to parse it to a Firebase arrayValue -static func array2fields(array : Array) -> Array: - var fields : Array = [] - var var_type : String = "" +static func array2fields(array: Array) -> Array: + var fields: Array = [] + var var_type: String = "" for field in array: match typeof(field): TYPE_DICTIONARY: @@ -105,12 +109,13 @@ static func array2fields(array : Array) -> Array: TYPE_STRING: var_type = "stringValue" TYPE_ARRAY: var_type = "arrayValue" - fields.append({ var_type : field }) + fields.append({var_type: field}) return fields + # Pass a Firebase arrayValue Dictionary to convert it back to an Array -static func fields2array(array : Dictionary) -> Array: - var fields : Array = [] +static func fields2array(array: Dictionary) -> Array: + var fields: Array = [] if array.has("values"): for field in array.values: var item @@ -134,28 +139,31 @@ static func fields2array(array : Dictionary) -> Array: fields.append(item) return fields + # Converts a gdscript Dictionary (most likely obtained with OS.get_datetime()) to a Firebase Timestamp -static func dict2timestamp(dict : Dictionary) -> String: - dict.erase('weekday') - dict.erase('dst') - var dict_values : Array = dict.values() +static func dict2timestamp(dict: Dictionary) -> String: + dict.erase("weekday") + dict.erase("dst") + var dict_values: Array = dict.values() return "%04d-%02d-%02dT%02d:%02d:%02d.00Z" % dict_values + # Converts a Firebase Timestamp back to a gdscript Dictionary -static func timestamp2dict(timestamp : String) -> Dictionary: - var datetime : Dictionary = {year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0} - var dict : PoolStringArray = timestamp.split("T")[0].split("-") +static func timestamp2dict(timestamp: String) -> Dictionary: + var datetime: Dictionary = {year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0} + var dict: PoolStringArray = timestamp.split("T")[0].split("-") dict.append_array(timestamp.split("T")[1].split(":")) - for value in dict.size() : + for value in dict.size(): datetime[datetime.keys()[value]] = int(dict[value]) return datetime -static func is_field_timestamp(field : Dictionary) -> bool: - return field.has_all(['year','month','day','hour','minute','second']) + +static func is_field_timestamp(field: Dictionary) -> bool: + return field.has_all(["year", "month", "day", "hour", "minute", "second"]) + # Call print(document) to return directly this document formatted func _to_string() -> String: - return ("doc_name: {doc_name}, \ndoc_fields: {doc_fields}, \ncreate_time: {create_time}\n").format( - {doc_name = self.doc_name, - doc_fields = self.doc_fields, - create_time = self.create_time}) + return "doc_name: {doc_name}, \ndoc_fields: {doc_fields}, \ncreate_time: {create_time}\n".format( + {doc_name = self.doc_name, doc_fields = self.doc_fields, create_time = self.create_time} + ) diff --git a/addons/godot-firebase/functions/function_task.gd b/addons/godot-firebase/functions/function_task.gd index f82e4dd..461e005 100644 --- a/addons/godot-firebase/functions/function_task.gd +++ b/addons/godot-firebase/functions/function_task.gd @@ -9,11 +9,11 @@ ## [code]var result : Array = yield(Firebase.Firestore, "result_query")[/code] ## ## @tutorial https://github.com/GodotNuts/GodotFirebase/wiki/Firestore#FirestoreTask - tool class_name FunctionTask extends Reference + ## Emitted when a request is completed. The request can be successful or not successful: if not, an [code]error[/code] Dictionary will be passed as a result. ## @arg-types Variant signal task_finished(result) @@ -31,17 +31,18 @@ var data: Dictionary var error: Dictionary ## Whether the data came from cache. -var from_cache : bool = false +var from_cache: bool = false + +var _response_headers: PoolStringArray = PoolStringArray() +var _response_code: int = 0 -var _response_headers : PoolStringArray = PoolStringArray() -var _response_code : int = 0 +var _method: int = -1 +var _url: String = "" +var _fields: String = "" +var _headers: PoolStringArray = [] -var _method : int = -1 -var _url : String = "" -var _fields : String = "" -var _headers : PoolStringArray = [] -func _on_request_completed(result : int, response_code : int, headers : PoolStringArray, body : PoolByteArray) -> void: +func _on_request_completed(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void: var bod if validate_json(body.get_string_from_utf8()).empty(): bod = JSON.parse(body.get_string_from_utf8()).result @@ -52,15 +53,15 @@ func _on_request_completed(result : int, response_code : int, headers : PoolStri from_cache = offline data = bod - if response_code == HTTPClient.RESPONSE_OK and data!=null: + if response_code == HTTPClient.RESPONSE_OK and data != null: emit_signal("function_executed", result, data) else: - error = {result=result, response_code=response_code, data=data} + error = {result = result, response_code = response_code, data = data} emit_signal("task_error", result, response_code, str(data)) emit_signal("task_finished", data) -# + #func _handle_cache(offline : bool, data, encrypt_key : String, cache_path : String, body) -> Dictionary: # if offline: # Firebase._printerr("Offline queries are currently unsupported!") diff --git a/addons/godot-firebase/plugin.gd b/addons/godot-firebase/plugin.gd index d21b2e2..e0f7678 100644 --- a/addons/godot-firebase/plugin.gd +++ b/addons/godot-firebase/plugin.gd @@ -1,8 +1,10 @@ tool extends EditorPlugin + func _enter_tree() -> void: add_autoload_singleton("Firebase", "res://addons/godot-firebase/firebase/firebase.tscn") + func _exit_tree() -> void: remove_autoload_singleton("Firebase") diff --git a/addons/godot-firebase/storage/storage.gd b/addons/godot-firebase/storage/storage.gd index 56da0ea..af7c22a 100644 --- a/addons/godot-firebase/storage/storage.gd +++ b/addons/godot-firebase/storage/storage.gd @@ -8,7 +8,8 @@ tool class_name FirebaseStorage extends Node -const _API_VERSION : String = "v0" + +const _API_VERSION: String = "v0" ## @arg-types int, int, PoolStringArray ## @arg-enums HTTPRequest.Result, HTTPClient.ResponseCode @@ -21,36 +22,38 @@ signal task_successful(result, response_code, data) signal task_failed(result, response_code, data) ## The current storage bucket the Storage API is referencing. -var bucket : String +var bucket: String ## @default false ## Whether a task is currently being processed. -var requesting : bool = false +var requesting: bool = false + +var _auth: Dictionary +var _config: Dictionary -var _auth : Dictionary -var _config : Dictionary +var _references: Dictionary = {} -var _references : Dictionary = {} +var _base_url: String = "" +var _extended_url: String = "/[API_VERSION]/b/[APP_ID]/o/[FILE_PATH]" +var _root_ref: StorageReference -var _base_url : String = "" -var _extended_url : String = "/[API_VERSION]/b/[APP_ID]/o/[FILE_PATH]" -var _root_ref : StorageReference +var _http_client: HTTPClient = HTTPClient.new() +var _pending_tasks: Array = [] -var _http_client : HTTPClient = HTTPClient.new() -var _pending_tasks : Array = [] +var _current_task: StorageTask +var _response_code: int +var _response_headers: PoolStringArray +var _response_data: PoolByteArray +var _content_length: int +var _reading_body: bool -var _current_task : StorageTask -var _response_code : int -var _response_headers : PoolStringArray -var _response_data : PoolByteArray -var _content_length : int -var _reading_body : bool -func _notification(what : int) -> void: +func _notification(what: int) -> void: if what == NOTIFICATION_INTERNAL_PROCESS: _internal_process(get_process_delta_time()) -func _internal_process(_delta : float) -> void: + +func _internal_process(_delta: float) -> void: if not requesting: set_process_internal(false) return @@ -110,6 +113,7 @@ func _internal_process(_delta : float) -> void: HTTPClient.STATUS_SSL_HANDSHAKE_ERROR: _finish_request(HTTPRequest.RESULT_SSL_HANDSHAKE_ERROR) + ## @args path ## @arg-defaults "" ## @return StorageReference @@ -138,7 +142,8 @@ func ref(path := "") -> StorageReference: else: return _references[path] -func _set_config(config_json : Dictionary) -> void: + +func _set_config(config_json: Dictionary) -> void: _config = config_json if bucket != _config.storageBucket: bucket = _config.storageBucket @@ -146,19 +151,19 @@ func _set_config(config_json : Dictionary) -> void: _check_emulating() -func _check_emulating() -> void : +func _check_emulating() -> void: ## Check emulating if not Firebase.emulating: _base_url = "https://firebasestorage.googleapis.com" else: - var port : String = _config.emulators.ports.storage + var port: String = _config.emulators.ports.storage if port == "": Firebase._printerr("You are in 'emulated' mode, but the port for Storage has not been configured.") else: - _base_url = "http://localhost:{port}/{version}/".format({ version = _API_VERSION, port = port }) + _base_url = "http://localhost:{port}/{version}/".format({version = _API_VERSION, port = port}) -func _upload(data : PoolByteArray, headers : PoolStringArray, ref : StorageReference, meta_only : bool) -> StorageTask: +func _upload(data: PoolByteArray, headers: PoolStringArray, ref: StorageReference, meta_only: bool) -> StorageTask: if not (_config and _auth): return null @@ -171,7 +176,8 @@ func _upload(data : PoolByteArray, headers : PoolStringArray, ref : StorageRefer _process_request(task) return task -func _download(ref : StorageReference, meta_only : bool, url_only : bool) -> StorageTask: + +func _download(ref: StorageReference, meta_only: bool, url_only: bool) -> StorageTask: if not (_config and _auth): return null @@ -205,7 +211,8 @@ func _download(ref : StorageReference, meta_only : bool, url_only : bool) -> Sto return task -func _list(ref : StorageReference, list_all : bool) -> StorageTask: + +func _list(ref: StorageReference, list_all: bool) -> StorageTask: if not (_config and _auth): return null @@ -216,7 +223,8 @@ func _list(ref : StorageReference, list_all : bool) -> StorageTask: _process_request(task) return task -func _delete(ref : StorageReference) -> StorageTask: + +func _delete(ref: StorageReference) -> StorageTask: if not (_config and _auth): return null @@ -227,7 +235,8 @@ func _delete(ref : StorageReference) -> StorageTask: _process_request(task) return task -func _process_request(task : StorageTask) -> void: + +func _process_request(task: StorageTask) -> void: if requesting: _pending_tasks.append(task) return @@ -248,7 +257,8 @@ func _process_request(task : StorageTask) -> void: _http_client.close() set_process_internal(true) -func _finish_request(result : int) -> void: + +func _finish_request(result: int) -> void: var task := _current_task requesting = false @@ -267,25 +277,25 @@ func _finish_request(result : int) -> void: task.data = null StorageTask.Task.TASK_DOWNLOAD_URL: - var json : Dictionary = JSON.parse(_response_data.get_string_from_utf8()).result + var json: Dictionary = JSON.parse(_response_data.get_string_from_utf8()).result if json and json.has("downloadTokens"): task.data = _base_url + _get_file_url(task.ref) + "?alt=media&token=" + json.downloadTokens else: task.data = "" StorageTask.Task.TASK_LIST, StorageTask.Task.TASK_LIST_ALL: - var json : Dictionary = JSON.parse(_response_data.get_string_from_utf8()).result + var json: Dictionary = JSON.parse(_response_data.get_string_from_utf8()).result var items := [] if json and json.has("items"): for item in json.items: - var item_name : String = item.name + var item_name: String = item.name if item.bucket != bucket: continue if not item_name.begins_with(task.ref.full_path): continue if task.action == StorageTask.Task.TASK_LIST: - var dir_path : Array = item_name.split("/") - var slash_count : int = task.ref.full_path.count("/") + var dir_path: Array = item_name.split("/") + var slash_count: int = task.ref.full_path.count("/") item_name = "" for i in slash_count + 1: item_name += dir_path[i] @@ -300,7 +310,7 @@ func _finish_request(result : int) -> void: _: task.data = JSON.parse(_response_data.get_string_from_utf8()).result - var next_task : StorageTask + var next_task: StorageTask if not _pending_tasks.empty(): next_task = _pending_tasks.pop_front() @@ -321,13 +331,14 @@ func _finish_request(result : int) -> void: break -func _get_file_url(ref : StorageReference) -> String: +func _get_file_url(ref: StorageReference) -> String: var url := _extended_url.replace("[APP_ID]", ref.bucket) url = url.replace("[API_VERSION]", _API_VERSION) return url.replace("[FILE_PATH]", ref.full_path.replace("/", "%2F")) + # Removes any "../" or "./" in the file path. -func _simplify_path(path : String) -> String: +func _simplify_path(path: String) -> String: var dirs := path.split("/") var new_dirs := [] for dir in dirs: @@ -343,11 +354,14 @@ func _simplify_path(path : String) -> String: new_path = new_path.replace("\\", "/") return new_path -func _on_FirebaseAuth_login_succeeded(auth_token : Dictionary) -> void: + +func _on_FirebaseAuth_login_succeeded(auth_token: Dictionary) -> void: _auth = auth_token -func _on_FirebaseAuth_token_refresh_succeeded(auth_result : Dictionary) -> void: + +func _on_FirebaseAuth_token_refresh_succeeded(auth_result: Dictionary) -> void: _auth = auth_result + func _on_FirebaseAuth_logout() -> void: _auth = {} diff --git a/addons/godot-firebase/storage/storage_reference.gd b/addons/godot-firebase/storage/storage_reference.gd index 56a41f5..f47b786 100644 --- a/addons/godot-firebase/storage/storage_reference.gd +++ b/addons/godot-firebase/storage/storage_reference.gd @@ -6,6 +6,7 @@ tool class_name StorageReference extends Reference + ## The default MIME type to use when uploading a file. ## Data sent with this type are interpreted as plain binary data. Note that firebase will generate an MIME type based on the file extenstion if none is provided. const DEFAULT_MIME_TYPE = "application/octet-stream" @@ -42,23 +43,23 @@ const MIME_TYPES = { ## @default "" ## The stroage bucket this referenced file/folder is located in. -var bucket : String = "" +var bucket: String = "" ## @default "" ## The path to the file/folder relative to [member bucket]. -var full_path : String = "" +var full_path: String = "" ## @default "" ## The name of the file/folder, including any file extension. ## Example: If the [member full_path] is [code]images/user/image.png[/code], then the [member name] would be [code]image.png[/code]. -var name : String = "" +var name: String = "" ## The parent [StorageReference] one level up the file hierarchy. ## If the current [StorageReference] is the root (i.e. the [member full_path] is [code]""[/code]) then the [member parent] will be [code]null[/code]. -var parent : StorageReference +var parent: StorageReference ## The root [StorageReference]. -var root : StorageReference +var root: StorageReference ## @type FirebaseStorage ## The Storage API that created this [StorageReference] to begin with. @@ -67,20 +68,22 @@ var storage # FirebaseStorage (Can't static type due to cyclic reference) ## @default false ## Whether this [StorageReference] is valid. None of the functions will work when in an invalid state. ## It is set to false when [method delete] is called. -var valid : bool = false +var valid: bool = false + ## @args path ## @return StorageReference ## Returns a reference to another [StorageReference] relative to this one. -func child(path : String) -> StorageReference: +func child(path: String) -> StorageReference: if not valid: return null return storage.ref(full_path.plus_file(path)) + ## @args data, metadata ## @return StorageTask ## Makes an attempt to upload data to the referenced file location. Status on this task is found in the returned [StorageTask]. -func put_data(data : PoolByteArray, metadata := {}) -> StorageTask: +func put_data(data: PoolByteArray, metadata := {}) -> StorageTask: if not valid: return null if not "Content-Length" in metadata and OS.get_name() != "HTML5": @@ -92,16 +95,18 @@ func put_data(data : PoolByteArray, metadata := {}) -> StorageTask: return storage._upload(data, headers, self, false) + ## @args data, metadata ## @return StorageTask ## Like [method put_data], but [code]data[/code] is a [String]. -func put_string(data : String, metadata := {}) -> StorageTask: +func put_string(data: String, metadata := {}) -> StorageTask: return put_data(data.to_utf8(), metadata) + ## @args file_path, metadata ## @return StorageTask ## Like [method put_data], but the data comes from a file at [code]file_path[/code]. -func put_file(file_path : String, metadata := {}) -> StorageTask: +func put_file(file_path: String, metadata := {}) -> StorageTask: var file := File.new() file.open(file_path, File.READ) var data := file.get_buffer(file.get_len()) @@ -112,6 +117,7 @@ func put_file(file_path : String, metadata := {}) -> StorageTask: return put_data(data, metadata) + ## @return StorageTask ## Makes an attempt to download the files from the referenced file location. Status on this task is found in the returned [StorageTask]. func get_data() -> StorageTask: @@ -120,6 +126,7 @@ func get_data() -> StorageTask: storage._download(self, false, false) return storage._pending_tasks[-1] + ## @return StorageTask ## Like [method get_data], but the data in the returned [StorageTask] comes in the form of a [String]. func get_string() -> StorageTask: @@ -127,6 +134,7 @@ func get_string() -> StorageTask: task.connect("task_finished", self, "_on_task_finished", [task, "stringify"]) return task + ## @return StorageTask ## Attempts to get the download url that points to the referenced file's data. Using the url directly may require an authentication header. Status on this task is found in the returned [StorageTask]. func get_download_url() -> StorageTask: @@ -134,6 +142,7 @@ func get_download_url() -> StorageTask: return null return storage._download(self, false, true) + ## @return StorageTask ## Attempts to get the metadata of the referenced file. Status on this task is found in the returned [StorageTask]. func get_metadata() -> StorageTask: @@ -141,16 +150,18 @@ func get_metadata() -> StorageTask: return null return storage._download(self, true, false) + ## @args metadata ## @return StorageTask ## Attempts to update the metadata of the referenced file. Any field with a value of [code]null[/code] will be deleted on the server end. Status on this task is found in the returned [StorageTask]. -func update_metadata(metadata : Dictionary) -> StorageTask: +func update_metadata(metadata: Dictionary) -> StorageTask: if not valid: return null var data := JSON.print(metadata).to_utf8() var headers := PoolStringArray(["Accept: application/json"]) return storage._upload(data, headers, self, true) + ## @return StorageTask ## Attempts to get the list of files and/or folders under the referenced folder This function is not nested unlike [method list_all]. Status on this task is found in the returned [StorageTask]. func list() -> StorageTask: @@ -158,6 +169,7 @@ func list() -> StorageTask: return null return storage._list(self, false) + ## @return StorageTask ## Attempts to get the list of files and/or folders under the referenced folder This function is nested unlike [method list]. Status on this task is found in the returned [StorageTask]. func list_all() -> StorageTask: @@ -165,6 +177,7 @@ func list_all() -> StorageTask: return null return storage._list(self, true) + ## @return StorageTask ## Attempts to delete the referenced file/folder. If successful, the reference will become invalid And can no longer be used. If you need to reference this location again, make a new reference with [method StorageTask.ref]. Status on this task is found in the returned [StorageTask]. func delete() -> StorageTask: @@ -172,13 +185,15 @@ func delete() -> StorageTask: return null return storage._delete(self) + func _to_string() -> String: var string := "gs://%s/%s" % [bucket, full_path] if not valid: string += " [Invalid Reference]" return string -func _on_task_finished(task : StorageTask, action : String) -> void: + +func _on_task_finished(task: StorageTask, action: String) -> void: match action: "stringify": if typeof(task.data) == TYPE_RAW_ARRAY: diff --git a/addons/godot-firebase/storage/storage_task.gd b/addons/godot-firebase/storage/storage_task.gd index 213b371..3efc353 100644 --- a/addons/godot-firebase/storage/storage_task.gd +++ b/addons/godot-firebase/storage/storage_task.gd @@ -5,6 +5,7 @@ tool class_name StorageTask extends Reference + enum Task { TASK_UPLOAD, TASK_UPLOAD_META, @@ -28,7 +29,7 @@ var ref # Storage Reference (Can't static type due to cyclic reference) ## @default -1 ## @setter set_action ## The kind of operation this [StorageTask] is keeping track of. -var action : int = -1 setget set_action +var action: int = -1 setget set_action ## @default PoolByteArray() ## Data that the tracked task will/has returned. @@ -36,16 +37,16 @@ var data = PoolByteArray() # data can be of any type. ## @default 0.0 ## The percentage of data that has been received. -var progress : float = 0.0 +var progress: float = 0.0 ## @default -1 ## @enum HTTPRequest.Result ## The resulting status of the task. Anyting other than [constant HTTPRequest.RESULT_SUCCESS] means an error has occured. -var result : int = -1 +var result: int = -1 ## @default false ## Whether the task is finished processing. -var finished : bool = false +var finished: bool = false ## @default PoolStringArray() ## The returned HTTP response headers. @@ -54,13 +55,14 @@ var response_headers := PoolStringArray() ## @default 0 ## @enum HTTPClient.ResponseCode ## The returned HTTP response code. -var response_code : int = 0 +var response_code: int = 0 + +var _method: int = -1 +var _url: String = "" +var _headers: PoolStringArray = PoolStringArray() -var _method : int = -1 -var _url : String = "" -var _headers : PoolStringArray = PoolStringArray() -func set_action(value : int) -> void: +func set_action(value: int) -> void: action = value match action: Task.TASK_UPLOAD: diff --git a/addons/http-sse-client/HTTPSSEClient.gd b/addons/http-sse-client/HTTPSSEClient.gd index f15b395..ea77a34 100644 --- a/addons/http-sse-client/HTTPSSEClient.gd +++ b/addons/http-sse-client/HTTPSSEClient.gd @@ -1,6 +1,7 @@ tool extends Node + signal new_sse_event(headers, event, data) signal connected signal connection_error(error) @@ -22,7 +23,8 @@ var connection_in_progress = false var is_requested = false var response_body = PoolByteArray() -func connect_to_host(domain : String, url_after_domain : String, port : int = -1, use_ssl : bool = false, verify_host : bool = true): + +func connect_to_host(domain: String, url_after_domain: String, port: int = -1, use_ssl: bool = false, verify_host: bool = true): self.domain = domain self.url_after_domain = url_after_domain self.port = port @@ -30,6 +32,7 @@ func connect_to_host(domain : String, url_after_domain : String, port : int = -1 self.verify_host = verify_host told_to_connect = true + func attempt_to_connect(): var err = httpclient.connect_to_host(domain, port, use_ssl, verify_host) if err == OK: @@ -38,6 +41,7 @@ func attempt_to_connect(): else: emit_signal("connection_error", str(err)) + func attempt_to_request(httpclient_status): if httpclient_status == HTTPClient.STATUS_CONNECTING or httpclient_status == HTTPClient.STATUS_RESOLVING: return @@ -47,6 +51,7 @@ func attempt_to_request(httpclient_status): if err == OK: is_requested = true + func _parse_response_body(headers): var body = response_body.get_string_from_utf8() if body: @@ -56,23 +61,23 @@ func _parse_response_body(headers): if response_body.size() > 0 and result: # stop here if the value doesn't parse response_body.resize(0) emit_signal("new_sse_event", headers, event_data.event, result) - else: - if event_data.event != continue_internal: - response_body.resize(0) + elif event_data.event != continue_internal: + response_body.resize(0) + func _process(delta): - if !told_to_connect: + if not told_to_connect: return - if !is_connected: - if !connection_in_progress: + if not is_connected: + if not connection_in_progress: attempt_to_connect() connection_in_progress = true return httpclient.poll() var httpclient_status = httpclient.get_status() - if !is_requested: + if not is_requested: attempt_to_request(httpclient_status) return @@ -82,7 +87,7 @@ func _process(delta): if httpclient_status == HTTPClient.STATUS_BODY: httpclient.poll() var chunk = httpclient.read_response_body_chunk() - if(chunk.size() == 0): + if chunk.size() == 0: return else: response_body = response_body + chunk @@ -100,7 +105,8 @@ func _process(delta): if response_body.size() > 0: _parse_response_body(headers) -func get_event_data(body : String) -> Dictionary: + +func get_event_data(body: String) -> Dictionary: var result = {} var event_idx = body.find(event_tag) if event_idx == -1: @@ -120,6 +126,7 @@ func get_event_data(body : String) -> Dictionary: result["data"] = data return result + func _exit_tree(): if httpclient: httpclient.close() diff --git a/addons/http-sse-client/httpsseclient_plugin.gd b/addons/http-sse-client/httpsseclient_plugin.gd index bda975a..26dda6c 100644 --- a/addons/http-sse-client/httpsseclient_plugin.gd +++ b/addons/http-sse-client/httpsseclient_plugin.gd @@ -1,8 +1,10 @@ tool extends EditorPlugin + func _enter_tree(): add_custom_type("HTTPSSEClient", "Node", preload("HTTPSSEClient.gd"), preload("icon.png")) + func _exit_tree(): remove_custom_type("HTTPSSEClient") diff --git a/addons/silicon.util.custom_docs/class_doc_generator.gd b/addons/silicon.util.custom_docs/class_doc_generator.gd index b0f8ab5..e703056 100644 --- a/addons/silicon.util.custom_docs/class_doc_generator.gd +++ b/addons/silicon.util.custom_docs/class_doc_generator.gd @@ -1,6 +1,7 @@ tool extends Reference + var _pending_docs := {} var _docs_queue := [] @@ -283,6 +284,7 @@ func _generate(doc: ClassDocItem) -> String: annotations.clear() return "" + func _create_method_doc(name: String, script: Script = null, method := {}) -> MethodDocItem: if method.empty(): var methods := script.get_script_method_list() diff --git a/addons/silicon.util.custom_docs/doc_exporter/doc_exporter.gd b/addons/silicon.util.custom_docs/doc_exporter/doc_exporter.gd index 0f15a97..6591e71 100644 --- a/addons/silicon.util.custom_docs/doc_exporter/doc_exporter.gd +++ b/addons/silicon.util.custom_docs/doc_exporter/doc_exporter.gd @@ -1,8 +1,9 @@ ## The base class for every document exporter. ## @contribute https://placeholder_contribute.com tool -extends Reference class_name DocExporter +extends Reference + ## @virtual ## @args doc diff --git a/addons/silicon.util.custom_docs/doc_item/argument_doc_item.gd b/addons/silicon.util.custom_docs/doc_item/argument_doc_item.gd index 4155ea3..5107bf1 100644 --- a/addons/silicon.util.custom_docs/doc_item/argument_doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/argument_doc_item.gd @@ -1,8 +1,9 @@ ## An object that contains documentation data about an argument of a signal or method. ## @contribute https://placeholder_contribute.com tool -extends DocItem class_name ArgumentDocItem +extends DocItem + ## @default "" ## The default value of the argument. @@ -16,6 +17,7 @@ var enumeration := "" ## The class/built-in type of [member default]. var type := "" + func _init(args := {}) -> void: for arg in args: set(arg, args[arg]) diff --git a/addons/silicon.util.custom_docs/doc_item/class_doc_item.gd b/addons/silicon.util.custom_docs/doc_item/class_doc_item.gd index 49a598a..6293708 100644 --- a/addons/silicon.util.custom_docs/doc_item/class_doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/class_doc_item.gd @@ -1,8 +1,9 @@ ## An object that contains documentation data about a class. ## @contribute https://placeholder_contribute.com tool -extends DocItem class_name ClassDocItem +extends DocItem + var base := "" ## The base class this class extends from. var path := "" ## The file location of this class' script. @@ -31,6 +32,7 @@ func _init(args := {}) -> void: for arg in args: set(arg, args[arg]) + ## @args name ## @return MethodDocItem ## Gets a method document called [code]name[/code]. @@ -40,6 +42,7 @@ func get_method_doc(name: String) -> MethodDocItem: return doc return null + ## @args name ## @return PropertyDocItem ## Gets a signal document called [code]name[/code]. @@ -49,6 +52,7 @@ func get_property_doc(name: String) -> PropertyDocItem: return doc return null + ## @args name ## @return SignalDocItem ## Gets a signal document called [code]name[/code]. @@ -58,6 +62,7 @@ func get_signal_doc(name: String) -> SignalDocItem: return doc return null + ## @args name ## @return ConstantlDocItem ## Gets a signal document called [code]name[/code]. diff --git a/addons/silicon.util.custom_docs/doc_item/constant_doc_item.gd b/addons/silicon.util.custom_docs/doc_item/constant_doc_item.gd index f3394a5..5ff678e 100644 --- a/addons/silicon.util.custom_docs/doc_item/constant_doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/constant_doc_item.gd @@ -1,8 +1,9 @@ ## An object that contains documentation data about a constant. ## @contribute https://placeholder_contribute.com tool -extends DocItem class_name ConstantDocItem +extends DocItem + ## @default "" ## A description of the constant. diff --git a/addons/silicon.util.custom_docs/doc_item/doc_item.gd b/addons/silicon.util.custom_docs/doc_item/doc_item.gd index 6995533..c1c035a 100644 --- a/addons/silicon.util.custom_docs/doc_item/doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/doc_item.gd @@ -1,7 +1,8 @@ ## The base class for all documentation items. tool -extends Reference class_name DocItem +extends Reference + ## @default "" ## The name of the documentation item. diff --git a/addons/silicon.util.custom_docs/doc_item/method_doc_item.gd b/addons/silicon.util.custom_docs/doc_item/method_doc_item.gd index 98d5b9e..756ac4b 100644 --- a/addons/silicon.util.custom_docs/doc_item/method_doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/method_doc_item.gd @@ -1,6 +1,7 @@ tool -extends DocItem class_name MethodDocItem +extends DocItem + ## @default "" ## A description of the method. diff --git a/addons/silicon.util.custom_docs/doc_item/property_doc_item.gd b/addons/silicon.util.custom_docs/doc_item/property_doc_item.gd index 3206cf2..d6da050 100644 --- a/addons/silicon.util.custom_docs/doc_item/property_doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/property_doc_item.gd @@ -1,8 +1,9 @@ ## An object that contains documentation data about a property. ## @contribute https://placeholder_contribute.com tool -extends DocItem class_name PropertyDocItem +extends DocItem + ## @default "" ## A description of the property. @@ -28,6 +29,7 @@ var setter := "" ## The getter method of the property. var getter := "" + func _init(args := {}) -> void: for arg in args: set(arg, args[arg]) diff --git a/addons/silicon.util.custom_docs/doc_item/signal_doc_item.gd b/addons/silicon.util.custom_docs/doc_item/signal_doc_item.gd index 946a33f..ec775bb 100644 --- a/addons/silicon.util.custom_docs/doc_item/signal_doc_item.gd +++ b/addons/silicon.util.custom_docs/doc_item/signal_doc_item.gd @@ -1,8 +1,9 @@ ## An object that contains documentation data about a signal. ## @contribute https://placeholder_contribute.com tool -extends DocItem class_name SignalDocItem +extends DocItem + ## @default "" ## A description of the signal. @@ -12,6 +13,7 @@ var description := "" ## A list of arguments the signal carries. var args := [] + func _init(args := {}) -> void: for arg in args: set(arg, args[arg]) diff --git a/test/TestUtils.gd b/test/TestUtils.gd index 1189f0b..a109892 100644 --- a/test/TestUtils.gd +++ b/test/TestUtils.gd @@ -1,9 +1,8 @@ class_name TestUtils extends Object -static func instantiate(clazz: Script) -> Node: - var o = Node.new() - o.set_script(clazz) - - return o +static func instantiate(script: Script) -> Node: + var o = Node.new() + o.set_script(script) + return o diff --git a/test/storage_stress_test.gd b/test/storage_stress_test.gd index 0237a85..3594a37 100644 --- a/test/storage_stress_test.gd +++ b/test/storage_stress_test.gd @@ -1,10 +1,12 @@ extends Node2D + var offset := 0 export var email := "" export var password := "" + func _ready() -> void: Firebase.Auth.login_with_email_and_password(email, password) yield(Firebase.Auth, "login_succeeded") diff --git a/test/unit/test_FirebaseDatabaseStore.gd b/test/unit/test_FirebaseDatabaseStore.gd index 1104454..6278b63 100644 --- a/test/unit/test_FirebaseDatabaseStore.gd +++ b/test/unit/test_FirebaseDatabaseStore.gd @@ -1,5 +1,6 @@ extends "res://addons/gut/test.gd" + const FirebaseDatabaseStore = preload("res://addons/godot-firebase/database/database_store.gd") const TestKey = "-MPrgu_F8OXiL-VpRxjq" const TestObject = { @@ -22,6 +23,7 @@ const TestValue = 12345.6789 class TestPutOperations: extends "res://addons/gut/test.gd" + func test_put_object(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -34,6 +36,7 @@ class TestPutOperations: store.queue_free() + func test_put_nested_object(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -47,6 +50,7 @@ class TestPutOperations: store.queue_free() + func test_put_array_value(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -60,6 +64,7 @@ class TestPutOperations: store.queue_free() + func test_put_normal_value(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -73,10 +78,10 @@ class TestPutOperations: store.queue_free() + func test_put_deleted_value(): # NOTE: Firebase Realtime Database sets values to null to indicate that they have been - # deleted. - + # deleted. var store = TestUtils.instantiate(FirebaseDatabaseStore) store.put(TestKey, TestObject) @@ -89,6 +94,7 @@ class TestPutOperations: store.queue_free() + func test_put_new_object(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -101,6 +107,7 @@ class TestPutOperations: store.queue_free() + func test_put_new_nested_object(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -113,6 +120,7 @@ class TestPutOperations: store.queue_free() + func test_put_new_array_value(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -125,6 +133,7 @@ class TestPutOperations: store.queue_free() + func test_put_new_normal_value(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -140,6 +149,7 @@ class TestPutOperations: class TestPatchOperations: extends "res://addons/gut/test.gd" + func test_patch_object(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -152,6 +162,7 @@ class TestPatchOperations: store.queue_free() + func test_patch_nested_object(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -165,6 +176,7 @@ class TestPatchOperations: store.queue_free() + func test_patch_array_value(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -178,6 +190,7 @@ class TestPatchOperations: store.queue_free() + func test_patch_normal_value(): var store = TestUtils.instantiate(FirebaseDatabaseStore) @@ -191,10 +204,10 @@ class TestPatchOperations: store.queue_free() + func test_patch_deleted_value(): # NOTE: Firebase Realtime Database sets values to null to indicate that they have been - # deleted. - + # deleted. var store = TestUtils.instantiate(FirebaseDatabaseStore) store.put(TestKey, TestObject) diff --git a/test/unit/test_FirestoreDocument.gd b/test/unit/test_FirestoreDocument.gd index 281bc71..3313c35 100644 --- a/test/unit/test_FirestoreDocument.gd +++ b/test/unit/test_FirestoreDocument.gd @@ -1,81 +1,48 @@ extends "res://addons/gut/test.gd" + const FirestoreDocument = preload("res://addons/godot-firebase/firestore/firestore_document.gd") class TestDeserialization: extends "res://addons/gut/test.gd" + func test_deserialize_array_of_dicts(): - var doc_infos : Dictionary = { - "name":"projects/godot-firebase/databases/(default)/documents/rooms/EUZT", + var doc_infos: Dictionary = { + "name": "projects/godot-firebase/databases/(default)/documents/rooms/EUZT", "fields": { - "code": { - "stringValue":"EUZT" - }, + "code": {"stringValue": "EUZT"}, "players": { "arrayValue": { - "values": [{ - "mapValue": { - "fields": { - "name": { - "stringValue":"Hello" - } - } - } - }, { - "mapValue":{ - "fields":{ - "name":{ - "stringValue":"Test" - } - } - } - }] + "values": [ + {"mapValue": {"fields": {"name": {"stringValue": "Hello"}}}}, + {"mapValue": {"fields": {"name": {"stringValue": "Test"}}}} + ] } - }, + } }, - "createTime":"2021-02-16T07:24:11.106522Z", - "updateTime":"2021-02-16T08:21:32.131028Z" + "createTime": "2021-02-16T07:24:11.106522Z", + "updateTime": "2021-02-16T08:21:32.131028Z" } - var expected_doc_fields : Dictionary = { - "code": "EUZT", - "players": [ - { "name": "Hello" }, - { "name": "Test" }, - ] + var expected_doc_fields: Dictionary = { + "code": "EUZT", "players": [{"name": "Hello"}, {"name": "Test"}] } - var firestore_document : FirestoreDocument = FirestoreDocument.new(doc_infos) + var firestore_document: FirestoreDocument = FirestoreDocument.new(doc_infos) assert_eq_deep(firestore_document.doc_fields, expected_doc_fields) - func test_deserialize_array_of_strings(): - - var doc_infos : Dictionary = { - "name":"projects/godot-firebase/databases/(default)/documents/rooms/EUZT", + var doc_infos: Dictionary = { + "name": "projects/godot-firebase/databases/(default)/documents/rooms/EUZT", "fields": { - "code": { - "stringValue":"EUZT" - }, - "things": { - "arrayValue": { - "values": [{ - "stringValue": "first" - }, { - "stringValue":"second" - }] - } - } + "code": {"stringValue": "EUZT"}, + "things": {"arrayValue": {"values": [{"stringValue": "first"}, {"stringValue": "second"}]}} }, - "createTime":"2021-02-16T07:24:11.106522Z", - "updateTime":"2021-02-16T08:21:32.131028Z" + "createTime": "2021-02-16T07:24:11.106522Z", + "updateTime": "2021-02-16T08:21:32.131028Z" } - var expected_doc_fields : Dictionary = { - "code": "EUZT", - "things": ["first", "second"] - } - var firestore_document : FirestoreDocument = FirestoreDocument.new(doc_infos) + var expected_doc_fields: Dictionary = {"code": "EUZT", "things": ["first", "second"]} + var firestore_document: FirestoreDocument = FirestoreDocument.new(doc_infos) assert_eq_deep(firestore_document.doc_fields, expected_doc_fields) -