SplatTool-public/TelemetryWebpost.cs
2026-04-23 17:08:47 +02:00

137 lines
No EOL
5.8 KiB
C#

using ModMenu;
using Func;
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.Json;
using System.Text.Encodings.Web;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Text.Json.Serialization;
using System.Security.Cryptography.X509Certificates;
namespace TelemetryWebpost {
public class SplatTelemetry {
private static readonly HttpClient client = new HttpClient();
public static uint LastStartNetworkTime = 0;
public static string Telemetry2Json(byte[] rawData) {
if (rawData == null || rawData.Length == 0)
return "{}";
int actualStart = Array.IndexOf(rawData, (byte)0x2D);
if (actualStart == -1) return "{}";
string content = Encoding.UTF8.GetString(rawData, actualStart, rawData.Length - actualStart);
string[] lines = content.Split(new[] { "\r\n", "\n" }, StringSplitOptions.None);
if (lines.Length == 0 || string.IsNullOrWhiteSpace(lines[0]))
return "{}";
string boundary = lines[0].Trim();
string[] parts = content.Split(new[] { boundary }, StringSplitOptions.RemoveEmptyEntries);
var result = new Dictionary<string, string>();
foreach (var part in parts) {
if (string.IsNullOrWhiteSpace(part) ||
part.Trim() == "--" ||
part.Contains("name=\"FaceImg\"") || // Kit Kat said he doesnt need faceimg.tga so i'll skip it :innocent:, makes my life easier.
!part.Contains("Content-Disposition"))
{
continue;
}
var nameMatch = Regex.Match(part, "name=\"(?<name>[^\"]+)\"");
if (!nameMatch.Success) continue;
string key = nameMatch.Groups["name"].Value;
int valueStart = part.IndexOf("\r\n\r\n");
int offset = 4;
if (valueStart == -1) {
valueStart = part.IndexOf("\n\n");
offset = 2;
}
if (valueStart == -1) continue;
string value = part.Substring(valueStart + offset).Trim(new[] { '\r', '\n', '-', ' ' });
result[key] = value;
}
var options = new JsonSerializerOptions {
WriteIndented = true,
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
return JsonSerializer.Serialize(result, options);
}
public static async Task SendTelemetryHttp(string targetUrl, string uniqueId, string TelemetryPayload, byte[] faceImgData) {
var TelemetryPayloadDict = JsonSerializer.Deserialize<Dictionary<string, string>>(TelemetryPayload);
TelemetryPayloadDict["ServerEnv"] = "L1";
if (LastStartNetworkTime == Convert.ToUInt32(TelemetryPayloadDict["StartNetworkTime"])) {
Console.WriteLine("Data sent already...");
return;
}
LastStartNetworkTime = Convert.ToUInt32(TelemetryPayloadDict["StartNetworkTime"]);
try {
using (var content = new MultipartFormDataContent()) {
foreach (var kvp in TelemetryPayloadDict) {
content.Add(new StringContent(kvp.Value), kvp.Key);
}
var imageContent = new ByteArrayContent(faceImgData);
imageContent.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
content.Add(imageContent, "FaceImg", "face.bin");
byte[] requestBody = await content.ReadAsByteArrayAsync();
string sha1Hash;
using (SHA1 sha1 = SHA1.Create()) {
byte[] hashBytes = sha1.ComputeHash(requestBody);
sha1Hash = BitConverter.ToString(hashBytes).Replace("-", "").ToLower();
}
var request = new HttpRequestMessage(HttpMethod.Post, targetUrl);
request.Content = content;
request.Headers.Add("X-BOSS-Digest", sha1Hash);
request.Headers.Add("X-BOSS-UniqueId", uniqueId);
Console.WriteLine($"Sending telemetry for {TelemetryPayloadDict["MiiName"]}...");
HttpResponseMessage response = await client.SendAsync(request);
if (response.IsSuccessStatusCode) {
Console.WriteLine("SUCCESS: Splatoon result saved.");
} else {
string errorText = await response.Content.ReadAsStringAsync();
Console.WriteLine($"FAILED: {(int)response.StatusCode} - {errorText}");
}
}
} catch (Exception ex) {
Console.WriteLine($"Connection Error: {ex.Message}");
}
}
public static void SendTelemetry() {
if (Program.readUInt32(0x101E4FF8) == 0) {
var p = Program.readUInt32(0x101DCDB0) + 0x150;
var data = Program.readBytes(p, 0x1800);
byte[] faceimg_pattern = new byte[]{ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00 };
int faceimg_offset = ExtFunc.FindPattern(data, faceimg_pattern);
if (faceimg_offset == -1) {
return;
}
var faceimg = Program.readBytes((uint)(p + faceimg_offset), 65580);
var TelemetryPayload = Telemetry2Json(data);
// Console.WriteLine(TelemetryPayload);
SendTelemetryHttp(Program.config["TelemetryUrl"], "0162b", TelemetryPayload, faceimg).GetAwaiter().GetResult();
}
}
}
}