mirror of
https://github.com/MikuLeaks/KianaBH3.git
synced 2025-12-14 22:04:36 +01:00
Init enter game
This commit is contained in:
99
Common/Util/ConfigManager.cs
Normal file
99
Common/Util/ConfigManager.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using KianaBH.Configuration;
|
||||
using KianaBH.Internationalization;
|
||||
using Newtonsoft.Json;
|
||||
using KianaBH.Util.Extensions;
|
||||
|
||||
namespace KianaBH.Util;
|
||||
|
||||
public static class ConfigManager
|
||||
{
|
||||
public static readonly Logger Logger = new("ConfigManager");
|
||||
public static ConfigContainer Config { get; private set; } = new();
|
||||
private static readonly string ConfigFilePath = Config.Path.ConfigPath + "/Config.json";
|
||||
public static HotfixContainer Hotfix { get; private set; } = new();
|
||||
private static readonly string HotfixFilePath = Config.Path.ConfigPath + "/Hotfix.json";
|
||||
|
||||
public static void LoadConfig()
|
||||
{
|
||||
LoadConfigData();
|
||||
LoadHotfixData();
|
||||
}
|
||||
|
||||
private static void LoadConfigData()
|
||||
{
|
||||
var file = new FileInfo(ConfigFilePath);
|
||||
if (!file.Exists)
|
||||
{
|
||||
Config = new()
|
||||
{
|
||||
ServerOption =
|
||||
{
|
||||
Language = Extensions.Extensions.GetCurrentLanguage()
|
||||
}
|
||||
};
|
||||
|
||||
Logger.Info("Current Language is " + Config.ServerOption.Language);
|
||||
SaveData(Config, ConfigFilePath);
|
||||
}
|
||||
|
||||
using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var json = reader.ReadToEnd();
|
||||
Config = JsonConvert.DeserializeObject<ConfigContainer>(json)!;
|
||||
}
|
||||
|
||||
SaveData(Config, ConfigFilePath);
|
||||
}
|
||||
|
||||
private static void LoadHotfixData()
|
||||
{
|
||||
var file = new FileInfo(HotfixFilePath);
|
||||
|
||||
// Generate all necessary versions
|
||||
var verList = Extensions.Extensions.GetSupportVersions();
|
||||
|
||||
Logger.Info(I18NManager.Translate("Server.ServerInfo.CurrentVersion",
|
||||
verList.Aggregate((current, next) => $"{current}, {next}")));
|
||||
|
||||
if (!file.Exists)
|
||||
{
|
||||
Hotfix = new HotfixContainer();
|
||||
SaveData(Hotfix, HotfixFilePath);
|
||||
file.Refresh();
|
||||
}
|
||||
|
||||
using (var stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var reader = new StreamReader(stream))
|
||||
{
|
||||
var json = reader.ReadToEnd();
|
||||
Hotfix = JsonConvert.DeserializeObject<HotfixContainer>(json)!;
|
||||
}
|
||||
|
||||
foreach (var version in verList)
|
||||
if (!Hotfix.Hotfixes.TryGetValue(version, out var _))
|
||||
Hotfix.Hotfixes[version] = new();
|
||||
|
||||
SaveData(Hotfix, HotfixFilePath);
|
||||
}
|
||||
|
||||
private static void SaveData(object data, string path)
|
||||
{
|
||||
var json = JsonConvert.SerializeObject(data, Formatting.Indented);
|
||||
using var stream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
|
||||
using var writer = new StreamWriter(stream);
|
||||
writer.Write(json);
|
||||
}
|
||||
|
||||
public static void InitDirectories()
|
||||
{
|
||||
foreach (var property in Config.Path.GetType().GetProperties())
|
||||
{
|
||||
var dir = property.GetValue(Config.Path)?.ToString();
|
||||
|
||||
if (!string.IsNullOrEmpty(dir))
|
||||
if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Common/Util/Crpyto/DispatchEncryption.cs
Normal file
35
Common/Util/Crpyto/DispatchEncryption.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace KianaBH.Util.Crypto;
|
||||
|
||||
public static class DispatchEncryption
|
||||
{
|
||||
private static readonly JsonSerializerOptions JsonSerializerOptions = new()
|
||||
{
|
||||
PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower
|
||||
};
|
||||
|
||||
public static string? EncryptDispatchContent(string version, object? data)
|
||||
{
|
||||
if (!ConfigManager.Hotfix.AesKeys.TryGetValue(version, out var aesKey))
|
||||
return null;
|
||||
|
||||
var serializedData = JsonSerializer.Serialize(data, JsonSerializerOptions);
|
||||
var keyBytes = aesKey.Split(' ')
|
||||
.Select(b => Convert.ToByte(b, 16))
|
||||
.ToArray();
|
||||
|
||||
using var aes = Aes.Create();
|
||||
aes.Mode = CipherMode.ECB;
|
||||
aes.Padding = PaddingMode.PKCS7;
|
||||
aes.Key = keyBytes;
|
||||
|
||||
var encryptor = aes.CreateEncryptor();
|
||||
var dataBytes = Encoding.UTF8.GetBytes(serializedData);
|
||||
var encryptedBytes = encryptor.TransformFinalBlock(dataBytes, 0, dataBytes.Length);
|
||||
|
||||
return Convert.ToBase64String(encryptedBytes);
|
||||
}
|
||||
}
|
||||
232
Common/Util/Extensions/Extensions.cs
Normal file
232
Common/Util/Extensions/Extensions.cs
Normal file
@@ -0,0 +1,232 @@
|
||||
using KianaBH.Proto;
|
||||
using Newtonsoft.Json;
|
||||
using System.Buffers.Binary;
|
||||
using System.Globalization;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace KianaBH.Util.Extensions;
|
||||
|
||||
public static partial class Extensions
|
||||
{
|
||||
#region Regex
|
||||
|
||||
[GeneratedRegex(@"CN|OS|BETA|PROD|CECREATION|Android|Win|iOS")]
|
||||
public static partial Regex VersionRegex();
|
||||
|
||||
[GeneratedRegex(@"(?<=Avatar_)(.*?)(?=_Config)")]
|
||||
public static partial Regex AvatarConfigRegex();
|
||||
|
||||
[GeneratedRegex(@"(?<=Avatar_RogueBattleevent)(.*?)(?=_Config.json)")]
|
||||
public static partial Regex BattleEventDataRegex();
|
||||
|
||||
[GeneratedRegex(@"coin(\d+)tier")]
|
||||
public static partial Regex ProductRegex();
|
||||
|
||||
#endregion
|
||||
|
||||
public static string GetCurrentLanguage()
|
||||
{
|
||||
var uiCulture = CultureInfo.CurrentUICulture;
|
||||
return uiCulture.Name switch
|
||||
{
|
||||
"zh-CN" => "CHS",
|
||||
"zh-TW" => "CHT",
|
||||
"ja-JP" => "JP",
|
||||
_ => "EN"
|
||||
};
|
||||
}
|
||||
|
||||
public static List<string> GetSupportVersions()
|
||||
{
|
||||
var verList = new List<string>();
|
||||
if (GameConstants.GAME_VERSION[^1] == '5')
|
||||
for (var i = 1; i < 6; i++)
|
||||
verList.Add(GameConstants.GAME_VERSION + i.ToString());
|
||||
else
|
||||
verList.Add(GameConstants.GAME_VERSION);
|
||||
|
||||
return verList;
|
||||
}
|
||||
|
||||
public static T RandomElement<T>(this List<T> values)
|
||||
{
|
||||
var index = new Random().Next(values.Count);
|
||||
return values[index];
|
||||
}
|
||||
|
||||
public static string RandomKey(int length)
|
||||
{
|
||||
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
var random = new Random();
|
||||
return new string(Enumerable.Repeat(chars, length)
|
||||
.Select(s => s[random.Next(s.Length)]).ToArray());
|
||||
}
|
||||
|
||||
public static ICollection<T> Clone<T>(this ICollection<T> values)
|
||||
{
|
||||
List<T> list = [.. values];
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public static int RandomInt(int from, int to)
|
||||
{
|
||||
return new Random().Next(from, to);
|
||||
}
|
||||
|
||||
public static string GetSha256Hash(string input)
|
||||
{
|
||||
byte[] bytes = SHA256.HashData(Encoding.UTF8.GetBytes(input));
|
||||
var builder = new StringBuilder();
|
||||
for (int i = 0; i < bytes.Length; i++) builder.Append(bytes[i].ToString("x2"));
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public static void SafeAdd<T>(this List<T> list, T item)
|
||||
{
|
||||
if (!list.Contains(item)) list.Add(item);
|
||||
}
|
||||
|
||||
public static void SafeAddRange<T>(this List<T> list, List<T> item)
|
||||
{
|
||||
foreach (var i in item) list.SafeAdd(i);
|
||||
}
|
||||
|
||||
public static long GetUnixSec()
|
||||
{
|
||||
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
public static long ToUnixSec(this DateTime dt)
|
||||
{
|
||||
return new DateTimeOffset(dt).ToUnixTimeSeconds();
|
||||
}
|
||||
|
||||
public static long GetUnixMs()
|
||||
{
|
||||
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
|
||||
}
|
||||
|
||||
public static string ToArrayString<T>(this List<T> list)
|
||||
{
|
||||
return list.JoinFormat(", ", "");
|
||||
}
|
||||
|
||||
public static string ToJsonString<TK, TV>(this Dictionary<TK, TV> dic) where TK : notnull
|
||||
{
|
||||
return JsonConvert.SerializeObject(dic);
|
||||
}
|
||||
|
||||
public static byte[] StringToByteArray(string hex)
|
||||
{
|
||||
if (hex.Length % 2 == 1)
|
||||
throw new Exception("The binary key cannot have an odd number of digits");
|
||||
|
||||
byte[] arr = new byte[hex.Length >> 1];
|
||||
|
||||
for (int i = 0; i < hex.Length >> 1; ++i)
|
||||
{
|
||||
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
|
||||
}
|
||||
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static int GetHexVal(char hex)
|
||||
{
|
||||
int val = (int)hex;
|
||||
//For uppercase A-F letters:
|
||||
//return val - (val < 58 ? 48 : 55);
|
||||
//For lowercase a-f letters:
|
||||
//return val - (val < 58 ? 48 : 87);
|
||||
//Or the two combined, but a bit slower:
|
||||
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
|
||||
}
|
||||
|
||||
#region Kcp Utils
|
||||
|
||||
public static string JoinFormat<T>(this IEnumerable<T> list, string separator,
|
||||
string formatString)
|
||||
{
|
||||
formatString = string.IsNullOrWhiteSpace(formatString) ? "{0}" : formatString;
|
||||
return string.Join(separator,
|
||||
list.Select(item => string.Format(formatString, item)));
|
||||
}
|
||||
|
||||
public static void WriteConvID(this BinaryWriter bw, long convId)
|
||||
{
|
||||
//bw.Write(convId);
|
||||
bw.Write((int)(convId >> 32));
|
||||
bw.Write((int)(convId & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
public static long GetNextAvailableIndex<T>(this SortedList<long, T> sortedList)
|
||||
{
|
||||
long key = 1;
|
||||
long count = sortedList.Count;
|
||||
long counter = 0;
|
||||
do
|
||||
{
|
||||
if (count == 0) break;
|
||||
var nextKeyInList = sortedList.Keys.ElementAt((Index)counter++);
|
||||
if (key != nextKeyInList) break;
|
||||
key = nextKeyInList + 1;
|
||||
} while (count != 1 && counter != count && key == sortedList.Keys.ElementAt((Index)counter));
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
public static long AddNext<T>(this SortedList<long, T> sortedList, T item)
|
||||
{
|
||||
var key = sortedList.GetNextAvailableIndex();
|
||||
sortedList.Add(key, item);
|
||||
return key;
|
||||
}
|
||||
|
||||
public static int ReadInt32BE(this BinaryReader br)
|
||||
{
|
||||
return BinaryPrimitives.ReadInt32BigEndian(br.ReadBytes(sizeof(int)));
|
||||
}
|
||||
|
||||
public static uint ReadUInt32BE(this BinaryReader br)
|
||||
{
|
||||
return BinaryPrimitives.ReadUInt32BigEndian(br.ReadBytes(sizeof(uint)));
|
||||
}
|
||||
|
||||
public static ushort ReadUInt16BE(this BinaryReader br)
|
||||
{
|
||||
return BinaryPrimitives.ReadUInt16BigEndian(br.ReadBytes(sizeof(ushort)));
|
||||
}
|
||||
|
||||
public static void WriteUInt16BE(this BinaryWriter bw, ushort value)
|
||||
{
|
||||
Span<byte> data = stackalloc byte[sizeof(ushort)];
|
||||
BinaryPrimitives.WriteUInt16BigEndian(data, value);
|
||||
bw.Write(data);
|
||||
}
|
||||
|
||||
public static void WriteInt32BE(this BinaryWriter bw, int value)
|
||||
{
|
||||
Span<byte> data = stackalloc byte[sizeof(int)];
|
||||
BinaryPrimitives.WriteInt32BigEndian(data, value);
|
||||
bw.Write(data);
|
||||
}
|
||||
|
||||
public static void WriteUInt32BE(this BinaryWriter bw, uint value)
|
||||
{
|
||||
Span<byte> data = stackalloc byte[sizeof(uint)];
|
||||
BinaryPrimitives.WriteUInt32BigEndian(data, value);
|
||||
bw.Write(data);
|
||||
}
|
||||
|
||||
public static void WriteUInt64BE(this BinaryWriter bw, ulong value)
|
||||
{
|
||||
Span<byte> data = stackalloc byte[sizeof(ulong)];
|
||||
BinaryPrimitives.WriteUInt64BigEndian(data, value);
|
||||
bw.Write(data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
24
Common/Util/Extensions/JsonStringToObjectConverter.cs
Normal file
24
Common/Util/Extensions/JsonStringToObjectConverter.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace KianaBH.Util.Extensions;
|
||||
|
||||
public class JsonStringToObjectConverter<T> : JsonConverter<T> where T : class
|
||||
{
|
||||
public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
if (reader.TokenType != JsonTokenType.String)
|
||||
return JsonSerializer.Deserialize<T>(ref reader, options);
|
||||
|
||||
var jsonString = reader.GetString();
|
||||
return !string.IsNullOrEmpty(jsonString)
|
||||
? JsonSerializer.Deserialize<T>(jsonString, options)
|
||||
: null;
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options)
|
||||
{
|
||||
var json = JsonSerializer.Serialize(value, options);
|
||||
writer.WriteStringValue(json);
|
||||
}
|
||||
}
|
||||
11
Common/Util/GameConstants.cs
Normal file
11
Common/Util/GameConstants.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace KianaBH.Util;
|
||||
|
||||
public static class GameConstants
|
||||
{
|
||||
public const string GAME_VERSION = "8.2.0";
|
||||
public const int MAX_STAMINA = 300;
|
||||
public const int STAMINA_RECOVERY_TIME = 360; // 6 minutes
|
||||
public const int STAMINA_RESERVE_RECOVERY_TIME = 1080; // 18 minutes
|
||||
public const int INVENTORY_MAX_EQUIPMENT = 1000;
|
||||
public const int MAX_LINEUP_COUNT = 9;
|
||||
}
|
||||
185
Common/Util/IConsole.cs
Normal file
185
Common/Util/IConsole.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using Kodnix.Character;
|
||||
|
||||
namespace KianaBH.Util;
|
||||
|
||||
public class IConsole
|
||||
{
|
||||
public static readonly string PrefixContent = "[KianaBH]> ";
|
||||
public static readonly string Prefix = $"\u001b[38;2;255;192;203m{PrefixContent}\u001b[0m";
|
||||
private static readonly int HistoryMaxCount = 10;
|
||||
|
||||
public static List<char> Input { get; set; } = [];
|
||||
private static int CursorIndex { get; set; } = 0;
|
||||
private static readonly List<string> InputHistory = [];
|
||||
private static int HistoryIndex = -1;
|
||||
|
||||
public static event Action<string>? OnConsoleExcuteCommand;
|
||||
|
||||
public static void InitConsole()
|
||||
{
|
||||
Console.Title = ConfigManager.Config.GameServer.GameServerName;
|
||||
}
|
||||
|
||||
public static int GetWidth(string str)
|
||||
=> str.ToCharArray().Sum(EastAsianWidth.GetLength);
|
||||
|
||||
public static void RedrawInput(List<char> input, bool hasPrefix = true)
|
||||
=> RedrawInput(new string([.. input]), hasPrefix);
|
||||
|
||||
public static void RedrawInput(string input, bool hasPrefix = true)
|
||||
{
|
||||
var length = GetWidth(input);
|
||||
if (hasPrefix)
|
||||
{
|
||||
input = Prefix + input;
|
||||
length += GetWidth(PrefixContent);
|
||||
}
|
||||
|
||||
if (Console.GetCursorPosition().Left > 0)
|
||||
Console.SetCursorPosition(0, Console.CursorTop);
|
||||
|
||||
Console.Write(input + new string(' ', Console.BufferWidth - length));
|
||||
Console.SetCursorPosition(length, Console.CursorTop);
|
||||
}
|
||||
|
||||
#region Handlers
|
||||
|
||||
public static void HandleEnter()
|
||||
{
|
||||
var input = new string([.. Input]);
|
||||
if (string.IsNullOrWhiteSpace(input)) return;
|
||||
|
||||
// New line
|
||||
Console.WriteLine();
|
||||
Input = [];
|
||||
CursorIndex = 0;
|
||||
if (InputHistory.Count >= HistoryMaxCount)
|
||||
InputHistory.RemoveAt(0);
|
||||
InputHistory.Add(input);
|
||||
HistoryIndex = InputHistory.Count;
|
||||
|
||||
// Handle command
|
||||
if (input.StartsWith('/')) input = input[1..].Trim();
|
||||
OnConsoleExcuteCommand?.Invoke(input);
|
||||
}
|
||||
|
||||
public static void HandleBackspace()
|
||||
{
|
||||
if (CursorIndex <= 0) return;
|
||||
CursorIndex--;
|
||||
var targetWidth = GetWidth(Input[CursorIndex].ToString());
|
||||
Input.RemoveAt(CursorIndex);
|
||||
|
||||
var (left, _) = Console.GetCursorPosition();
|
||||
Console.SetCursorPosition(left - targetWidth, Console.CursorTop);
|
||||
var remain = new string([.. Input.Skip(CursorIndex)]);
|
||||
Console.Write(remain + new string(' ', targetWidth));
|
||||
Console.SetCursorPosition(left - targetWidth, Console.CursorTop);
|
||||
}
|
||||
|
||||
public static void HandleUpArrow()
|
||||
{
|
||||
if (InputHistory.Count == 0) return;
|
||||
|
||||
if (HistoryIndex > 0)
|
||||
{
|
||||
HistoryIndex--;
|
||||
var history = InputHistory[HistoryIndex];
|
||||
Input = [.. history];
|
||||
CursorIndex = Input.Count;
|
||||
RedrawInput(Input);
|
||||
}
|
||||
}
|
||||
|
||||
public static void HandleDownArrow()
|
||||
{
|
||||
if (HistoryIndex >= InputHistory.Count) return;
|
||||
|
||||
HistoryIndex++;
|
||||
if (HistoryIndex >= InputHistory.Count)
|
||||
{
|
||||
HistoryIndex = InputHistory.Count;
|
||||
Input = [];
|
||||
CursorIndex = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
var history = InputHistory[HistoryIndex];
|
||||
Input = [.. history];
|
||||
CursorIndex = Input.Count;
|
||||
}
|
||||
RedrawInput(Input);
|
||||
}
|
||||
|
||||
public static void HandleLeftArrow()
|
||||
{
|
||||
if (CursorIndex <= 0) return;
|
||||
|
||||
var (left, _) = Console.GetCursorPosition();
|
||||
CursorIndex--;
|
||||
Console.SetCursorPosition(left - GetWidth(Input[CursorIndex].ToString()), Console.CursorTop);
|
||||
}
|
||||
|
||||
public static void HandleRightArrow()
|
||||
{
|
||||
if (CursorIndex >= Input.Count) return;
|
||||
|
||||
var (left, _) = Console.GetCursorPosition();
|
||||
CursorIndex++;
|
||||
Console.SetCursorPosition(left + GetWidth(Input[CursorIndex - 1].ToString()), Console.CursorTop);
|
||||
}
|
||||
|
||||
public static void HandleInput(ConsoleKeyInfo keyInfo)
|
||||
{
|
||||
if (char.IsControl(keyInfo.KeyChar)) return;
|
||||
if (Input.Count >= (Console.BufferWidth - PrefixContent.Length)) return;
|
||||
HandleInput(keyInfo.KeyChar);
|
||||
}
|
||||
|
||||
public static void HandleInput(char keyChar)
|
||||
{
|
||||
Input.Insert(CursorIndex, keyChar);
|
||||
CursorIndex++;
|
||||
|
||||
var (left, _) = Console.GetCursorPosition();
|
||||
Console.Write(new string([.. Input.Skip(CursorIndex - 1)]));
|
||||
Console.SetCursorPosition(left + GetWidth(keyChar.ToString()), Console.CursorTop);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static string ListenConsole()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
ConsoleKeyInfo keyInfo;
|
||||
try { keyInfo = Console.ReadKey(true); }
|
||||
catch (InvalidOperationException) { continue; }
|
||||
|
||||
switch (keyInfo.Key)
|
||||
{
|
||||
case ConsoleKey.Enter:
|
||||
HandleEnter();
|
||||
break;
|
||||
case ConsoleKey.Backspace:
|
||||
HandleBackspace();
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
HandleLeftArrow();
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
HandleRightArrow();
|
||||
break;
|
||||
case ConsoleKey.UpArrow:
|
||||
HandleUpArrow();
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
HandleDownArrow();
|
||||
break;
|
||||
default:
|
||||
HandleInput(keyInfo);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
109
Common/Util/Logger.cs
Normal file
109
Common/Util/Logger.cs
Normal file
@@ -0,0 +1,109 @@
|
||||
using Spectre.Console;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace KianaBH.Util;
|
||||
|
||||
public class Logger(string moduleName)
|
||||
{
|
||||
private static FileInfo? LogFile;
|
||||
private static readonly object _lock = new();
|
||||
private readonly string ModuleName = moduleName;
|
||||
|
||||
public void Log(string message, LoggerLevel level)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
var savedInput = IConsole.Input.ToList(); // Copy
|
||||
IConsole.RedrawInput("", false);
|
||||
AnsiConsole.MarkupLine($"[[[bold deepskyblue3_1]{DateTime.Now:HH:mm:ss}[/]]] " +
|
||||
$"[[[gray]{ModuleName}[/]]] [[[{(ConsoleColor)level}]{level}[/]]] " +
|
||||
$"{message.Replace("[", "[[").Replace("]", "]]")}");
|
||||
IConsole.RedrawInput(savedInput);
|
||||
|
||||
var logMessage = $"[{DateTime.Now:HH:mm:ss}] [{ModuleName}] [{level}] {message}";
|
||||
WriteToFile(logMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public void Info(string message, Exception? e = null)
|
||||
{
|
||||
Log(message, LoggerLevel.INFO);
|
||||
if (e != null)
|
||||
{
|
||||
Log(e.Message, LoggerLevel.INFO);
|
||||
Log(e.StackTrace!, LoggerLevel.INFO);
|
||||
}
|
||||
}
|
||||
|
||||
public void Warn(string message, Exception? e = null)
|
||||
{
|
||||
Log(message, LoggerLevel.WARN);
|
||||
if (e != null)
|
||||
{
|
||||
Log(e.Message, LoggerLevel.WARN);
|
||||
Log(e.StackTrace!, LoggerLevel.WARN);
|
||||
}
|
||||
}
|
||||
|
||||
public void Error(string message, Exception? e = null)
|
||||
{
|
||||
Log(message, LoggerLevel.ERROR);
|
||||
if (e != null)
|
||||
{
|
||||
Log(e.Message, LoggerLevel.ERROR);
|
||||
Log(e.StackTrace!, LoggerLevel.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
public void Fatal(string message, Exception? e = null)
|
||||
{
|
||||
Log(message, LoggerLevel.FATAL);
|
||||
if (e != null)
|
||||
{
|
||||
Log(e.Message, LoggerLevel.FATAL);
|
||||
Log(e.StackTrace!, LoggerLevel.FATAL);
|
||||
}
|
||||
}
|
||||
|
||||
public void Debug(string message, Exception? e = null)
|
||||
{
|
||||
Log(message, LoggerLevel.DEBUG);
|
||||
if (e != null)
|
||||
{
|
||||
Log(e.Message, LoggerLevel.DEBUG);
|
||||
Log(e.StackTrace!, LoggerLevel.DEBUG);
|
||||
}
|
||||
}
|
||||
|
||||
public static void SetLogFile(FileInfo file)
|
||||
{
|
||||
LogFile = file;
|
||||
}
|
||||
|
||||
public static void WriteToFile(string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (LogFile == null) throw new Exception("LogFile is not set");
|
||||
using var sw = LogFile.AppendText();
|
||||
sw.WriteLine(message);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static Logger GetByClassName()
|
||||
{
|
||||
return new Logger(new StackTrace().GetFrame(1)?.GetMethod()?.ReflectedType?.Name ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
public enum LoggerLevel
|
||||
{
|
||||
INFO = ConsoleColor.Cyan,
|
||||
WARN = ConsoleColor.Yellow,
|
||||
ERROR = ConsoleColor.Red,
|
||||
FATAL = ConsoleColor.DarkRed,
|
||||
DEBUG = ConsoleColor.Blue
|
||||
}
|
||||
34
Common/Util/LoggingMiddleware.cs
Normal file
34
Common/Util/LoggingMiddleware.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using KianaBH.Util;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace KianaBH.SdkServer.Utils;
|
||||
|
||||
public class RequestLoggingMiddleware(RequestDelegate next)
|
||||
{
|
||||
public async Task InvokeAsync(HttpContext context, Logger logger)
|
||||
{
|
||||
var request = context.Request;
|
||||
var method = request.Method;
|
||||
var path = request.Path + request.QueryString;
|
||||
|
||||
await next(context);
|
||||
|
||||
var statusCode = context.Response.StatusCode;
|
||||
|
||||
if (path.StartsWith("/report") || path.Contains("/log/") || path == "/alive")
|
||||
return;
|
||||
|
||||
if (statusCode == 200)
|
||||
{
|
||||
logger.Info($"{method} {path} => {statusCode}");
|
||||
}
|
||||
else if (statusCode == 404)
|
||||
{
|
||||
logger.Warn($"{method} {path} => {statusCode}");
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.Error($"{method} {path} => {statusCode}");
|
||||
}
|
||||
}
|
||||
}
|
||||
29
Common/Util/Security/Crypto.cs
Normal file
29
Common/Util/Security/Crypto.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace KianaBH.Util.Security;
|
||||
|
||||
public class Crypto
|
||||
{
|
||||
private static readonly Random SecureRandom = new();
|
||||
|
||||
// Simple way to create a unique session key
|
||||
public static string CreateSessionKey(string accountUid)
|
||||
{
|
||||
var random = new byte[64];
|
||||
SecureRandom.NextBytes(random);
|
||||
|
||||
var temp = accountUid + "." + DateTime.Now.Ticks + "." + SecureRandom;
|
||||
|
||||
try
|
||||
{
|
||||
var bytes = SHA512.HashData(Encoding.UTF8.GetBytes(temp));
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
catch
|
||||
{
|
||||
var bytes = SHA512.HashData(Encoding.UTF8.GetBytes(temp));
|
||||
return Convert.ToBase64String(bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user