mirror of
https://git.crafterpika.cc/crafterpika/SplatTool-public.git
synced 2026-08-17 10:42:15 +02:00
137 lines
5.8 KiB
C#
137 lines
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();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|