214 lines
7.4 KiB
C#
214 lines
7.4 KiB
C#
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace BarrageGrab
|
|
{
|
|
/// <summary>
|
|
/// 快手礼物ID→名称映射表,通过代理嗅探自动收集
|
|
/// </summary>
|
|
public static class KsGiftHelper
|
|
{
|
|
private static readonly ConcurrentDictionary<uint, string> GiftNames = new ConcurrentDictionary<uint, string>();
|
|
private static readonly string GiftCachePath;
|
|
|
|
static KsGiftHelper()
|
|
{
|
|
GiftCachePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "ks_gifts.json");
|
|
LoadMapping();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取礼物名称,找不到返回 null
|
|
/// </summary>
|
|
public static string GetGiftName(uint giftId)
|
|
{
|
|
GiftNames.TryGetValue(giftId, out var name);
|
|
return name;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 尝试从任意 JSON 字符串中解析礼物映射
|
|
/// 支持多种快手 API 返回格式:
|
|
/// - giftList: [{id:1, name:"小红花"}, ...]
|
|
/// - giftPanelList: [{id:1, giftName:"小红花"}, ...]
|
|
/// - allGifts: {"1": {name:"小红花"}, ...}
|
|
/// 返回是否解析到了新数据
|
|
/// </summary>
|
|
public static bool TryParseGiftData(string json)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(json)) return false;
|
|
json = json.Trim();
|
|
if (json.Length < 10) return false;
|
|
|
|
bool added = false;
|
|
|
|
try
|
|
{
|
|
// 如果 JSON 以数组开头,需要特殊处理
|
|
if (json.StartsWith("["))
|
|
{
|
|
var arr = JArray.Parse(json);
|
|
added = ParseGiftArray(arr) || added;
|
|
return added;
|
|
}
|
|
|
|
var obj = JObject.Parse(json);
|
|
|
|
// 方式1: giftList → [{id, name}] 或 giftList → [{id, giftName}]
|
|
var giftList = obj["giftList"] as JArray;
|
|
if (giftList != null)
|
|
{
|
|
added = ParseGiftArray(giftList) || added;
|
|
}
|
|
|
|
// 方式2: giftPanelList → [{id, name}]
|
|
var giftPanelList = obj["giftPanelList"] as JArray;
|
|
if (giftPanelList != null)
|
|
{
|
|
added = ParseGiftArray(giftPanelList) || added;
|
|
}
|
|
|
|
// 方式3: allGifts → {"1": {name:"xxx"}, "2": {...}}
|
|
var allGifts = obj["allGifts"] as JObject;
|
|
if (allGifts != null)
|
|
{
|
|
foreach (var kv in allGifts)
|
|
{
|
|
if (uint.TryParse(kv.Key, out var gid))
|
|
{
|
|
var name = kv.Value?["name"]?.Value<string>()
|
|
?? kv.Value?["giftName"]?.Value<string>()
|
|
?? kv.Value?["title"]?.Value<string>();
|
|
if (!string.IsNullOrWhiteSpace(name))
|
|
{
|
|
added = UpdateMapping(gid, name) || added;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 方式4: data.giftList / data.giftPanelList / result.giftList
|
|
var data = obj["data"] ?? obj["result"];
|
|
if (data is JObject dataObj)
|
|
{
|
|
var dataGiftList = dataObj["giftList"] as JArray;
|
|
if (dataGiftList != null)
|
|
{
|
|
added = ParseGiftArray(dataGiftList) || added;
|
|
}
|
|
var dataGiftPanel = dataObj["giftPanelList"] as JArray;
|
|
if (dataGiftPanel != null)
|
|
{
|
|
added = ParseGiftArray(dataGiftPanel) || added;
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// 不是有效 JSON,忽略
|
|
}
|
|
|
|
return added;
|
|
}
|
|
|
|
private static bool ParseGiftArray(JArray arr)
|
|
{
|
|
bool added = false;
|
|
foreach (var item in arr)
|
|
{
|
|
if (item is JObject giftObj)
|
|
{
|
|
var idToken = giftObj["id"] ?? giftObj["giftId"];
|
|
var nameToken = giftObj["giftName"] ?? giftObj["name"] ?? giftObj["title"] ?? giftObj["displayName"];
|
|
|
|
if (idToken != null && nameToken != null)
|
|
{
|
|
uint id = 0;
|
|
if (idToken.Type == JTokenType.Integer)
|
|
id = idToken.Value<uint>();
|
|
else if (idToken.Type == JTokenType.String && uint.TryParse(idToken.Value<string>(), out var sid))
|
|
id = sid;
|
|
else
|
|
continue;
|
|
|
|
var name = nameToken.Value<string>();
|
|
if (!string.IsNullOrWhiteSpace(name) && id > 0)
|
|
{
|
|
added = UpdateMapping(id, name) || added;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return added;
|
|
}
|
|
|
|
private static bool UpdateMapping(uint giftId, string giftName)
|
|
{
|
|
if (GiftNames.TryGetValue(giftId, out var existing) && existing == giftName)
|
|
return false;
|
|
|
|
GiftNames[giftId] = giftName;
|
|
Logger.LogInfo($"KS礼物映射: #{giftId} → {giftName}");
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 保存映射到本地文件
|
|
/// </summary>
|
|
public static void SaveMapping()
|
|
{
|
|
if (GiftNames.Count == 0) return;
|
|
|
|
try
|
|
{
|
|
var dict = new Dictionary<uint, string>();
|
|
foreach (var kv in GiftNames) dict[kv.Key] = kv.Value;
|
|
var json = JsonConvert.SerializeObject(dict, Formatting.Indented);
|
|
File.WriteAllText(GiftCachePath, json);
|
|
Logger.LogInfo($"KS礼物映射已保存 ({GiftNames.Count} 个) → {GiftCachePath}");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogWarn($"保存KS礼物映射失败: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 从本地文件加载映射
|
|
/// </summary>
|
|
private static void LoadMapping()
|
|
{
|
|
try
|
|
{
|
|
if (!File.Exists(GiftCachePath)) return;
|
|
|
|
var json = File.ReadAllText(GiftCachePath);
|
|
var dict = JsonConvert.DeserializeObject<Dictionary<uint, string>>(json);
|
|
if (dict != null)
|
|
{
|
|
foreach (var kv in dict)
|
|
{
|
|
GiftNames[kv.Key] = kv.Value;
|
|
}
|
|
Logger.LogInfo($"KS礼物映射已加载 ({GiftNames.Count} 个) → {GiftCachePath}");
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.LogWarn($"加载KS礼物映射失败: {ex.Message}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取当前映射数量
|
|
/// </summary>
|
|
public static int Count => GiftNames.Count;
|
|
}
|
|
}
|