feat: phone login via QR when the saved Mudfish login expires
When autologin is rejected the panel offers '휴대폰으로 로그인 (QR)'. It opens a 5-minute LAN relay to the launcher UI guarded by a one-time token (first phone to open the QR URL is the only client allowed) and shows the URL as a QR code. The relay closes as soon as a new session appears, on cancel, on expiry, and on unload. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d8f1c05372
commit
7513fef6f8
12 files changed
+586
-7
No files matched your search
@@ -2,6 +2,7 @@ import asyncio
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
import urllib.parse
|
||||
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "py_modules"))
|
||||
|
||||
@@ -10,9 +11,11 @@ import decky # noqa: E402
|
||||
from mudfish_decky import system # noqa: E402
|
||||
from mudfish_decky.client import MudfishClient # noqa: E402
|
||||
from mudfish_decky.controller import Controller # noqa: E402
|
||||
from mudfish_decky.relay import LoginRelay # noqa: E402
|
||||
from mudfish_decky.store import Store # noqa: E402
|
||||
|
||||
RESUME_POLL_SECONDS = 2
|
||||
LOGIN_RELAY_SECONDS = 300
|
||||
|
||||
|
||||
class Plugin:
|
||||
@@ -23,9 +26,19 @@ class Plugin:
|
||||
installed = system.find_mudfish()
|
||||
base = system.api_base(installed[1]) if installed else system.DEFAULT_API
|
||||
store = Store(os.path.join(decky.DECKY_PLUGIN_SETTINGS_DIR, "settings.json"))
|
||||
self.controller = Controller(MudfishClient(base), system, store)
|
||||
target = urllib.parse.urlsplit(base)
|
||||
self.controller = Controller(
|
||||
MudfishClient(base), system, store,
|
||||
relay_factory=lambda: LoginRelay(target=(target.hostname, target.port or 80), ttl=LOGIN_RELAY_SECONDS),
|
||||
)
|
||||
return self.controller
|
||||
|
||||
async def start_login(self) -> dict:
|
||||
return await asyncio.to_thread(self._get_controller().start_login)
|
||||
|
||||
async def stop_login(self) -> dict:
|
||||
return await asyncio.to_thread(self._get_controller().stop_login)
|
||||
|
||||
async def get_state(self) -> dict:
|
||||
return await asyncio.to_thread(self._get_controller().state)
|
||||
|
||||
|
||||
Reference in new issue
Block a user