Fix : 후원 시스템 업데이트

This commit is contained in:
user 2026-05-31 04:18:37 +09:00
parent 4d539b56c9
commit 756b2f7c82

View File

@ -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<DonationData> donationQueue = new Queue<DonationData>();
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
/// </summary>
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
}
}
/// <summary>
/// Send the "platform" feed message that starts/maintains donation delivery on a platform socket.
/// Mirrors weflab: socket.send(iop, { type:"platform", start, platform:<obj>, use:[] }).
/// </summary>
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<string>(),
// 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);
}
/// <summary>
/// Periodically re-send the platform feed message to keep the donation feed alive (every 60s).
/// </summary>
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<string> NonMonetarySubtypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
@ -828,22 +906,31 @@ namespace WefLab
{
var eventArray = JsonConvert.DeserializeObject<JArray>(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")
{
// 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)
{
Debug.LogError($"[WefLab] ({conn.Label}) Error parsing Socket.IO EVENT: {ex.Message}");
@ -1436,18 +1523,39 @@ namespace WefLab
}
/// <summary>
/// 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.
/// </summary>
private void SendJoinMessage(PlatformConnection conn)
{
var joinData = new
object joinData;
if (conn.platform == "main")
{
joinData = new
{
type = "join",
page = "page",
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);