config.tab

This commit is contained in:
rfi 2023-10-07 07:44:06 +07:00
parent 859e3fa042
commit 212d08496c
9 changed files with 206 additions and 3 deletions

View File

@ -19,6 +19,9 @@ namespace AscNet.Common
interface IGameServer interface IGameServer
{ {
[Option(DefaultValue = nameof(AscNet))]
string RegionName { get; set; }
[Option(DefaultValue = "127.0.0.1")] [Option(DefaultValue = "127.0.0.1")]
string Host { get; set; } string Host { get; set; }

View File

@ -4,7 +4,7 @@ namespace AscNet.Common.Util
{ {
public class Logger public class Logger
{ {
public static readonly Logger c = new("SF", ConsoleColor.DarkRed); public static readonly Logger c = new(nameof(AscNet), ConsoleColor.DarkRed);
private readonly string _name; private readonly string _name;
private readonly bool TraceOnError; private readonly bool TraceOnError;
private readonly ConsoleColor _color; private readonly ConsoleColor _color;

View File

@ -0,0 +1,37 @@
using System.Reflection;
namespace AscNet.Common.Util
{
public static class TsvTool
{
public static string SerializeObject<T>(IEnumerable<T> objs) where T : new()
{
string res = string.Empty;
Type type = typeof(T);
var properties = type.GetProperties()
.OrderBy(p => p.GetCustomAttribute<PropertyOrderAttribute>()?.Order ?? int.MaxValue)
.ToList();
res += string.Join('\t', properties.Select(x => x.Name)) + '\n';
foreach (var obj in objs)
{
res += string.Join('\t', properties.Select(x => x.GetValue(obj))) + '\n';
}
return res;
}
}
[AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
public sealed class PropertyOrderAttribute : Attribute
{
public int Order { get; }
public PropertyOrderAttribute(int order)
{
Order = order;
}
}
}

View File

@ -16,7 +16,6 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Models\" />
<Folder Include="Properties\" /> <Folder Include="Properties\" />
</ItemGroup> </ItemGroup>

View File

@ -1,10 +1,59 @@
namespace AscNet.SDKServer.Controllers using AscNet.Common.Util;
using AscNet.SDKServer.Models;
using Newtonsoft.Json;
namespace AscNet.SDKServer.Controllers
{ {
internal class ConfigController : IRegisterable internal class ConfigController : IRegisterable
{ {
private static readonly Dictionary<string, ServerVersionConfig> versions = new();
static ConfigController()
{
versions = JsonConvert.DeserializeObject<Dictionary<string, ServerVersionConfig>>(File.ReadAllText("./Configs/version_config.json"))!;
}
public static void Register(WebApplication app) public static void Register(WebApplication app)
{ {
app.MapGet("/prod/client/config/com.kurogame.punishing.grayraven.en.pc/{version}/standalone/config.tab", (HttpContext ctx) =>
{
List<RemoteConfig> remoteConfigs = new();
ServerVersionConfig versionConfig = versions.GetValueOrDefault((string)ctx.Request.RouteValues["version"]!) ?? versions.First().Value;
foreach (var property in typeof(ServerVersionConfig).GetProperties())
remoteConfigs.AddConfig(property.Name, (string)property.GetValue(versionConfig)!);
remoteConfigs.AddConfig("ApplicationVersion", (string)ctx.Request.RouteValues["version"]!);
remoteConfigs.AddConfig("Debug", true);
remoteConfigs.AddConfig("External", true);
remoteConfigs.AddConfig("Channel", 1);
remoteConfigs.AddConfig("PayCallbackUrl", "empty");
remoteConfigs.AddConfig("PrimaryCdns", "http://prod-encdn-akamai.kurogame.net/prod|http://prod-encdn-aliyun.kurogame.net/prod");
remoteConfigs.AddConfig("SecondaryCdns", "http://prod-encdn-aliyun.kurogame.net/prod");
remoteConfigs.AddConfig("CdnInvalidTime", 600);
remoteConfigs.AddConfig("MtpEnabled", false);
remoteConfigs.AddConfig("MemoryLimit", 2048);
remoteConfigs.AddConfig("CloseMsgEncrypt", false);
remoteConfigs.AddConfig("ServerListStr", $"{Common.Common.config.GameServer.RegionName}#{Common.Common.config.GameServer.Host}/api/Login/Login");
remoteConfigs.AddConfig("AndroidPayCallbackUrl", $"{Common.Common.config.GameServer.Host}/api/XPay/HeroHgAndroidPayResult"); // i just wanna know what this is
remoteConfigs.AddConfig("IosPayCallbackUrl", $"{Common.Common.config.GameServer.Host}/api/XPay/HeroHgIosPayResult"); // i just wanna know what this is
remoteConfigs.AddConfig("WatermarkEnabled", true); // i just wanna know what this is
remoteConfigs.AddConfig("PicComposition", "empty"); // i just wanna know what this is
remoteConfigs.AddConfig("DeepLinkEnabled", true);
remoteConfigs.AddConfig("DownloadMethod", 1);
remoteConfigs.AddConfig("PcPayCallbackList", $"{Common.Common.config.GameServer.Host}/api/XPay/KuroPayResult");
return TsvTool.SerializeObject(remoteConfigs);
});
app.MapPost("/feedback", (HttpContext ctx) =>
{
return ctx.Response.WriteAsJsonAsync(new
{
code = 0,
msg = "ok"
});
});
} }
} }
} }

View File

@ -0,0 +1,56 @@
using AscNet.Common.Util;
namespace AscNet.SDKServer.Models
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public class RemoteConfig
{
[PropertyOrder(0)]
public string Key { get; set; }
[PropertyOrder(1)]
public string Type { get; set; }
[PropertyOrder(2)]
public string Value { get; set; }
}
public static class RemoteConfigExtension
{
public static void AddConfig<T>(this List<RemoteConfig> remoteConfigs, string key, T value)
{
if (!typeMap.TryGetValue(typeof(T), out string? typeStr) || value is null)
throw new ArgumentException("Unsupported value!", nameof(value));
RemoteConfig remoteConfig = new()
{
Key = key,
Type = typeStr
};
switch (typeStr)
{
case "int":
case "float":
case "string":
remoteConfig.Value = value.ToString() ?? "";
break;
case "bool":
remoteConfig.Value = value.ToString() == "True" ? "1" : "0";
break;
default:
break;
}
remoteConfigs.Add(remoteConfig);
}
private static Dictionary<Type, string> typeMap = new Dictionary<Type, string>
{
{ typeof(string), "string" },
{ typeof(int), "int" },
{ typeof(bool), "bool" },
{ typeof(float), "float" },
};
}
}

View File

@ -0,0 +1,23 @@
using Newtonsoft.Json;
namespace AscNet.SDKServer.Models
{
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
public class ServerVersionConfig
{
[JsonProperty("DocumentVersion", NullValueHandling = NullValueHandling.Ignore)]
public string DocumentVersion { get; set; }
[JsonProperty("LaunchModuleVersion", NullValueHandling = NullValueHandling.Ignore)]
public string LaunchModuleVersion { get; set; }
[JsonProperty("IndexMd5", NullValueHandling = NullValueHandling.Ignore)]
public string IndexMd5 { get; set; }
[JsonProperty("IndexSha1", NullValueHandling = NullValueHandling.Ignore)]
public string IndexSha1 { get; set; }
[JsonProperty("LaunchIndexSha1", NullValueHandling = NullValueHandling.Ignore)]
public string LaunchIndexSha1 { get; set; }
}
}

View File

@ -0,0 +1,9 @@
{
"1.30.0": {
"DocumentVersion": "1.30.3",
"LaunchModuleVersion": "1.30.3",
"IndexMd5": "c5d4baac85a6e37b8109ea43dc045d31",
"IndexSha1": "544254b3f611e4268c108c88a366f8743cc7045b",
"LaunchIndexSha1": "e5726b1edcaf486a95561eb01a72365ccb30dd3c"
}
}

27
proxy.py Normal file
View File

@ -0,0 +1,27 @@
from mitmproxy import http
from mitmproxy import ctx
from mitmproxy.proxy import layer, layers
def load(loader):
# ctx.options.web_open_browser = False
# We change the connection strategy to lazy so that next_layer happens before we actually connect upstream.
ctx.options.connection_strategy = "lazy"
ctx.options.upstream_cert = False
ctx.options.ssl_insecure = True
def next_layer(nextlayer: layer.NextLayer):
# ctx.log(
# f"{nextlayer.context=}\n"
# f"{nextlayer.data_client()[:70]=}\n"
# )
# this is HTTPS only
sni = nextlayer.context.client.sni
if sni and (sni.endswith("kurogame.net") or sni.endswith("kurogame-service.com")):
ctx.log('sni:' + sni)
nextlayer.context.server.address = ("127.0.0.1", 443)
def request(flow: http.HTTPFlow) -> None:
if "kurogame.net" in flow.request.pretty_url or "kurogame-service.com" in flow.request.pretty_url:
flow.request.host = "localhost"
flow.request.headers["Host"] = "localhost"
pass