newgrounds login system :)

This commit is contained in:
Haze Weathers 2023-10-13 16:20:53 -04:00
parent a205fc3008
commit 644748463c
3 changed files with 215 additions and 4 deletions

View file

@ -2,10 +2,19 @@ extends Node
const GATEWAY_URI: String = "https://newgrounds.io/gateway_v3.php"
const SESSION_FILE: String = "user://ngio.pr"
const EMPTY_SESSION: Dictionary = {
expired = true,
id = "",
passport_url = "",
remember = false,
user = null,
}
var app_id: String = "" # app id on newgrounds
var aes_key := PoolByteArray([]) # AES-128/Base64 encryption key
var session: Dictionary = EMPTY_SESSION
var keys_loaded: bool = false # whether id and key have been loaded from ini file
var http := HTTPRequest.new() # http request node
@ -27,6 +36,7 @@ func _ready() -> void:
if app_id == "":
push_error("Failed to load ngio data. Will not be able to access scoreboards.")
keys_loaded = false
return
else:
keys_loaded = true
@ -42,14 +52,76 @@ func _ready() -> void:
# initialize rng for encryption
rng.randomize()
# try to load saved session
if not yield(load_saved_session(), "completed"):
yield(start_new_session(), "completed")
func _test_http() -> void:
print(yield(request_execute("Gateway.getDatetime"), "completed"))
## attempts to load a saved newgrounds.io session
## returns true if the loaded session is valid
func load_saved_session() -> bool:
var ini = ConfigFile.new()
var err = ini.load(SESSION_FILE)
# fail if can't load ngio.pr
if err != OK:
session = EMPTY_SESSION
session.id = ini.get_value("ngio", "session_id", "")
# check session is valid
var response = yield(request_execute("App.checkSession"), "completed")
if has_result(response):
var result = response.result
if result.data.success and not result.data.session.expired:
session = result.data.session
return true
session = EMPTY_SESSION
ini.set_value("ngio", "session_id", "")
ini.save(SESSION_FILE)
return false
## start new session
func start_new_session() -> bool:
var response = yield(request_execute("App.startSession"), "completed")
if has_result(response):
var result = response.result
if result.data.success and not result.data.session.expired:
session = result.data.session
return true
session = EMPTY_SESSION
return false
## repeatedly checks session until it is logged in or cancelled
func passport_check() -> bool:
# attempt for maximum of 5 minutes
var attempts = 60
while attempts > 0:
attempts -= 1
yield(get_tree().create_timer(5.0), "timeout")
var response = yield(request_execute("App.checkSession"), "completed")
if has_result(response):
var result = response.result
if result.data.success:
if result.data.session.user:
session = result.data.session
if session.remember:
var ini = ConfigFile.new()
ini.set_value("ngio", "session_id", session.id)
ini.save(SESSION_FILE)
return true
else:
return false
return false
## checks if a response is valid and succeeded
func has_result(response: Dictionary) -> bool:
return "success" in response and response.success
## requests the provided component be executed, do not call async :/
# may call with either single or multiple components
func request_execute(component: String, parameters: Dictionary = {}, session_id: String = "", echo: String = "", encrypt: bool = false) -> Dictionary:
func request_execute(component: String, parameters: Dictionary = {}, echo: String = "", encrypt: bool = false) -> Dictionary:
# build request headers
var headers = [
"Content-Type: application/x-www-form-urlencoded",
@ -88,7 +160,7 @@ func request_execute(component: String, parameters: Dictionary = {}, session_id:
# compose request body
var request = {
app_id = app_id,
session_id = session_id,
session_id = session.id,
execute = execute,
}
var body = "input=" + to_json(request).percent_encode()
@ -98,6 +170,7 @@ func request_execute(component: String, parameters: Dictionary = {}, session_id:
yield(http, "request_completed")
return _response
## called when the HTTPRequest gets a responce
func _http_request_completed(result: int, response_code: int, headers: PoolStringArray, body: PoolByteArray) -> void:
if response_code == 200:

43
menus/newgrounds_login.gd Normal file
View file

@ -0,0 +1,43 @@
extends Control
onready var tab_container: TabContainer = $"%TabContainer"
func _ready() -> void:
visible = false
Fade.fade_out(0.4)
yield(Fade, "fade_finished")
visible = true
yield(get_tree(), "idle_frame")
grab_focus()
Fade.fade_in(0.4)
if not Ngio.keys_loaded:
tab_container.current_tab = 2
return
if Ngio.session.user == null and not Ngio.session.passport_url.empty():
var passport_url = Ngio.session.passport_url
# try to open in browser
OS.shell_open(passport_url)
# try to copy to clipboard
OS.clipboard = passport_url
if OS.has_clipboard():
$"%Clipboard".modulate.a = 1.0
_await_result()
elif Ngio.session.user != null:
tab_container.current_tab = 1
else:
tab_container.current_tab = 2
func _gui_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
if tab_container.current_tab == 0:
Ngio.request_execute("App.endSession")
queue_free()
elif event.is_action_pressed("ui_accept") and tab_container.current_tab != 0:
queue_free()
func _await_result() -> void:
var success = yield(Ngio.passport_check(), "completed")
if success:
tab_container.current_tab = 1
else:
tab_container.current_tab = 2

View file

@ -0,0 +1,95 @@
[gd_scene load_steps=8 format=2]
[ext_resource path="res://shaders/ska_plane.gdshader" type="Shader" id=1]
[ext_resource path="res://menus/newgrounds_login.gd" type="Script" id=2]
[ext_resource path="res://ui/theme.tres" type="Theme" id=3]
[ext_resource path="res://ui/2ndpuberty_scholar_outline.fnt" type="BitmapFont" id=4]
[ext_resource path="res://shaders/wibble_wobble.gdshader" type="Shader" id=5]
[sub_resource type="ShaderMaterial" id=1]
shader = ExtResource( 1 )
shader_param/color_1 = Color( 1, 0.709804, 0.054902, 1 )
shader_param/color_2 = Color( 1, 0.945098, 0.478431, 1 )
shader_param/checker_size = Vector2( 24, 12 )
shader_param/pan_speed = Vector2( 0, 0 )
shader_param/cycle_speed = Vector2( 8, -8 )
shader_param/cycle_alternation = Vector2( 0, 1 )
shader_param/uv_transform = Transform2D( 1, 1, 1, 1, 0, 0 )
[sub_resource type="ShaderMaterial" id=2]
shader = ExtResource( 5 )
shader_param/speed = Vector2( 8, 4 )
shader_param/ammount = Vector2( 12, 24 )
shader_param/offset = Vector2( 0, 0 )
shader_param/delay = Vector2( 0, 0 )
[node name="NewgroundsLogin" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
focus_mode = 2
script = ExtResource( 2 )
[node name="Background" type="ColorRect" parent="."]
material = SubResource( 1 )
anchor_right = 1.0
anchor_bottom = 1.0
[node name="CenterContainer" type="CenterContainer" parent="."]
anchor_right = 1.0
anchor_bottom = 1.0
theme = ExtResource( 3 )
[node name="TabContainer" type="TabContainer" parent="CenterContainer"]
unique_name_in_owner = true
margin_left = 23.0
margin_top = 43.0
margin_right = 233.0
margin_bottom = 148.0
tabs_visible = false
[node name="Loading" type="VBoxContainer" parent="CenterContainer/TabContainer"]
anchor_right = 1.0
anchor_bottom = 1.0
rect_pivot_offset = Vector2( -174, -77 )
[node name="Label" type="Label" parent="CenterContainer/TabContainer/Loading"]
margin_right = 210.0
margin_bottom = 10.0
custom_fonts/font = ExtResource( 4 )
text = "Log into newgrounds in browser"
align = 1
[node name="LoadingGraphic" type="Label" parent="CenterContainer/TabContainer/Loading"]
material = SubResource( 2 )
margin_top = 14.0
margin_right = 210.0
margin_bottom = 78.0
rect_min_size = Vector2( 0, 64 )
text = "§"
align = 1
valign = 1
[node name="Clipboard" type="Label" parent="CenterContainer/TabContainer/Loading"]
unique_name_in_owner = true
modulate = Color( 1, 1, 1, 0 )
margin_top = 82.0
margin_right = 210.0
margin_bottom = 105.0
custom_fonts/font = ExtResource( 4 )
text = "If browser didn't open,
url copied to clipboard"
align = 1
[node name="Success" type="Label" parent="CenterContainer/TabContainer"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
custom_fonts/font = ExtResource( 4 )
text = "Success!"
[node name="Failure" type="Label" parent="CenterContainer/TabContainer"]
visible = false
anchor_right = 1.0
anchor_bottom = 1.0
custom_fonts/font = ExtResource( 4 )
text = "Failure :("