fix: tons of change#1
Conversation
There was a problem hiding this comment.
Pull request overview
Updates Milky/Core integration points around the external signer service and Android login/captcha flows, likely to match upstream API/protocol changes.
Changes:
- Removes signer
Versionconfiguration and updates signer endpoints/response parsing (including wrappedappinfo_v2responses). - Extends Android signer requests to include a
quafield (currently passed as a hard-coded value). - Alters Android login TLV construction and replaces online captcha polling with console-driven input.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| Lagrange.Milky/Utility/Signer.cs | Removes versioned signer URLs, adds qua to Android signer payloads, updates appinfo_v2 deserialization to AndroidSignerResponse<BotAppInfo>. |
| Lagrange.Milky/Utility/JsonUtility.cs | Adds source-gen metadata for AndroidSignerResponse<BotAppInfo>. |
| Lagrange.Milky/Utility/CaptchaResolver/OnlineCaptchaResolver.cs | Replaces backend polling with Console.In.ReadLineAsync input flow. |
| Lagrange.Milky/Resources/appsettings_schema.json | Updates schema: signer Version removed from required/properties. |
| Lagrange.Milky/Resources/appsettings.jsonc | Removes signer Version from example config. |
| Lagrange.Milky/Configuration/SignerConfiguration.cs | Removes Version property. |
| Lagrange.Core/Internal/Packets/Login/WtLogin.cs | Replaces dynamic MainSigMap usage with a hard-coded value in Android login TLVs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // string queryUrl = string.Format(QueryUrl, _bot.BotUin); | ||
| // var response = await _client.GetAsync(queryUrl, token); | ||
| // if (response.StatusCode == HttpStatusCode.NotFound) | ||
| // { | ||
| // _logger.LogCaptchaWaiting(); | ||
| // continue; | ||
| // } | ||
|
|
||
| if (!response.IsSuccessStatusCode) | ||
| { | ||
| throw new Exception($"Unexpected http status code({response.StatusCode})"); | ||
| } | ||
| // if (!response.IsSuccessStatusCode) | ||
| // { | ||
| // throw new Exception($"Unexpected http status code({response.StatusCode})"); | ||
| // } | ||
|
|
||
| string result = await response.Content.ReadAsStringAsync(token); | ||
| string? json = JsonNode.Parse(result)?["data"]?.GetValue<string>(); | ||
| // string result = await response.Content.ReadAsStringAsync(token); | ||
| // string? json = JsonNode.Parse(result)?["data"]?.GetValue<string>(); | ||
| var json = await Console.In.ReadLineAsync(token); |
There was a problem hiding this comment.
OnlineCaptchaResolver no longer queries the captcha backend and instead blocks on Console.In.ReadLineAsync. Since this resolver is the default when UseOnlineCaptchaResolver=true, this effectively breaks captcha resolution in non-interactive/service environments and changes the feature semantics. Please restore the HTTP polling logic (or introduce a separate manual/console resolver behind config) rather than hard-coding console input here.
| if (json == null) continue; | ||
|
|
||
| return (json.Split('|')[0], json.Split('|')[1]); |
There was a problem hiding this comment.
The returned json string is split twice and indexed at [0] and [1] without validating the delimiter/segment count. With the new console-driven input path, malformed or empty input will throw IndexOutOfRangeException and loop termination becomes unclear; parse once and validate the expected format before returning.
| if (json == null) continue; | |
| return (json.Split('|')[0], json.Split('|')[1]); | |
| if (string.IsNullOrWhiteSpace(json)) | |
| { | |
| _logger.LogWarning("Received empty captcha response from console, waiting for valid input."); | |
| continue; | |
| } | |
| var parts = json.Split('|'); | |
| if (parts.Length < 2 || string.IsNullOrWhiteSpace(parts[0]) || string.IsNullOrWhiteSpace(parts[1])) | |
| { | |
| _logger.LogWarning("Invalid captcha response format: {Response}. Expected 'ticket|randstr'.", json); | |
| continue; | |
| } | |
| return (parts[0], parts[1]); |
| var response = await GetSign<AndroidSecSignRequest, AndroidSignerResponse<AndroidSecSignResponseData>>( | ||
| $"{_base}/sign", | ||
| new AndroidSecSignRequest( | ||
| uin, | ||
| cmd, | ||
| seq, | ||
| Convert.ToHexString(body.Span), | ||
| Convert.ToHexString(Context.Keystore.Guid), | ||
| Context.AppInfo.PtVersion | ||
| Context.AppInfo.PtVersion, | ||
| "V1_AND_SQ_9.2.20_11650_YYB_D" | ||
| ) |
There was a problem hiding this comment.
qua is hard-coded to a specific QUA string in multiple requests. Since BotAppInfo already exposes Qua (and different protocols/app versions may require different values), consider sourcing this from Context.AppInfo.Qua or a single shared constant/config value to avoid drift and make future upgrades safer.
| var result = JsonUtility.Deserialize<AndroidSignerResponse<BotAppInfo>>(await response.Content.ReadAsStreamAsync()); | ||
| if (result == null) throw new NullReferenceException("Result is null"); | ||
|
|
||
| _info = result; | ||
| return result; | ||
| _info = result.Data; | ||
| return result.Data; |
There was a problem hiding this comment.
GetAppInfo() now deserializes into AndroidSignerResponse<BotAppInfo> but does not validate result.Data before returning it (method return type is non-nullable). If the signer service returns { data: null } (or omits it), this will return null and likely fail later in DI setup; add an explicit null check for result.Data and throw a clear exception.
| tlvs.Tlv106Pwd(password); | ||
| tlvs.Tlv116(); | ||
| tlvs.Tlv100Android((uint)AppInfo.SdkInfo.MainSigMap); | ||
| tlvs.Tlv100Android(16724722); |
There was a problem hiding this comment.
Tlv100Android was changed from using AppInfo.SdkInfo.MainSigMap to a magic number (16724722). This makes the login packet behavior opaque and ignores any future changes to the configured AppInfo/protocol; please either keep using AppInfo.SdkInfo.MainSigMap or define a well-named constant (with rationale) derived from Sig flags so it stays maintainable.
| tlvs.Tlv100Android(16724722); | |
| tlvs.Tlv100Android(AppInfo.SdkInfo.MainSigMap); |
No description provided.