用GDScript实现扫码登陆Bilibili获取到SESSDATA
Godot中使用GDScript 实现 Bilibili 扫码登录获取 SESSDATA 流程 本文档总结 Godot 项目中通过 Bilibili 扫码登录获取 SESSDATA 的核心逻辑,代码位于脚本的 需要用户登陆 区域。 功能概述 调用 Bilibili 官方接口生成登录二维码,在应用内展示。 定时轮询二维码扫描状态,检测用户是否已扫码并确认登录。 扫码成功后通过登录链接交换得到 SESSDATA,并持久化到项目存储中。 提供回调机制通知调用方登录结果(成功/失败)。 源代码 # 扫码登录相关变量 var qr_window: Window = null var _poll_timer: Timer var on_qr_login_result: Callable func start_qr_login(login_callback: Callable) -> void: on_qr_login_result = login_callback var http = HTTPRequest.new() add_child(http) http.request_completed.connect(_on_qr_generated) var err = http.request("https://passport.bilibili.com/x/passport-login/web/qrcode/generate", PackedStringArray(), HTTPClient.METHOD_GET) func _on_qr_generated(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void: if response_code != 200: return var json = JSON.new() if json.parse(body.get_string_from_utf8()) != OK: return var data = json.get_data()["data"] var url = data["url"] var qrcode_key = data["qrcode_key"] _display_qrcode(url) _poll_login_status(qrcode_key) func _display_qrcode(content: String) -> void: qr_window = preload("res://Scene/Log_in.tscn").instantiate() qr_window.close_requested.connect(_on_qr_window_closed) add_child(qr_window) var encoded = content.uri_encode() var qr_api = "https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=" + encoded var img_request = HTTPRequest.new() add_child(img_request) img_request.request_completed.connect(func(_r, _c, _h, body): if not is_instance_valid(qr_window): return var img = Image.new() if img.load_png_from_buffer(body) == OK: var tex = ImageTexture.create_from_image(img) qr_window.get_node("QRImage").texture = tex else: push_error("二维码图片加载失败") ) img_request.request(qr_api, PackedStringArray(), HTTPClient.METHOD_GET) func _on_qr_window_closed() -> void: if qr_window: qr_window.queue_free() qr_window = null if _poll_timer: _poll_timer.stop() _poll_timer.queue_free() _poll_timer = null if on_qr_login_result: on_qr_login_result.call(false) func _close_qr_window() -> void: if qr_window: qr_window.queue_free() qr_window = null if _poll_timer: _poll_timer.stop() _poll_timer.queue_free() _poll_timer = null func _poll_login_status(qrcode_key: String) -> void: _poll_timer = Timer.new() _poll_timer.wait_time = 2.0 _poll_timer.autostart = true _poll_timer.timeout.connect(_check_qr_status.bind(qrcode_key)) add_child(_poll_timer) func _check_qr_status(qrcode_key: String) -> void: var http = HTTPRequest.new() add_child(http) http.request_completed.connect(func(result, response_code, headers, body): if response_code != 200: return var json = JSON.new() if json.parse(body.get_string_from_utf8()) != OK: return var data = json.get_data()["data"] var code = data["code"] if code == 0: _exchange_cookie(data["url"]) if on_qr_login_result: on_qr_login_result.call(true) _close_qr_window() elif code == 86038: if on_qr_login_result: on_qr_login_result.call(false) _close_qr_window() ) http.request("https://passport.bilibili.com/x/passport-login/web/qrcode/poll?qrcode_key=" + qrcode_key, PackedStringArray(), HTTPClient.METHOD_GET) func _exchange_cookie(login_url: String) -> void: var http = HTTPRequest.new() add_child(http) http.request_completed.connect(func(result, response_code, headers, body): for header in headers: if header.begins_with("Set-Cookie: SESSDATA="): var sess = header.split("=")[1].split(";")[0] GdScriptFunc.set_data("AccountData","SESSDATA",sess) break ) http.request(login_url, PackedStringArray(), HTTPClient.METHOD_GET) 核心流程 发起登录 调用 start_qr_login(login_callback) 开始流程,传入一个回调函数用于接收登录结果。 ...
我的小时候
今天找到了一张小时候的照片(划水) 大概是13年前吧,那是我才4岁 当看到这张图时,我顺着碎片的记忆寻找过去, 记得那是我们一家在河北省承德居住,爸爸在哪里打工,大概是建高铁铁路,具体什么职务就不记得了… 好怀念小时候啊。
Godot Windows平台如何自动处理鼠标穿透
可以利用DllImport导入SetWindowLong来设置窗口样式 具体代码: WindowsApiManager.cs using System.Runtime.InteropServices; using Godot; public partial class WindowsApiManager : Node { private nint _hWnd; [DllImport("user32.dll")] public static extern nint GetActiveWindow(); [DllImport("user32.dll")] private static extern int SetWindowLong(nint hWnd, int nIndex, uint dwNewLong); public override void _Ready() { _hWnd = GetActiveWindow(); _ = SetWindowLong(_hWnd, -20, 524416u); } public void SetClickThrough(bool clickthrough) { if (clickthrough) { _ = SetWindowLong(_hWnd, -20, 524448u); } else { _ = SetWindowLong(_hWnd, -20, 524416u); } } } MouseDetection.cs using Godot; public partial class MouseDetection : Node { private WindowsApiManager _api; private bool _clickthrough = true; public override void _Ready() { _api = GetNode<WindowsApiManager>("/root/WindowsApiManager"); _api.SetClickThrough(clickthrough: true); } public override void _PhysicsProcess(double _) { DetectPassthrough(); } private void DetectPassthrough() { Viewport viewport = GetViewport(); Image img = viewport.GetTexture().GetImage(); Rect2 rect = viewport.GetVisibleRect(); Vector2 mousePosition = viewport.GetMousePosition(); int viewX = (int)((int)mousePosition.X + rect.Position.X); int viewY = (int)((int)mousePosition.Y + rect.Position.Y); int x = (int)(img.GetSize().X * viewX / rect.Size.X); int y = (int)(img.GetSize().Y * viewY / rect.Size.Y); if (x < img.GetSize().X && x >= 0 && y < img.GetSize().Y && y >= 0) { SetClickability(img.GetPixel(x, y).A >= 1f); } img.Dispose(); } private void SetClickability(bool clickable) { if (clickable != _clickthrough) { _clickthrough = clickable; _api.SetClickThrough(!clickable); } } } 使用方法: 将WindowsApiManager.cs设为自动加载脚本 ...