mirror of
https://github.com/oshima-studios/OshimaGameModule.git
synced 2025-04-23 20:39:36 +08:00
模组架构修改
This commit is contained in:
parent
d26a1ccdd7
commit
d5327af742
@ -1,6 +1,6 @@
|
|||||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaModules
|
namespace Oshima.Core.Constant
|
||||||
{
|
{
|
||||||
public class OshimaGameModuleConstant
|
public class OshimaGameModuleConstant
|
||||||
{
|
{
|
||||||
@ -16,6 +16,7 @@ namespace Oshima.FunGame.OshimaModules
|
|||||||
public const string FastAutoMap = "oshima.fungame.fastauto.map";
|
public const string FastAutoMap = "oshima.fungame.fastauto.map";
|
||||||
public const string Anonymous = "oshima.fungame.anonymous";
|
public const string Anonymous = "oshima.fungame.anonymous";
|
||||||
public const string AnonymousMap = "oshima.fungame.anonymous.map";
|
public const string AnonymousMap = "oshima.fungame.anonymous.map";
|
||||||
|
public const string Server = "oshima.fungame.server";
|
||||||
|
|
||||||
private static readonly string[] Maps = [FastAutoMap];
|
private static readonly string[] Maps = [FastAutoMap];
|
||||||
private static readonly string[] Characters = [Character];
|
private static readonly string[] Characters = [Character];
|
@ -1,5 +1,5 @@
|
|||||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaMaps
|
namespace Oshima.FunGame.OshimaMaps
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaMaps
|
namespace Oshima.FunGame.OshimaMaps
|
||||||
{
|
{
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OshimaModules\OshimaModules.csproj" />
|
<ProjectReference Include="..\OshimaCore\OshimaCore.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -5,7 +5,7 @@ using Milimoe.FunGame.Core.Library.Common.Addon;
|
|||||||
using Milimoe.FunGame.Core.Library.Common.Event;
|
using Milimoe.FunGame.Core.Library.Common.Event;
|
||||||
using Milimoe.FunGame.Core.Library.Constant;
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
using Milimoe.FunGame.Core.Model;
|
using Milimoe.FunGame.Core.Model;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaModes
|
namespace Oshima.FunGame.OshimaModes
|
||||||
{
|
{
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Milimoe.FunGame.Core.Entity;
|
using Milimoe.FunGame.Core.Entity;
|
||||||
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaModules.Characters;
|
using Oshima.FunGame.OshimaModules.Characters;
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaModules
|
namespace Oshima.FunGame.OshimaModules
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Milimoe.FunGame.Core.Entity;
|
using Milimoe.FunGame.Core.Entity;
|
||||||
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaModules.Items;
|
using Oshima.FunGame.OshimaModules.Items;
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaModules
|
namespace Oshima.FunGame.OshimaModules
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Milimoe.FunGame.Core.Entity;
|
using Milimoe.FunGame.Core.Entity;
|
||||||
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaModules.Effects.ItemEffects;
|
using Oshima.FunGame.OshimaModules.Effects.ItemEffects;
|
||||||
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
|
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
|
||||||
using Oshima.FunGame.OshimaModules.Items;
|
using Oshima.FunGame.OshimaModules.Items;
|
||||||
|
@ -22,6 +22,10 @@
|
|||||||
<NoWarn>1701;1702;CS8981;IDE1006;IDE0130</NoWarn>
|
<NoWarn>1701;1702;CS8981;IDE1006;IDE0130</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\OshimaCore\OshimaCore.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="FunGame.Core">
|
<Reference Include="FunGame.Core">
|
||||||
<HintPath>..\..\FunGame.Core\bin\Debug\net9.0\FunGame.Core.dll</HintPath>
|
<HintPath>..\..\FunGame.Core\bin\Debug\net9.0\FunGame.Core.dll</HintPath>
|
||||||
|
@ -5,10 +5,8 @@ using Milimoe.FunGame.Core.Entity;
|
|||||||
using Milimoe.FunGame.Core.Interface.Base;
|
using Milimoe.FunGame.Core.Interface.Base;
|
||||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
using Milimoe.FunGame.Core.Library.Constant;
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
using Oshima.Core;
|
|
||||||
using Oshima.Core.Configs;
|
using Oshima.Core.Configs;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaServers.Service;
|
|
||||||
|
|
||||||
namespace Oshima.FunGame.OshimaServers
|
namespace Oshima.FunGame.OshimaServers
|
||||||
{
|
{
|
||||||
@ -94,9 +92,6 @@ namespace Oshima.FunGame.OshimaServers
|
|||||||
{
|
{
|
||||||
Controller.NewSQLHelper();
|
Controller.NewSQLHelper();
|
||||||
Controller.NewMailSender();
|
Controller.NewMailSender();
|
||||||
OSMCore.InitOSMCore();
|
|
||||||
FunGameService.InitFunGame();
|
|
||||||
FunGameSimulation.InitFunGameSimulation();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -7,7 +7,7 @@ using Milimoe.FunGame.Core.Interface.Base;
|
|||||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
using Milimoe.FunGame.Core.Library.Constant;
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
using Milimoe.FunGame.Core.Model;
|
using Milimoe.FunGame.Core.Model;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaModules.Items;
|
using Oshima.FunGame.OshimaModules.Items;
|
||||||
using Oshima.FunGame.OshimaModules.Skills;
|
using Oshima.FunGame.OshimaModules.Skills;
|
||||||
using Oshima.FunGame.OshimaServers.Service;
|
using Oshima.FunGame.OshimaServers.Service;
|
||||||
|
129
OshimaServers/OshimaServer.cs
Normal file
129
OshimaServers/OshimaServer.cs
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
|
using Milimoe.FunGame.Core.Entity;
|
||||||
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
|
using Oshima.Core;
|
||||||
|
using Oshima.Core.Configs;
|
||||||
|
using Oshima.Core.Constant;
|
||||||
|
using Oshima.FunGame.OshimaServers.Service;
|
||||||
|
using TaskScheduler = Milimoe.FunGame.Core.Api.Utility.TaskScheduler;
|
||||||
|
|
||||||
|
namespace Oshima.FunGame.OshimaServers
|
||||||
|
{
|
||||||
|
public class OshimaServer : ServerPlugin
|
||||||
|
{
|
||||||
|
public override string Name => OshimaGameModuleConstant.Server;
|
||||||
|
|
||||||
|
public override string Description => OshimaGameModuleConstant.Description;
|
||||||
|
|
||||||
|
public override string Version => OshimaGameModuleConstant.Version;
|
||||||
|
|
||||||
|
public override string Author => OshimaGameModuleConstant.Author;
|
||||||
|
|
||||||
|
public override void ProcessInput(string input)
|
||||||
|
{
|
||||||
|
if (input.StartsWith("fungametest"))
|
||||||
|
{
|
||||||
|
FunGameSimulation.StartSimulationGame(true, true);
|
||||||
|
}
|
||||||
|
// OSM指令
|
||||||
|
if (input.Length >= 4 && input[..4].Equals(".osm", StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
//MasterCommand.Execute(read, GeneralSettings.Master, false, GeneralSettings.Master, false);
|
||||||
|
Controller.WriteLine("试图使用 .osm 指令:" + input);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void AfterLoad(ServerPluginLoader loader, params object[] objs)
|
||||||
|
{
|
||||||
|
Controller.NewSQLHelper();
|
||||||
|
Controller.NewMailSender();
|
||||||
|
OSMCore.InitOSMCore();
|
||||||
|
FunGameService.InitFunGame();
|
||||||
|
FunGameSimulation.InitFunGameSimulation();
|
||||||
|
TaskScheduler.Shared.AddTask("重置每日运势", new TimeSpan(0, 0, 0), () =>
|
||||||
|
{
|
||||||
|
Controller.WriteLine("已重置所有人的今日运势");
|
||||||
|
Daily.ClearDaily();
|
||||||
|
});
|
||||||
|
TaskScheduler.Shared.AddTask("重置交易冷却1", new TimeSpan(9, 0, 0), () =>
|
||||||
|
{
|
||||||
|
Controller.WriteLine("重置物品交易冷却时间");
|
||||||
|
_ = FunGameService.AllowSellAndTrade();
|
||||||
|
});
|
||||||
|
TaskScheduler.Shared.AddTask("重置交易冷却2", new TimeSpan(15, 0, 0), () =>
|
||||||
|
{
|
||||||
|
Controller.WriteLine("重置物品交易冷却时间");
|
||||||
|
_ = FunGameService.AllowSellAndTrade();
|
||||||
|
});
|
||||||
|
TaskScheduler.Shared.AddRecurringTask("刷新存档缓存", TimeSpan.FromMinutes(1), () =>
|
||||||
|
{
|
||||||
|
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
|
||||||
|
if (Directory.Exists(directoryPath))
|
||||||
|
{
|
||||||
|
string[] filePaths = Directory.GetFiles(directoryPath);
|
||||||
|
foreach (string filePath in filePaths)
|
||||||
|
{
|
||||||
|
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
PluginConfig pc = new("saved", fileName);
|
||||||
|
pc.LoadConfig();
|
||||||
|
if (pc.Count > 0)
|
||||||
|
{
|
||||||
|
User user = FunGameService.GetUser(pc);
|
||||||
|
// 将用户存入缓存
|
||||||
|
FunGameService.UserIdAndUsername[user.Id] = user;
|
||||||
|
// 任务结算
|
||||||
|
EntityModuleConfig<Quest> quests = new("quests", user.Id.ToString());
|
||||||
|
quests.LoadConfig();
|
||||||
|
if (quests.Count > 0 && FunGameService.SettleQuest(user, quests))
|
||||||
|
{
|
||||||
|
quests.SaveConfig();
|
||||||
|
user.LastTime = DateTime.Now;
|
||||||
|
pc.Add("user", user);
|
||||||
|
pc.SaveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Controller.WriteLine("读取 FunGame 存档缓存", LogLevel.Debug);
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
TaskScheduler.Shared.AddTask("刷新每日任务", new TimeSpan(4, 0, 0), () =>
|
||||||
|
{
|
||||||
|
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/quests";
|
||||||
|
if (Directory.Exists(directoryPath))
|
||||||
|
{
|
||||||
|
string[] filePaths = Directory.GetFiles(directoryPath);
|
||||||
|
foreach (string filePath in filePaths)
|
||||||
|
{
|
||||||
|
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
EntityModuleConfig<Quest> quests = new("quests", fileName);
|
||||||
|
quests.Clear();
|
||||||
|
FunGameService.CheckQuestList(quests);
|
||||||
|
quests.SaveConfig();
|
||||||
|
}
|
||||||
|
Controller.WriteLine("刷新每日任务");
|
||||||
|
}
|
||||||
|
// 刷新签到
|
||||||
|
directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
|
||||||
|
if (Directory.Exists(directoryPath))
|
||||||
|
{
|
||||||
|
string[] filePaths = Directory.GetFiles(directoryPath);
|
||||||
|
foreach (string filePath in filePaths)
|
||||||
|
{
|
||||||
|
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
PluginConfig pc = new("saved", fileName);
|
||||||
|
pc.LoadConfig();
|
||||||
|
pc.Add("signed", false);
|
||||||
|
pc.SaveConfig();
|
||||||
|
}
|
||||||
|
Controller.WriteLine("刷新签到");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
TaskScheduler.Shared.AddRecurringTask("刷新boss", TimeSpan.FromHours(1), () =>
|
||||||
|
{
|
||||||
|
FunGameService.GenerateBoss();
|
||||||
|
Controller.WriteLine("刷新boss");
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,7 +2,7 @@ using System.Text;
|
|||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Milimoe.FunGame.Core.Entity;
|
using Milimoe.FunGame.Core.Entity;
|
||||||
using Milimoe.FunGame.Core.Library.Constant;
|
using Milimoe.FunGame.Core.Library.Constant;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaModules.Characters;
|
using Oshima.FunGame.OshimaModules.Characters;
|
||||||
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
|
using Oshima.FunGame.OshimaModules.Effects.OpenEffects;
|
||||||
using Oshima.FunGame.OshimaModules.Items;
|
using Oshima.FunGame.OshimaModules.Items;
|
||||||
|
160
OshimaWebAPI/Controllers/QQBotController.cs
Normal file
160
OshimaWebAPI/Controllers/QQBotController.cs
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Oshima.FunGame.WebAPI.Models;
|
||||||
|
using Oshima.FunGame.WebAPI.Services;
|
||||||
|
using Rebex.Security.Cryptography;
|
||||||
|
|
||||||
|
namespace Oshima.FunGame.WebAPI.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("[controller]")]
|
||||||
|
public class QQBotController(IOptions<BotConfig> botConfig, ILogger<QQBotController> logger, QQBotService service) : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly BotConfig _botConfig = botConfig.Value;
|
||||||
|
private readonly ILogger<QQBotController> _logger = logger;
|
||||||
|
private readonly QQBotService _service = service;
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Post([FromBody] Payload? payload)
|
||||||
|
{
|
||||||
|
if (payload is null)
|
||||||
|
{
|
||||||
|
return BadRequest("Payload 格式无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogDebug("收到 Webhook 请求:{payload}", payload);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (payload.Op == 13)
|
||||||
|
{
|
||||||
|
return HandleValidation(payload);
|
||||||
|
}
|
||||||
|
else if (payload.Op == 0)
|
||||||
|
{
|
||||||
|
// 处理其他事件
|
||||||
|
return await HandleEventAsync(payload);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogWarning("未处理操作码:{payload.Op}", payload.Op);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError("Error: {e}", e);
|
||||||
|
return StatusCode(500, "服务器内部错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IActionResult HandleValidation(Payload payload)
|
||||||
|
{
|
||||||
|
ValidationRequest? validationPayload = JsonSerializer.Deserialize<ValidationRequest>(payload.Data.ToString() ?? "");
|
||||||
|
if (validationPayload is null)
|
||||||
|
{
|
||||||
|
_logger.LogError("反序列化验证 Payload 失败");
|
||||||
|
return BadRequest("无效的验证 Payload 格式");
|
||||||
|
}
|
||||||
|
string seed = _botConfig.Secret;
|
||||||
|
while (seed.Length < 32)
|
||||||
|
{
|
||||||
|
seed += seed;
|
||||||
|
}
|
||||||
|
seed = seed[..32];
|
||||||
|
|
||||||
|
byte[] privateKeyBytes = Encoding.UTF8.GetBytes(seed);
|
||||||
|
|
||||||
|
Ed25519 ed25519 = new();
|
||||||
|
|
||||||
|
ed25519.FromSeed(privateKeyBytes);
|
||||||
|
|
||||||
|
// 将你的消息转换为 byte[]
|
||||||
|
byte[] message = Encoding.UTF8.GetBytes(validationPayload.EventTs + validationPayload.PlainToken);
|
||||||
|
|
||||||
|
// 使用 Sign 方法签名消息
|
||||||
|
byte[] result = ed25519.SignMessage(message);
|
||||||
|
|
||||||
|
string signature = Convert.ToHexString(result).ToLower(CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
|
|
||||||
|
ValidationResponse response = new()
|
||||||
|
{
|
||||||
|
PlainToken = validationPayload.PlainToken,
|
||||||
|
Signature = signature
|
||||||
|
};
|
||||||
|
string responseJson = JsonSerializer.Serialize(response);
|
||||||
|
_logger.LogDebug("验证相应:{responseJson}", responseJson);
|
||||||
|
return Ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IActionResult> HandleEventAsync(Payload payload)
|
||||||
|
{
|
||||||
|
_logger.LogDebug("处理事件:{EventType}, 数据:{Data}", payload.EventType, payload.Data);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
switch (payload.EventType)
|
||||||
|
{
|
||||||
|
case "C2C_MESSAGE_CREATE":
|
||||||
|
C2CMessage? c2cMessage = JsonSerializer.Deserialize<C2CMessage>(payload.Data.ToString() ?? "");
|
||||||
|
if (c2cMessage != null)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
_logger.LogInformation("收到来自用户 {c2cMessage.Author.UserOpenId} 的消息:{c2cMessage.Content}", c2cMessage.Author.UserOpenId, c2cMessage.Content);
|
||||||
|
// 上传图片
|
||||||
|
var (fileUuid, fileInfo, ttl, error) = await _service.UploadC2CMediaAsync(c2cMessage.Author.UserOpenId, 1, $"{Request.Scheme}://{Request.Host}{Request.PathBase}/images/zi/dj1.png");
|
||||||
|
if (string.IsNullOrEmpty(error))
|
||||||
|
{
|
||||||
|
// 回复富媒体消息
|
||||||
|
await _service.SendC2CMessageAsync(c2cMessage.Author.UserOpenId, "", msgType: 7, media: new { file_info = fileInfo });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("上传图片失败:{error}", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("反序列化 C2C 消息数据失败");
|
||||||
|
return BadRequest("无效的 C2C 消息数据格式");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case "GROUP_AT_MESSAGE_CREATE":
|
||||||
|
GroupAtMessage? groupAtMessage = JsonSerializer.Deserialize<GroupAtMessage>(payload.Data.ToString() ?? "");
|
||||||
|
if (groupAtMessage != null)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
_logger.LogInformation("收到来自群组 {groupAtMessage.GroupOpenId} 的消息:{groupAtMessage.Content}", groupAtMessage.GroupOpenId, groupAtMessage.Content);
|
||||||
|
// 回复消息
|
||||||
|
await _service.SendGroupMessageAsync(groupAtMessage.GroupOpenId, $"你发送的消息是:{groupAtMessage.Content}", msgType: 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_logger.LogError("反序列化群聊消息数据失败");
|
||||||
|
return BadRequest("无效的群聊消息数据格式");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
_logger.LogWarning("未定义事件:{EventType}", payload.EventType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (JsonException e)
|
||||||
|
{
|
||||||
|
_logger.LogError("反序列化过程遇到错误:{e}", e);
|
||||||
|
return BadRequest("Invalid JSON format");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_logger.LogError("Error: {e}", e);
|
||||||
|
return StatusCode(500, "服务器内部错误");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,7 @@ using Microsoft.Extensions.Logging;
|
|||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Oshima.Core.Configs;
|
using Oshima.Core.Configs;
|
||||||
using Oshima.FunGame.WebAPI.Models;
|
using Oshima.FunGame.WebAPI.Models;
|
||||||
using Oshima.FunGame.WebAPI.Utils;
|
using Oshima.FunGame.WebAPI.Services;
|
||||||
|
|
||||||
namespace Oshima.FunGame.WebAPI.Controllers
|
namespace Oshima.FunGame.WebAPI.Controllers
|
||||||
{
|
{
|
||||||
@ -16,13 +16,13 @@ namespace Oshima.FunGame.WebAPI.Controllers
|
|||||||
[HttpPost("get/{user_id}", Name = "GetUserDaily")]
|
[HttpPost("get/{user_id}", Name = "GetUserDaily")]
|
||||||
public UserDaily Get(long user_id)
|
public UserDaily Get(long user_id)
|
||||||
{
|
{
|
||||||
return UserDailyUtil.GetUserDaily(user_id);
|
return UserDailyService.GetUserDaily(user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("view/{user_id}", Name = "ViewUserDaily")]
|
[HttpGet("view/{user_id}", Name = "ViewUserDaily")]
|
||||||
public UserDaily View(long user_id)
|
public UserDaily View(long user_id)
|
||||||
{
|
{
|
||||||
return UserDailyUtil.ViewUserDaily(user_id);
|
return UserDailyService.ViewUserDaily(user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("open/{open_id}", Name = "GetOpenUserDaily")]
|
[HttpPost("open/{open_id}", Name = "GetOpenUserDaily")]
|
||||||
@ -30,7 +30,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
|
|||||||
{
|
{
|
||||||
if (QQOpenID.QQAndOpenID.TryGetValue(open_id, out long qq) && qq != 0)
|
if (QQOpenID.QQAndOpenID.TryGetValue(open_id, out long qq) && qq != 0)
|
||||||
{
|
{
|
||||||
return UserDailyUtil.GetUserDaily(qq);
|
return UserDailyService.GetUserDaily(qq);
|
||||||
}
|
}
|
||||||
return new(0, 0, "你似乎没有绑定QQ呢,请先发送【绑定+QQ号】(如:绑定123456789)再使用哦!");
|
return new(0, 0, "你似乎没有绑定QQ呢,请先发送【绑定+QQ号】(如:绑定123456789)再使用哦!");
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ namespace Oshima.FunGame.WebAPI.Controllers
|
|||||||
[HttpPost("remove/{user_id}", Name = "RemoveUserDaily")]
|
[HttpPost("remove/{user_id}", Name = "RemoveUserDaily")]
|
||||||
public string Remove(long user_id)
|
public string Remove(long user_id)
|
||||||
{
|
{
|
||||||
return UserDailyUtil.RemoveDaily(user_id);
|
return UserDailyService.RemoveDaily(user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("img/{type}", Name = "GetTypeImage")]
|
[HttpGet("img/{type}", Name = "GetTypeImage")]
|
||||||
|
136
OshimaWebAPI/Models/QQBot.cs
Normal file
136
OshimaWebAPI/Models/QQBot.cs
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace Oshima.FunGame.WebAPI.Models
|
||||||
|
{
|
||||||
|
public class Payload
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public string Id { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("op")]
|
||||||
|
public int Op { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonPropertyName("d")]
|
||||||
|
public object Data { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonPropertyName("s")]
|
||||||
|
public int SequenceNumber { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonPropertyName("t")]
|
||||||
|
public string EventType { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ValidationRequest
|
||||||
|
{
|
||||||
|
[JsonPropertyName("plain_token")]
|
||||||
|
public string PlainToken { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("event_ts")]
|
||||||
|
public string EventTs { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ValidationResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("plain_token")]
|
||||||
|
public string PlainToken { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("signature")]
|
||||||
|
public string Signature { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BotConfig
|
||||||
|
{
|
||||||
|
public string AppId { get; set; } = "";
|
||||||
|
public string Secret { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Author
|
||||||
|
{
|
||||||
|
[JsonPropertyName("user_openid")]
|
||||||
|
public string UserOpenId { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("member_openid")]
|
||||||
|
public string MemberOpenId { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Attachment
|
||||||
|
{
|
||||||
|
[JsonPropertyName("content_type")]
|
||||||
|
public string ContentType { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("filename")]
|
||||||
|
public string Filename { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("height")]
|
||||||
|
public int Height { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonPropertyName("width")]
|
||||||
|
public int Width { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonPropertyName("size")]
|
||||||
|
public int Size { get; set; } = 0;
|
||||||
|
|
||||||
|
[JsonPropertyName("url")]
|
||||||
|
public string Url { get; set; } = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public class C2CMessage
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public string Id { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("author")]
|
||||||
|
public Author Author { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonPropertyName("content")]
|
||||||
|
public string Content { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("timestamp")]
|
||||||
|
public string Timestamp { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("attachments")]
|
||||||
|
public Attachment[] Attachments { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GroupAtMessage
|
||||||
|
{
|
||||||
|
[JsonPropertyName("id")]
|
||||||
|
public string Id { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("author")]
|
||||||
|
public Author Author { get; set; } = new();
|
||||||
|
|
||||||
|
[JsonPropertyName("content")]
|
||||||
|
public string Content { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("timestamp")]
|
||||||
|
public string Timestamp { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("group_openid")]
|
||||||
|
public string GroupOpenId { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("attachments")]
|
||||||
|
public Attachment[] Attachments { get; set; } = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
public class MediaResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("file_uuid")]
|
||||||
|
public string FileUuid { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("file_info")]
|
||||||
|
public string FileInfo { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("ttl")]
|
||||||
|
public int Ttl { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AccessTokenResponse
|
||||||
|
{
|
||||||
|
[JsonPropertyName("access_token")]
|
||||||
|
public string AccessToken { get; set; } = "";
|
||||||
|
|
||||||
|
[JsonPropertyName("expires_in")]
|
||||||
|
public string ExpiresIn { get; set; } = "";
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Milimoe.FunGame.Core.Api.Utility;
|
using Milimoe.FunGame.Core.Api.Utility;
|
||||||
using Milimoe.FunGame.Core.Entity;
|
|
||||||
using Milimoe.FunGame.Core.Library.Common.Addon;
|
using Milimoe.FunGame.Core.Library.Common.Addon;
|
||||||
using Milimoe.FunGame.Core.Library.Constant;
|
|
||||||
using Oshima.Core.Configs;
|
using Oshima.Core.Configs;
|
||||||
using Oshima.FunGame.OshimaModules;
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.OshimaServers.Service;
|
using Oshima.FunGame.OshimaServers.Service;
|
||||||
using Oshima.FunGame.WebAPI.Constant;
|
using Oshima.FunGame.WebAPI.Constant;
|
||||||
using TaskScheduler = Milimoe.FunGame.Core.Api.Utility.TaskScheduler;
|
using Oshima.FunGame.WebAPI.Models;
|
||||||
|
using Oshima.FunGame.WebAPI.Services;
|
||||||
|
|
||||||
namespace Oshima.FunGame.WebAPI
|
namespace Oshima.FunGame.WebAPI
|
||||||
{
|
{
|
||||||
@ -34,95 +35,19 @@ namespace Oshima.FunGame.WebAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void AfterLoad(params object[] objs)
|
public override void AfterLoad(WebAPIPluginLoader loader, params object[] objs)
|
||||||
{
|
{
|
||||||
Statics.RunningPlugin = this;
|
Statics.RunningPlugin = this;
|
||||||
Controller.NewSQLHelper();
|
Controller.NewSQLHelper();
|
||||||
Controller.NewMailSender();
|
Controller.NewMailSender();
|
||||||
|
if (objs.Length > 0 && objs[0] is WebApplicationBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Services.AddMemoryCache();
|
||||||
|
builder.Services.AddScoped<QQBotService>();
|
||||||
|
// 使用 Configure<BotConfig> 从配置源绑定
|
||||||
|
builder.Services.Configure<BotConfig>(builder.Configuration.GetSection("Bot"));
|
||||||
|
}
|
||||||
WebAPIAuthenticator.WebAPICustomBearerTokenAuthenticator += CustomBearerTokenAuthenticator;
|
WebAPIAuthenticator.WebAPICustomBearerTokenAuthenticator += CustomBearerTokenAuthenticator;
|
||||||
TaskScheduler.Shared.AddTask("重置每日运势", new TimeSpan(0, 0, 0), () =>
|
|
||||||
{
|
|
||||||
Controller.WriteLine("已重置所有人的今日运势");
|
|
||||||
Daily.ClearDaily();
|
|
||||||
});
|
|
||||||
TaskScheduler.Shared.AddTask("重置交易冷却1", new TimeSpan(9, 0, 0), () =>
|
|
||||||
{
|
|
||||||
Controller.WriteLine("重置物品交易冷却时间");
|
|
||||||
_ = FunGameService.AllowSellAndTrade();
|
|
||||||
});
|
|
||||||
TaskScheduler.Shared.AddTask("重置交易冷却2", new TimeSpan(15, 0, 0), () =>
|
|
||||||
{
|
|
||||||
Controller.WriteLine("重置物品交易冷却时间");
|
|
||||||
_ = FunGameService.AllowSellAndTrade();
|
|
||||||
});
|
|
||||||
TaskScheduler.Shared.AddRecurringTask("刷新存档缓存", TimeSpan.FromMinutes(1), () =>
|
|
||||||
{
|
|
||||||
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
|
|
||||||
if (Directory.Exists(directoryPath))
|
|
||||||
{
|
|
||||||
string[] filePaths = Directory.GetFiles(directoryPath);
|
|
||||||
foreach (string filePath in filePaths)
|
|
||||||
{
|
|
||||||
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
|
||||||
PluginConfig pc = new("saved", fileName);
|
|
||||||
pc.LoadConfig();
|
|
||||||
if (pc.Count > 0)
|
|
||||||
{
|
|
||||||
User user = FunGameService.GetUser(pc);
|
|
||||||
// 将用户存入缓存
|
|
||||||
FunGameService.UserIdAndUsername[user.Id] = user;
|
|
||||||
// 任务结算
|
|
||||||
EntityModuleConfig<Quest> quests = new("quests", user.Id.ToString());
|
|
||||||
quests.LoadConfig();
|
|
||||||
if (quests.Count > 0 && FunGameService.SettleQuest(user, quests))
|
|
||||||
{
|
|
||||||
quests.SaveConfig();
|
|
||||||
user.LastTime = DateTime.Now;
|
|
||||||
pc.Add("user", user);
|
|
||||||
pc.SaveConfig();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Controller.WriteLine("读取 FunGame 存档缓存", LogLevel.Debug);
|
|
||||||
}
|
|
||||||
}, true);
|
|
||||||
TaskScheduler.Shared.AddTask("刷新每日任务", new TimeSpan(4, 0, 0), () =>
|
|
||||||
{
|
|
||||||
string directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/quests";
|
|
||||||
if (Directory.Exists(directoryPath))
|
|
||||||
{
|
|
||||||
string[] filePaths = Directory.GetFiles(directoryPath);
|
|
||||||
foreach (string filePath in filePaths)
|
|
||||||
{
|
|
||||||
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
|
||||||
EntityModuleConfig<Quest> quests = new("quests", fileName);
|
|
||||||
quests.Clear();
|
|
||||||
FunGameService.CheckQuestList(quests);
|
|
||||||
quests.SaveConfig();
|
|
||||||
}
|
|
||||||
Controller.WriteLine("刷新每日任务");
|
|
||||||
}
|
|
||||||
// 刷新签到
|
|
||||||
directoryPath = $@"{AppDomain.CurrentDomain.BaseDirectory}configs/saved";
|
|
||||||
if (Directory.Exists(directoryPath))
|
|
||||||
{
|
|
||||||
string[] filePaths = Directory.GetFiles(directoryPath);
|
|
||||||
foreach (string filePath in filePaths)
|
|
||||||
{
|
|
||||||
string fileName = Path.GetFileNameWithoutExtension(filePath);
|
|
||||||
PluginConfig pc = new("saved", fileName);
|
|
||||||
pc.LoadConfig();
|
|
||||||
pc.Add("signed", false);
|
|
||||||
pc.SaveConfig();
|
|
||||||
}
|
|
||||||
Controller.WriteLine("刷新签到");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
TaskScheduler.Shared.AddRecurringTask("刷新boss", TimeSpan.FromHours(1), () =>
|
|
||||||
{
|
|
||||||
FunGameService.GenerateBoss();
|
|
||||||
Controller.WriteLine("刷新boss");
|
|
||||||
}, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string CustomBearerTokenAuthenticator(string token)
|
private string CustomBearerTokenAuthenticator(string token)
|
||||||
|
@ -24,6 +24,10 @@
|
|||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Rebex.Elliptic.Ed25519" Version="1.2.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\OshimaCore\OshimaCore.csproj" />
|
<ProjectReference Include="..\OshimaCore\OshimaCore.csproj" />
|
||||||
<ProjectReference Include="..\OshimaModules\OshimaModules.csproj" />
|
<ProjectReference Include="..\OshimaModules\OshimaModules.csproj" />
|
||||||
|
125
OshimaWebAPI/Services/QQBotService.cs
Normal file
125
OshimaWebAPI/Services/QQBotService.cs
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
using System.Net.Http.Headers;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using Oshima.FunGame.WebAPI.Constant;
|
||||||
|
using Oshima.FunGame.WebAPI.Models;
|
||||||
|
|
||||||
|
namespace Oshima.FunGame.WebAPI.Services
|
||||||
|
{
|
||||||
|
public class QQBotService(IOptions<BotConfig> botConfig, IHttpClientFactory httpClientFactory, IMemoryCache memoryCache)
|
||||||
|
{
|
||||||
|
private readonly BotConfig _botConfig = botConfig.Value;
|
||||||
|
private readonly HttpClient _httpClient = httpClientFactory.CreateClient();
|
||||||
|
private readonly IMemoryCache _memoryCache = memoryCache;
|
||||||
|
private const string AccessTokenCacheKey = "QQBotAccessToken";
|
||||||
|
|
||||||
|
public async Task SendC2CMessageAsync(string openid, string content, int msgType = 0, object? media = null, string? msgId = null, int? msgSeq = null)
|
||||||
|
{
|
||||||
|
await SendMessageAsync($"/v2/users/{openid}/messages", content, msgType, media, msgId, msgSeq);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendGroupMessageAsync(string groupOpenid, string content, int msgType = 0, object? media = null, string? msgId = null, int? msgSeq = null)
|
||||||
|
{
|
||||||
|
await SendMessageAsync($"/v2/groups/{groupOpenid}/messages", content, msgType, media, msgId, msgSeq);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SendMessageAsync(string url, string content, int msgType = 0, object? media = null, string? msgId = null, int? msgSeq = null)
|
||||||
|
{
|
||||||
|
string accessToken = await GetAccessTokenAsync();
|
||||||
|
HttpRequestMessage request = new(HttpMethod.Post, $"https://api.sgroup.qq.com{url}");
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("QQBot", accessToken);
|
||||||
|
Statics.RunningPlugin?.Controller.WriteLine($"使用的 Access Token:{accessToken}", Milimoe.FunGame.Core.Library.Constant.LogLevel.Debug);
|
||||||
|
Dictionary<string, object> requestBody = new()
|
||||||
|
{
|
||||||
|
{ "content", content },
|
||||||
|
{ "msg_type", msgType }
|
||||||
|
};
|
||||||
|
if (media != null)
|
||||||
|
{
|
||||||
|
requestBody.Add("media", media);
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(msgId))
|
||||||
|
{
|
||||||
|
requestBody.Add("msg_id", msgId);
|
||||||
|
}
|
||||||
|
if (msgSeq.HasValue)
|
||||||
|
{
|
||||||
|
requestBody.Add("msg_seq", msgSeq.Value);
|
||||||
|
}
|
||||||
|
request.Content = new StringContent(JsonSerializer.Serialize(requestBody), System.Text.Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(string? fileUuid, string? fileInfo, int ttl, string? error)> UploadC2CMediaAsync(string openid, int fileType, string url)
|
||||||
|
{
|
||||||
|
return await UploadMediaAsync($"/v2/users/{openid}/files", fileType, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<(string? fileUuid, string? fileInfo, int ttl, string? error)> UploadGroupMediaAsync(string groupOpenid, int fileType, string url)
|
||||||
|
{
|
||||||
|
return await UploadMediaAsync($"/v2/groups/{groupOpenid}/files", fileType, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<(string? fileUuid, string? fileInfo, int ttl, string? error)> UploadMediaAsync(string url, int fileType, string fileUrl)
|
||||||
|
{
|
||||||
|
string accessToken = await GetAccessTokenAsync();
|
||||||
|
HttpRequestMessage request = new(HttpMethod.Post, $"https://api.sgroup.qq.com{url}");
|
||||||
|
request.Headers.Authorization = new AuthenticationHeaderValue("QQBot", accessToken);
|
||||||
|
Statics.RunningPlugin?.Controller.WriteLine($"使用的 Access Token:{accessToken}", Milimoe.FunGame.Core.Library.Constant.LogLevel.Debug);
|
||||||
|
Dictionary<string, object> requestBody = new()
|
||||||
|
{
|
||||||
|
{ "file_type", fileType },
|
||||||
|
{ "url", fileUrl },
|
||||||
|
{ "srv_send_msg", false }
|
||||||
|
};
|
||||||
|
request.Content = new StringContent(JsonSerializer.Serialize(requestBody), System.Text.Encoding.UTF8, "application/json");
|
||||||
|
|
||||||
|
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
if (!response.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
string errorBody = await response.Content.ReadAsStringAsync();
|
||||||
|
return (null, null, 0, $"状态码:{response.StatusCode},错误信息:{errorBody}");
|
||||||
|
}
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
MediaResponse? mediaResponse = JsonSerializer.Deserialize<MediaResponse>(responseBody);
|
||||||
|
if (mediaResponse == null)
|
||||||
|
{
|
||||||
|
return (null, null, 0, "反序列化富媒体消息失败。");
|
||||||
|
}
|
||||||
|
Statics.RunningPlugin?.Controller.WriteLine($"接收到的富媒体消息:{mediaResponse.FileInfo}", Milimoe.FunGame.Core.Library.Constant.LogLevel.Debug);
|
||||||
|
return (mediaResponse.FileUuid, mediaResponse.FileInfo, mediaResponse.Ttl, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetAccessTokenAsync()
|
||||||
|
{
|
||||||
|
if (_memoryCache.TryGetValue(AccessTokenCacheKey, out string? accessToken) && !string.IsNullOrEmpty(accessToken))
|
||||||
|
{
|
||||||
|
return accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
return await RefreshTokenAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<string> RefreshTokenAsync()
|
||||||
|
{
|
||||||
|
HttpRequestMessage request = new(HttpMethod.Post, "https://bots.qq.com/app/getAppAccessToken")
|
||||||
|
{
|
||||||
|
Content = new StringContent(JsonSerializer.Serialize(new { appId = _botConfig.AppId, clientSecret = _botConfig.Secret }), System.Text.Encoding.UTF8, "application/json")
|
||||||
|
};
|
||||||
|
HttpResponseMessage response = await _httpClient.SendAsync(request);
|
||||||
|
response.EnsureSuccessStatusCode();
|
||||||
|
string responseBody = await response.Content.ReadAsStringAsync();
|
||||||
|
AccessTokenResponse? tokenResponse = JsonSerializer.Deserialize<AccessTokenResponse>(responseBody);
|
||||||
|
if (tokenResponse == null || string.IsNullOrEmpty(tokenResponse.AccessToken) || !int.TryParse(tokenResponse.ExpiresIn, out int expiresIn))
|
||||||
|
{
|
||||||
|
throw new Exception("获取 Access Token 失败!");
|
||||||
|
}
|
||||||
|
_memoryCache.Set(AccessTokenCacheKey, tokenResponse.AccessToken, TimeSpan.FromSeconds(expiresIn - 60));
|
||||||
|
Statics.RunningPlugin?.Controller.WriteLine($"获取到 Access Token:{tokenResponse.AccessToken}", Milimoe.FunGame.Core.Library.Constant.LogLevel.Debug);
|
||||||
|
return tokenResponse.AccessToken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,9 +3,9 @@ using Oshima.Core.Configs;
|
|||||||
using Oshima.Core.Constant;
|
using Oshima.Core.Constant;
|
||||||
using Oshima.FunGame.WebAPI.Models;
|
using Oshima.FunGame.WebAPI.Models;
|
||||||
|
|
||||||
namespace Oshima.FunGame.WebAPI.Utils
|
namespace Oshima.FunGame.WebAPI.Services
|
||||||
{
|
{
|
||||||
public class UserDailyUtil
|
public class UserDailyService
|
||||||
{
|
{
|
||||||
public static UserDaily GetUserDaily(long user_id)
|
public static UserDaily GetUserDaily(long user_id)
|
||||||
{
|
{
|
Loading…
x
Reference in New Issue
Block a user