From 756b2f7c8262de32dfc7b8ee93cef8ec9a78737d Mon Sep 17 00:00:00 2001 From: user Date: Sun, 31 May 2026 04:18:37 +0900 Subject: [PATCH] =?UTF-8?q?Fix=20:=20=ED=9B=84=EC=9B=90=20=EC=8B=9C?= =?UTF-8?q?=EC=8A=A4=ED=85=9C=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Scripts/WefLab/WefLabWebSocketClient.cs | 140 ++++++++++++++++-- 1 file changed, 124 insertions(+), 16 deletions(-) diff --git a/Assets/Scripts/WefLab/WefLabWebSocketClient.cs b/Assets/Scripts/WefLab/WefLabWebSocketClient.cs index 88ff1d464..9519885cd 100644 --- a/Assets/Scripts/WefLab/WefLabWebSocketClient.cs +++ b/Assets/Scripts/WefLab/WefLabWebSocketClient.cs @@ -233,6 +233,10 @@ namespace WefLab [Tooltip("TTS language code sent to weflab's voice endpoint (affects the measured audio length).")] public string ttsLang = "ko"; + [Header("Debug")] + [Tooltip("Log the full raw JSON payload of every received socket event. Use this to inspect real platform donation/chat structures.")] + public bool verboseRawLog = true; + // Queue state (visible in Inspector for debugging) [Header("Queue Status (Read Only)")] [SerializeField] private int queueCount = 0; @@ -241,6 +245,7 @@ namespace WefLab // Donation queue private Queue donationQueue = new Queue(); private Coroutine queueProcessorCoroutine = null; + private Coroutine platformKeepAliveCoroutine = null; // ---- Precise timing: meta extracted from loginData + settings fetched from /api/ ---- private string userDir = ""; @@ -268,13 +273,17 @@ namespace WefLab private class PlatformConnection { public string platform; // "afreeca", "naver", "youtube", "main", ... + public string platformId; // the platform account id (loginData.platform[x].id), required for join_platform + public JObject platformData; // the full loginData.platform[x] object, sent in the "platform" feed message public string page; // subscription page: "alert" (donations) or "chat" public string wsUrl; // wss://ssafreeca.weflab.com/socket.io/?... public WebSocket ws; public string engineSid = ""; public string socketSid = ""; public bool connected = false; + public bool platformStarted = false; // whether the initial "platform" start message was sent + public bool IsPlatform => platform != "main"; public string Label => $"{platform}/{page}"; } @@ -538,6 +547,7 @@ namespace WefLab { string platform = prop.Name; string host = urlConfig["socket_" + platform]?.ToString(); + string platformId = (prop.Value as JObject)?["id"]?.ToString() ?? ""; if (string.IsNullOrEmpty(host)) { @@ -545,9 +555,13 @@ namespace WefLab continue; } + JObject platformData = prop.Value as JObject; + connections.Add(new PlatformConnection { platform = platform, + platformId = platformId, + platformData = platformData, page = "alert", wsUrl = BuildSocketUrl(host, "alert") }); @@ -557,6 +571,8 @@ namespace WefLab connections.Add(new PlatformConnection { platform = platform, + platformId = platformId, + platformData = platformData, page = "chat", wsUrl = BuildSocketUrl(host, "chat") }); @@ -665,6 +681,12 @@ namespace WefLab /// public void Disconnect() { + if (platformKeepAliveCoroutine != null) + { + StopCoroutine(platformKeepAliveCoroutine); + platformKeepAliveCoroutine = null; + } + foreach (var conn in connections) { if (conn.ws != null) @@ -676,6 +698,7 @@ namespace WefLab conn.connected = false; conn.engineSid = ""; conn.socketSid = ""; + conn.platformStarted = false; } UpdateAggregateState(); @@ -802,8 +825,19 @@ namespace WefLab conn.connected = true; UpdateAggregateState(); - // Send join message + // 1) Register the subscription SendJoinMessage(conn); + + // 2) Platform sockets must also start the platform feed; this is what actually + // triggers donation/chat delivery (join_platform alone is not enough). + if (conn.IsPlatform) + { + SendPlatformMessage(conn); + + // 3) Keep the feed alive with periodic re-sends (weflab uses config.time.page_platform = 60s) + if (platformKeepAliveCoroutine == null) + platformKeepAliveCoroutine = StartCoroutine(PlatformKeepAlive()); + } } catch (Exception ex) { @@ -811,6 +845,50 @@ namespace WefLab } } + /// + /// Send the "platform" feed message that starts/maintains donation delivery on a platform socket. + /// Mirrors weflab: socket.send(iop, { type:"platform", start, platform:, use:[] }). + /// + private void SendPlatformMessage(PlatformConnection conn) + { + bool start = !conn.platformStarted; + conn.platformStarted = true; + + var msg = new + { + type = "platform", + start = start, + platform = conn.platformData, + use = Array.Empty(), + // fields socket.send() auto-appends + page = pageType, + idx = userIdx, + pageid = conn.page, + preset = "0" + }; + + string fullMessage = "42" + JsonConvert.SerializeObject(new object[] { "msg", msg }); + Debug.Log($"[WefLab] ({conn.Label}) Sending PLATFORM feed message (start={start})"); + SendMessage(conn, fullMessage); + } + + /// + /// Periodically re-send the platform feed message to keep the donation feed alive (every 60s). + /// + private IEnumerator PlatformKeepAlive() + { + var wait = new WaitForSeconds(60f); + while (true) + { + yield return wait; + foreach (var conn in connections) + { + if (conn.IsPlatform && conn.connected && conn.ws != null && conn.ws.IsAlive) + SendPlatformMessage(conn); + } + } + } + // Subtypes that are NOT monetary donations (subscribe/membership/follow/emoticon). // value here is a month count or nothing, so they must not trigger amount-based events. private static readonly HashSet NonMonetarySubtypes = new HashSet(StringComparer.OrdinalIgnoreCase) @@ -828,21 +906,30 @@ namespace WefLab { var eventArray = JsonConvert.DeserializeObject(payload); - if (eventArray == null || eventArray.Count < 2) + if (eventArray == null || eventArray.Count < 1) + return; + + string eventName = eventArray[0].ToString(); + + // The server also emits bare events like ["pong"] - ignore anything that isn't a "msg" payload + if (eventName != "msg") { - Debug.LogWarning($"[WefLab] ({conn.Label}) Invalid event format: {payload}"); + Debug.Log($"[WefLab] ({conn.Label}) Socket event '{eventName}' (ignored)"); return; } - string eventName = eventArray[0].ToString(); + if (eventArray.Count < 2) + return; + var envelope = eventArray[1] as JObject; Debug.Log($"[WefLab] ===== EVENT ({conn.Label}) name={eventName} type={envelope?["type"]} ====="); - if (eventName == "msg") - { - HandleMessageEnvelope(conn.platform, envelope); - } + // Verbose: dump the full raw payload so real (non-test) platform structures can be verified + if (verboseRawLog && envelope != null) + Debug.Log($"[WefLab] RAW ({conn.Label}):\n{envelope.ToString(Formatting.Indented)}"); + + HandleMessageEnvelope(conn.platform, envelope); } catch (Exception ex) { @@ -1436,18 +1523,39 @@ namespace WefLab } /// - /// Send join message to subscribe to this connection's page (alert donations or chat). + /// Send the subscription message for this connection. + /// Platform sockets (ssafreeca/ssnaver/...) use "join_platform" with the platform + account id; + /// the main control socket (ssmain) uses the generic "join". Mirrors weflab's socket.connect / socket.join. /// private void SendJoinMessage(PlatformConnection conn) { - var joinData = new + object joinData; + + if (conn.platform == "main") { - type = "join", - page = "page", - idx = userIdx, - pageid = conn.page, // "alert" or "chat" - preset = "0" - }; + joinData = new + { + type = "join", + page = pageType, // "page" + idx = userIdx, + pageid = conn.page, // "alert" or "chat" + preset = "0" + }; + } + else + { + // Platform subscription - this is what actually delivers donation/chat events + joinData = new + { + type = "join_platform", + platform = conn.platform, + id = conn.platformId, + page = pageType, // "page" + idx = userIdx, + pageid = conn.page, // "alert" or "chat" + preset = "0" + }; + } var message = new object[] { "msg", joinData }; string json = JsonConvert.SerializeObject(message);