Merge pull request 'qqbot' (#1) from qqbot into master

Reviewed-on: #1
This commit is contained in:
milimoe 2025-08-02 10:45:22 +00:00
commit 1f7ae78257
15 changed files with 1884 additions and 229 deletions

View File

@ -3,7 +3,11 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34330.188
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RainBOT-CSharp", "src\RainBOT.csproj", "{46A60688-46D6-4414-A079-7DC0C95B5A37}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RainBOT", "src\RainBOT.csproj", "{46A60688-46D6-4414-A079-7DC0C95B5A37}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OneBot-HTTPClient", "..\OneBot-HTTPClient\src\OneBot-HTTPClient.csproj", "{D830E21D-78F7-4480-B86B-0AEA5A291A9D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FunGame.Core", "..\FunGame.Core\FunGame.Core.csproj", "{3054F4C0-60AA-4353-B453-12C88E067AE5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -15,6 +19,14 @@ Global
{46A60688-46D6-4414-A079-7DC0C95B5A37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{46A60688-46D6-4414-A079-7DC0C95B5A37}.Release|Any CPU.ActiveCfg = Release|Any CPU
{46A60688-46D6-4414-A079-7DC0C95B5A37}.Release|Any CPU.Build.0 = Release|Any CPU
{D830E21D-78F7-4480-B86B-0AEA5A291A9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D830E21D-78F7-4480-B86B-0AEA5A291A9D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D830E21D-78F7-4480-B86B-0AEA5A291A9D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D830E21D-78F7-4480-B86B-0AEA5A291A9D}.Release|Any CPU.Build.0 = Release|Any CPU
{3054F4C0-60AA-4353-B453-12C88E067AE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3054F4C0-60AA-4353-B453-12C88E067AE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3054F4C0-60AA-4353-B453-12C88E067AE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3054F4C0-60AA-4353-B453-12C88E067AE5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -242,11 +242,70 @@ namespace Milimoe.RainBOT.Command
Daily.InitDaily();
SayNo.InitSayNo();
Ignore.InitIgnore();
FunGame.FunGameSimulation = false;
RainBOTFunGame.FunGameSimulation = false;
SendMessage(send_group, target_id, "参数设定以及权限组重新加载完成。");
}
else Access_Denied(send_group, target_id);
}
else if (command.Contains(".osm checkws"))
{
if (user_id == GeneralSettings.Master)
{
SendMessage(send_group, target_id, OshimaController.Instance.HTTPClient?.Connected ?? false ? $"已连接上服务器。" : "连接已断开。");
}
else Access_Denied(send_group, target_id);
}
else if (command.Contains(".osm retryserver"))
{
if (user_id == GeneralSettings.Master)
{
TaskUtility.NewTask(async () =>
{
string m = "已经重新启动 FunGame WebSocket 服务。";
string msg = m;
OshimaController.Config.FunGame_isRetrying = false;
OshimaController.Config.FunGame_isAutoRetry = true;
OshimaController.CurrentRetryTimes = -1;
try
{
await OshimaController.Instance.DisconnectFromAnonymousServer();
}
catch (Exception e)
{
if (msg != m)
{
msg += "\r\n断开匿名服务器遇到问题";
}
msg += e.Message;
}
try
{
await OshimaController.Instance.DisconnectAsync();
}
catch (Exception e)
{
if (msg != m)
{
msg += "\r\n断开 FunGame 服务器遇到问题:";
}
msg += e.Message;
}
try
{
await OshimaController.Instance.Retry(true);
}
catch { }
try
{
await OshimaController.Instance.ConnectToAnonymousServer();
}
catch { }
msg += OshimaController.Instance.HTTPClient?.Connected ?? false ? $"已连接上服务器。" : "重试连接失败。";
SendMessage(send_group, target_id, msg);
});
}
else Access_Denied(send_group, target_id);
}
else if (command.Contains(".osm set"))
{
if (user_id == GeneralSettings.Master)
@ -477,6 +536,30 @@ namespace Milimoe.RainBOT.Command
}
}
break;
case "ai":
if (args.Length > 0)
{
if (args[0] != "on" && args[0] != "off")
{
break;
}
status = args[0] == "on";
msg = UpdateValue("AI", GeneralSettings.IsAI ? "开启" : "关闭", status ? "开启" : "关闭");
GeneralSettings.IsAI = status;
return msg;
}
break;
case "pai":
if (args.Length > 0 && int.TryParse(args[0], out int pai))
{
if (pai >= 0 && pai <= 100)
{
msg = UpdateValue("AI的概率", GeneralSettings.PAI + "%", pai + "%");
GeneralSettings.PAI = pai;
return msg;
}
}
break;
case "mute":
if (args.Length > 0)
{

View File

@ -42,6 +42,19 @@ namespace Milimoe.RainBOT.ListeningTask
}
}
if (e.detail.StartsWith("绑定"))
{
string detail = e.detail.Replace("绑定", "");
string msg = QQOpenID.Bind(detail, e.user_id);
await Bot.SendFriendMessage(e.user_id, "绑定", msg);
}
else if (e.detail.StartsWith("解绑"))
{
string detail = e.detail.Replace("解绑", "");
string msg = QQOpenID.Unbind(detail, e.user_id);
await Bot.SendFriendMessage(e.user_id, "解绑", msg);
}
// OSM指令
if (e.detail.Length >= 4 && e.detail[..4] == ".osm")
{
@ -52,16 +65,16 @@ namespace Milimoe.RainBOT.ListeningTask
if (e.detail.Length >= 9 && e.detail[..9].Equals("FunGame模拟", StringComparison.CurrentCultureIgnoreCase))
{
if (!await Bot.CheckBlackList(true, e.user_id, e.user_id)) return quick_reply;
if (!FunGame.FunGameSimulation)
if (!RainBOTFunGame.FunGameSimulation)
{
FunGame.FunGameSimulation = true;
List<string> msgs = await Bot.HttpGet<List<string>>("https://api.milimoe.com/fungame/test?isweb=false") ?? [];
RainBOTFunGame.FunGameSimulation = true;
List<string> msgs = await Bot.HttpGet<List<string>>($"https://{GeneralSettings.FunGameServer}/fungame/test?isweb=false") ?? [];
foreach (string msg in msgs)
{
await Bot.SendFriendMessage(e.user_id, "FunGame模拟", msg.Trim());
await Task.Delay(5500);
}
FunGame.FunGameSimulation = false;
RainBOTFunGame.FunGameSimulation = false;
}
else
{

View File

@ -1,6 +1,4 @@
using System.Text.RegularExpressions;
using Microsoft.VisualBasic;
using Milimoe.OneBot.Framework;
using Milimoe.OneBot.Framework;
using Milimoe.OneBot.Model.Content;
using Milimoe.OneBot.Model.Event;
using Milimoe.OneBot.Model.Message;
@ -73,10 +71,10 @@ namespace Milimoe.RainBOT.ListeningTask
if ((e.user_id == GeneralSettings.Master || GeneralSettings.RecallAccessGroup.Contains(e.user_id)) && e.detail.Contains("撤回;") && e.message.Any(m => m.type == "reply"))
{
ReplyMessage reply = (ReplyMessage)e.message.Where(m => m.type == "reply").First();
if (int.TryParse(reply.data.id, out int id))
if (long.TryParse(reply.data.id, out long id))
{
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.real_id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.message_id), true);
return quick_reply;
}
}
@ -90,29 +88,50 @@ namespace Milimoe.RainBOT.ListeningTask
if (e.detail.Contains("取消精华;"))
{
await Bot.SendMessage(SupportedAPI.delete_essence_msg, e.group_id, "取消精华", new DeleteEssenceMsgContent(id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.real_id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.message_id), true);
return quick_reply;
}
else
{
await Bot.SendMessage(SupportedAPI.set_essence_msg, e.group_id, "设置精华", new EssenceMsgContent(id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.real_id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.message_id), true);
return quick_reply;
}
}
}
if (Ignore.CustomIgnore.Any(e.detail.Contains) && Bot.BotIsAdmin(e.group_id))
if (e.user_id != GeneralSettings.Master && Ignore.CustomIgnore.Any(e.detail.Contains) && Bot.BotIsAdmin(e.group_id))
{
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.real_id), true);
await Bot.SendMessage(SupportedAPI.delete_msg, e.group_id, "撤回", new DeleteMsgContent(e.message_id), true);
await Bot.SendMessage(SupportedAPI.set_group_ban, e.group_id, "禁言", new SetGroupBanContent(e.group_id, e.user_id, 120), true);
return quick_reply;
}
if (e.detail.Contains("圣人榜"))
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
_ = OshimaController.Instance.SCList(e.group_id, e.user_id);
return quick_reply;
}
if (e.detail.Contains("出生榜"))
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
_ = OshimaController.Instance.SCList(e.group_id, e.user_id, true);
return quick_reply;
}
if (e.detail.Contains("圣人点数") || e.detail == "查询sc" || e.detail == "sc查询")
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
_ = OshimaController.Instance.SCRecord(e.group_id, e.user_id);
return quick_reply;
}
if (e.detail == "查询服务器启动时间")
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
string msg = (await Bot.HttpGet<string>("https://api.milimoe.com/test/getlastlogintime") ?? "").Trim();
string msg = (await Bot.HttpGet<string>($"https://{GeneralSettings.FunGameServer}/test/getlastlogintime") ?? "").Trim();
if (msg != "")
{
await Bot.SendGroupMessage(e.group_id, "查询服务器启动时间", msg);
@ -124,7 +143,7 @@ namespace Milimoe.RainBOT.ListeningTask
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
string detail = e.detail.Replace("查询任务计划", "").Trim();
string msg = await Bot.HttpGet<string>($"https://api.milimoe.com/test/gettask?name={detail}") ?? "";
string msg = await Bot.HttpGet<string>($"https://{GeneralSettings.FunGameServer}/test/gettask?name={detail}") ?? "";
if (msg != "")
{
await Bot.SendGroupMessage(e.group_id, "查询任务计划", msg);
@ -132,18 +151,27 @@ namespace Milimoe.RainBOT.ListeningTask
return quick_reply;
}
if (e.user_id == GeneralSettings.Master && e.detail == "查询余额")
{
string msg = await AI.GetBalance();
quick_reply = new(msg);
return quick_reply;
}
if (GeneralSettings.IsAI && GeneralSettings.FunGameGroup.Contains(e.group_id) && (e.detail.StartsWith("小雪") || e.CheckThrow(GeneralSettings.PAI, out _)))
{
AIChat(e);
}
if (!GeneralSettings.IsRun)
{
return quick_reply;
}
if (await FunGame.Handler(e))
_ = Task.Run(async () =>
{
return quick_reply;
}
if (GeneralSettings.FunGameGroup.Contains(e.group_id))
{
}
await RainBOTFunGame.Handler2(e);
});
// 发图API
if (e.detail == "来图")
@ -250,7 +278,7 @@ namespace Milimoe.RainBOT.ListeningTask
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
UserDaily daily = await Bot.HttpPost<UserDaily>("https://api.milimoe.com/userdaily/get/" + e.user_id, "") ?? new(0, 0, "");
UserDaily daily = await Bot.HttpPost<UserDaily>($"https://{GeneralSettings.FunGameServer}/userdaily/get/" + e.user_id, "") ?? new(0, 0, "");
if (daily.daily != "")
{
if (daily.type == 0)
@ -291,7 +319,7 @@ namespace Milimoe.RainBOT.ListeningTask
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id)) return quick_reply;
string msg = await Bot.HttpPost<string>("https://api.milimoe.com/userdaily/remove/" + e.user_id, "") ?? "";
string msg = await Bot.HttpPost<string>($"https://{GeneralSettings.FunGameServer}/userdaily/remove/" + e.user_id, "") ?? "";
if (msg != "")
{
GroupMessageContent content = new(e.group_id);
@ -312,9 +340,9 @@ namespace Milimoe.RainBOT.ListeningTask
{
if (qq == GeneralSettings.BotQQ)
{
await Bot.HttpPost<UserDaily>("https://api.milimoe.com/userdaily/get/" + qq, "");
await Bot.HttpPost<UserDaily>($"https://{GeneralSettings.FunGameServer}/userdaily/get/" + qq, "");
}
UserDaily daily = await Bot.HttpGet<UserDaily>("https://api.milimoe.com/userdaily/view/" + qq) ?? new(0, 0, "");
UserDaily daily = await Bot.HttpGet<UserDaily>($"https://{GeneralSettings.FunGameServer}/userdaily/view/" + qq) ?? new(0, 0, "");
if (daily.daily != "")
{
GroupMessageContent content = new(e.group_id);
@ -334,7 +362,7 @@ namespace Milimoe.RainBOT.ListeningTask
{
if (long.TryParse(str_qq.Trim().Replace("@", ""), out long qq))
{
string msg = await Bot.HttpPost<string>("https://api.milimoe.com/userdaily/remove/" + e.user_id, "") ?? "";
string msg = await Bot.HttpPost<string>($"https://{GeneralSettings.FunGameServer}/userdaily/remove/" + e.user_id, "") ?? "";
if (msg != "")
{
await Bot.SendGroupMessage(e.group_id, "重置运势", "已重置" + Bot.GetMemberNickName(e.group_id, qq) + "" + qq + ")的今日运势。");
@ -352,6 +380,8 @@ namespace Milimoe.RainBOT.ListeningTask
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id) || !Bot.BotIsAdmin(e.group_id)) return quick_reply;
if (e.user_id != GeneralSettings.Master)
{
_ = Task.Run(async () =>
{
await Bot.SendGroupMessage(e.group_id, "禁言抽奖", "2秒后开奖\r\n如需要忏悔请在开奖后3秒内发送忏悔开奖前发送无效。");
await Task.Delay(2000);
@ -361,6 +391,7 @@ namespace Milimoe.RainBOT.ListeningTask
await Task.Delay(3200);
await Bot.SendMessage(SupportedAPI.set_group_ban, e.group_id, "禁言抽奖", new SetGroupBanContent(e.group_id, e.user_id, mute_time), true);
MuteRecall.WillMute.Remove(e.user_id);
});
}
else
{
@ -372,10 +403,13 @@ namespace Milimoe.RainBOT.ListeningTask
else if (GeneralSettings.IsMute && e.detail == "忏悔" && MuteRecall.WillMute.ContainsKey(e.user_id))
{
if (!await Bot.CheckBlackList(true, e.user_id, e.group_id) || !Bot.BotIsAdmin(e.group_id)) return quick_reply;
_ = Task.Run(async () =>
{
await Task.Delay(3800);
MuteRecall.WillMute.Remove(e.user_id);
await Bot.SendMessage(SupportedAPI.set_group_ban, e.group_id, "忏悔", new SetGroupBanContent(e.group_id, e.user_id, 0), true);
await Bot.SendGroupMessage(e.group_id, "忏悔", "忏悔成功!!希望你保持纯真,保持野性的美。");
});
return quick_reply;
}
@ -454,6 +488,7 @@ namespace Milimoe.RainBOT.ListeningTask
if (content.message.Count > 0)
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", content);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
}
else if (SayNo.TriggerBeforeNo.Any(e.detail.Contains) && GeneralSettings.IsSayNo && e.CheckThrow(GeneralSettings.PSayNo, out dice))
@ -507,6 +542,7 @@ namespace Milimoe.RainBOT.ListeningTask
if (content.message.Count > 0)
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", content);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
}
else if (e.detail.Contains("可以") && !e.detail.Contains('不') && e.CheckThrow(GeneralSettings.PSayNo, out dice))
@ -515,10 +551,12 @@ namespace Milimoe.RainBOT.ListeningTask
if (dice < (GeneralSettings.PSayNo / 2))
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", "可以");
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
else
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", "不可以");
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
}
else if (e.detail.Contains('能') && !e.detail.Contains('不') && !SayNo.IgnoreTriggerBeforeCan.Any(e.detail.Contains) && e.CheckThrow(GeneralSettings.PSayNo, out dice))
@ -527,10 +565,12 @@ namespace Milimoe.RainBOT.ListeningTask
if (dice < (GeneralSettings.PSayNo / 2))
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", "能");
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
else
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", "不能");
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
}
else if (e.detail.Contains("可能") && !e.detail.Contains('不') && e.CheckThrow(GeneralSettings.PSayNo, out dice))
@ -539,21 +579,25 @@ namespace Milimoe.RainBOT.ListeningTask
if (dice < (GeneralSettings.PSayNo / 2))
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", "可能");
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
else
{
await Bot.SendGroupMessage(e.group_id, "随机反驳不", "不可能");
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
}
else if (e.detail.Contains('要') && !e.detail.Contains('不') && e.CheckThrow(GeneralSettings.PSayNo, out dice))
{
Bot.ColorfulCheckPass(sender, "随机反驳不", dice, GeneralSettings.PSayNo);
await Bot.SendGroupMessage(e.group_id, "随机反驳不", SayNo.SayWantWords[new Random().Next(SayNo.SayWantWords.Count)]);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
else if (e.detail.Contains('想') && !e.detail.Contains('不') && e.CheckThrow(GeneralSettings.PSayNo, out dice))
{
Bot.ColorfulCheckPass(sender, "随机反驳不", dice, GeneralSettings.PSayNo);
await Bot.SendGroupMessage(e.group_id, "随机反驳不", SayNo.SayThinkWords[new Random().Next(SayNo.SayThinkWords.Count)]);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
}
// 反向艾特
@ -571,6 +615,8 @@ namespace Milimoe.RainBOT.ListeningTask
await Bot.SendGroupMessage(e.group_id, "反向艾特", content);
}
}
AIChat(e, true);
return quick_reply;
}
@ -587,18 +633,20 @@ namespace Milimoe.RainBOT.ListeningTask
};
content.message.Add(new ImageMessage(img));
await Bot.SendGroupMessage(e.group_id, "Image", content);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
return quick_reply;
}
// 随机复读
if (GeneralSettings.IsRepeat && !Ignore.RepeatIgnore.Any(e.detail.Contains) && !Ignore.RepeatQQIgnore.Contains(e.user_id) && e.CheckThrow(GeneralSettings.PRepeat, out dice))
if (GeneralSettings.IsRepeat && !Ignore.RepeatIgnore.Any(e.detail.Contains) && !Ignore.RepeatQQIgnore.Contains(e.user_id) && e.CheckThrow(GeneralSettings.PRepeat, out dice) && !GroupRecallTask.Recalls.ContainsKey(e.detail))
{
// 出现了@at就直接触发复读没有延迟
int delay = e.message.Where(m => m.type == "at").Any() ? 0 : GeneralSettings.RepeatDelay[0] + new Random().Next(GeneralSettings.RepeatDelay[1] - GeneralSettings.RepeatDelay[0]);
Bot.ColorfulCheckPass(sender, "随机复读", dice, GeneralSettings.PRepeat, delay);
GroupMessageContent content = new(e.group_id);
content.message.AddRange(e.message);
await Bot.SendGroupMessage(e.group_id, "随机复读", content, delay * 1000);
_ = Bot.SendGroupMessage(e.group_id, "随机复读", content, delay * 1000);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail);
return quick_reply;
}
@ -613,7 +661,8 @@ namespace Milimoe.RainBOT.ListeningTask
{
GroupMessageContent content = new(e.group_id);
content.message.Add(new AtMessage(e.user_id));
switch (Random.Shared.Next(4))
int sc = 0;
switch (Random.Shared.Next(6))
{
case 0:
content.message.Add(new TextMessage(string.Concat(name.AsSpan(pos, name.Length > 1 ? 2 : name.Length), "哥")));
@ -623,13 +672,24 @@ namespace Milimoe.RainBOT.ListeningTask
break;
case 2:
content.message.Add(new TextMessage(string.Concat(name.AsSpan(pos, name.Length > 0 ? 1 : name.Length), "圣")));
sc = Random.Shared.Next(1, 4);
break;
case 3:
content.message.Add(new TextMessage(string.Concat(name.AsSpan(pos, name.Length > 0 ? 1 : name.Length), "亲")));
break;
case 4:
content.message.Add(new TextMessage(string.Concat(name.AsSpan(pos, name.Length > 1 ? 2 : name.Length), "亲")));
break;
case 5:
content.message.Add(new TextMessage(string.Concat("哈基", name.AsSpan(pos, name.Length > 0 ? 1 : name.Length))));
break;
default:
content.message.Add(new TextMessage(string.Concat(name.AsSpan(pos, name.Length > 0 ? 1 : name.Length), "出")));
sc = -Random.Shared.Next(1, 4);
break;
}
await Bot.SendGroupMessage(e.group_id, "随机叫哥", content, delay * 1000);
_ = Bot.SendGroupMessage(e.group_id, "随机叫哥", content, delay * 1000);
_ = OshimaController.Instance.SCAdd(e.user_id, e.group_id, e.detail, sc);
return quick_reply;
}
}
@ -643,5 +703,18 @@ namespace Milimoe.RainBOT.ListeningTask
return quick_reply;
}
public static void AIChat(GroupMessageEvent e, bool isAt = false)
{
AI.Add(e.user_id == GeneralSettings.Master ? (Random.Shared.Next(0, 10) < 5 ? "小音" : "米莉") : e.sender.title, string.Join("", e.message.Where(m => m.type == "text").Select(s => s.data.ToString())));
if (!AI.CD && (isAt || e.detail.StartsWith("小雪") || AI.List.Count > 4))
{
_ = Task.Run(async () =>
{
string reply = await AI.Chat();
await Bot.SendGroupMessage(e.group_id, "AI", reply);
});
}
}
}
}

View File

@ -0,0 +1,33 @@
using Milimoe.OneBot.Model.Event;
using Milimoe.RainBOT.Settings;
namespace Milimoe.RainBOT.ListeningTask
{
public class GroupRecallTask
{
public static Dictionary<string, DateTime> Recalls { get; } = [];
public static async Task ListeningTask_handler(GroupRecallEvent e)
{
try
{
Console.WriteLine($"{DateTime.Now:yyyy/MM/dd HH:mm:ss} N/Group_Recall G/{e.group_id}{(e.detail.Trim() == "" ? "" : " -> " + e.detail)}");
if (GeneralSettings.IsDebug)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine($"DEBUG{e.original_msg}");
Console.ForegroundColor = ConsoleColor.Gray;
}
Recalls[e.detail] = DateTime.Now;
await Task.CompletedTask;
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(ex);
Console.ForegroundColor = ConsoleColor.Gray;
}
}
}
}

View File

@ -5,6 +5,7 @@ using Milimoe.OneBot.Model.Other;
using Milimoe.RainBOT.Command;
using Milimoe.RainBOT.ListeningTask;
using Milimoe.RainBOT.Settings;
using TaskScheduler = Milimoe.FunGame.Core.Api.Utility.TaskScheduler;
try
{
@ -108,29 +109,34 @@ try
Daily.InitDaily();
SayNo.InitSayNo();
Ignore.InitIgnore();
QQOpenID.LoadConfig();
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("初始化完毕!");
Console.ForegroundColor = ConsoleColor.Gray;
if (args.Contains("--test"))
{
GeneralSettings.IsDebug = true;
Console.ForegroundColor = ConsoleColor.Cyan;
Console.WriteLine("Test模式");
Console.ForegroundColor = ConsoleColor.Gray;
await AI.Chat();
return;
}
Console.WriteLine("开始监听 -> " + listener.address);
// 绑定监听事件
listener.GroupMessageListening += GroupMessageTask.ListeningTask_handler;
listener.GroupBanNoticeListening += GroupBanTask.ListeningTask_handler;
listener.FriendMessageListening += FriendMessageTask.ListeningTask_handler;
listener.GroupRecallNoticeListening += GroupRecallTask.ListeningTask_handler;
_ = Task.Factory.StartNew(async () =>
{
while (true)
TaskScheduler.Shared.AddTask("发送每日新闻", new TimeSpan(8, 30, 0), async () =>
{
try
{
DateTime now = DateTime.Now;
if (now.Hour == 8 && now.Minute == 30 && !Daily.DailyNews)
{
Daily.DailyNews = true;
// 发送每日新闻
foreach (Group g in Bot.Groups)
{
GroupMessageContent content = new(g.group_id);
@ -141,27 +147,23 @@ try
Console.ForegroundColor = ConsoleColor.Gray;
}
}
if (now.Hour == 8 && now.Minute == 31)
catch (Exception e)
{
Daily.DailyNews = false;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e);
Console.ForegroundColor = ConsoleColor.Gray;
}
if (now.Hour == 0 && now.Minute == 0 && Daily.ClearDailys)
});
TaskScheduler.Shared.AddTask("清空每日运势", new TimeSpan(0, 0, 0), () =>
{
try
{
Daily.ClearDailys = false;
// 清空运势
Daily.UserDailys.Clear();
Daily.SaveDaily();
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("已重置所有人的今日运势。");
Console.ForegroundColor = ConsoleColor.Gray;
// 发放12点大挑战的奖励
//await Bot.Send12ClockPresents();
}
if (now.Hour == 0 && now.Minute == 1)
{
Daily.ClearDailys = true;
}
await Task.Delay(1000);
}
catch (Exception e)
{
@ -169,16 +171,11 @@ try
Console.WriteLine(e);
Console.ForegroundColor = ConsoleColor.Gray;
}
}
});
_ = Task.Factory.StartNew(async () =>
{
while (true)
TaskScheduler.Shared.AddRecurringTask("清空下载图片", TimeSpan.FromMinutes(1), () =>
{
try
{
await Task.Delay(1000 * 60);
foreach (long uid in BlackList.Times.Where(d => d.Value < 5).Select(d => d.Key))
{
BlackList.Times.Remove(uid);
@ -196,6 +193,25 @@ try
catch { }
}
}
if (GeneralSettings.IsDebug)
{
Console.ForegroundColor = ConsoleColor.Magenta;
Console.WriteLine("清空所有已下载的图片,释放空间。");
Console.ForegroundColor = ConsoleColor.Gray;
}
// 清除超时的撤回记录
DateTime now = DateTime.Now.AddMinutes(-5);
List<string> recalls = [.. GroupRecallTask.Recalls.Keys];
foreach (string recall in recalls)
{
DateTime recallTime = GroupRecallTask.Recalls[recall];
if (now > recallTime)
{
GroupRecallTask.Recalls.Remove(recall);
}
}
// 重置AI状态
AI.CD = false;
}
catch (Exception e)
{
@ -203,21 +219,29 @@ try
Console.WriteLine(e);
Console.ForegroundColor = ConsoleColor.Gray;
}
}
});
// 连接 Oshima Core 服务器
OshimaController.Config.FunGame_isAutoRetry = true;
Task r = Task.Run(async () =>
{
await OshimaController.Instance.Start();
await OshimaController.Instance.ConnectToAnonymousServer();
OshimaController.Config.FunGame_isAutoRetry = true;
});
bool isListening = true;
CancellationTokenSource cts = new();
CancellationToken ct = cts.Token;
Task t = Task.Factory.StartNew(() =>
Task t = Task.Factory.StartNew(async () =>
{
// 循环接收消息,此线程会在没有请求时阻塞
while (isListening)
{
try
{
listener.GetContext();
await listener.GetContext();
}
catch (Exception e)
{

433
src/Model/TEST.cs Normal file
View File

@ -0,0 +1,433 @@
//using Newtonsoft.Json.Linq;
//using QQBot4Sharp.Models;
//using Serilog;
//using System.Text;
//using System.Text.RegularExpressions;
//namespace QQBot4Sharp.Test
//{
// internal class Program
// {
// private static JObject _jConfig = [];
// static async Task Main(string[] args)
// {
// // 配置日志器
// Log.Logger = new LoggerConfiguration()
// .MinimumLevel.Debug()
// .WriteTo.Console()
// .CreateLogger();
// // 读取配置文件
// _jConfig = JObject.Parse(File.ReadAllText("config.json"));
// var info = new BotCreateInfo()
// {
// AppID = (string?)_jConfig["AppID"],
// ClientSecret = (string?)_jConfig["ClientSecret"],
// Intents = Intents.ALL,
// };
// // 创建机器人服务
// using var bot = new BotService(info);
// // 注册事件
// bot.OnReadyAsync += OnReadyAsync;
// bot.OnAtMessageCreateAsync += OnAtMessageCreateAsync;
// bot.OnDirectMessageCreateAsync += OnDirectMessageCreateAsync;
// bot.OnMessageCreateAsync += OnMessageCreateAsync;
// bot.OnC2CMessageCreateAsync += OnC2CMessageCreateAsync;
// bot.OnGroupAtMessageCreateAsync += OnGroupAtMessageCreateAsync;
// bot.OnMessageReactionAddAsync += OnMessageReactionAddAsync;
// bot.OnMessageReactionRemoveAsync += OnMessageReactionRemoveAsync;
// bot.OnInteractionCreateAsync += OnInteractionCreateAsync;
// bot.OnGuildUpdateAsync += OnGuildUpdateAsync;
// bot.OnChannelCreateAsync += OnChannelCreateAsync;
// // 启动和停止
// await bot.StartAsync();
// Console.ReadLine();
// await bot.StopAsync();
// }
// #region 通用事件
// /// <summary>
// /// READY 事件
// /// </summary>
// private static async Task OnReadyAsync(object sender, ContextEventArgs e)
// {
// Log.Information("Ready");
// var user = await e.Service.GetCurrentUserAsync();
// Log.Information($"当前用户:[{user.ID}]{user.Username}");
// await Task.CompletedTask;
// }
// #endregion
// #region 频道测试
// private static readonly Regex _atTestRegex = new("<@![0-9]+> 测试");
// private static readonly Regex _atPrivateTestRegex = new("<@![0-9]+> 私信测试");
// private static readonly Regex _atDeleteTestRegex = new("<@![0-9]+> 撤回测试");
// private static readonly Regex _atEmojiTestRegex = new("<@![0-9]+> 表情测试");
// private static readonly Regex _atMarkDownTestRegex = new("<@![0-9]+> MarkDown测试");
// private static readonly Regex _atGuildsRegex = new("<@![0-9]+> 频道列表测试");
// private static readonly Regex _atGuildRegex = new("<@![0-9]+> 频道测试");
// private static readonly Regex _atChannelRegex = new("<@![0-9]+> 子频道测试");
// private static readonly Regex _atChannelDetailRegex = new("<@![0-9]+> 子频道详情测试 [0-9]+");
// private static readonly Regex _atCreateChannelRegex = new("<@![0-9]+> 创建子频道测试 (?<Name>[0-9A-Za-z一-龥]+)");
// private static readonly Regex _atModifyChannelRegex = new("<@![0-9]+> 修改子频道测试 (?<ID>[0-9]+) (?<Name>[0-9A-Za-z一-龥]+)");
// private static readonly Regex _atDeleteChannelRegex = new("<@![0-9]+> 删除子频道测试 (?<ID>[0-9]+)");
// private static readonly Regex _atChannelOnlineMemberCountRegex = new("<@![0-9]+> 获取子频道在线成员数测试 (?<ID>[0-9]+)");
// /// <summary>
// /// 文字子频道At消息事件
// /// </summary>
// private static async Task OnAtMessageCreateAsync(object sender, AtMessageEventArgs e)
// {
// // 收到 “@Bot 测试” 消息后,回复 “At测试”
// if (_atTestRegex.IsMatch(e.Message.Content))
// {
// await e.ReplyAsync(new()
// {
// Content = "At测试",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 私信测试” 消息后,私信回复 “文字频道的私信测试”
// if (_atPrivateTestRegex.IsMatch(e.Message.Content))
// {
// var dms = await e.CreateDirectMessageSessionAsync(new()
// {
// RecipientID = e.Message.Author.ID,
// SourceGuildID = e.Message.GuildID,
// });
// await e.SendDirectMessageAsync(new()
// {
// Content = "文字频道的私信测试",
// MessageID = e.Message.ID,
// }, dms.GuildID);
// }
// // 收到 “@Bot 撤回测试” 消息后,先发送一个消息,过几秒后撤回
// if (_atDeleteTestRegex.IsMatch(e.Message.Content))
// {
// var delay = 5 * 1000;
// var msg = await e.ReplyAsync(new()
// {
// Content = $"该消息将在{delay / 1000}秒后撤回",
// MessageID = e.Message.ID,
// });
// await Task.Delay(delay);
// await e.DeleteChannelMessageAsync(msg);
// }
// // 收到 “@Bot 表情测试” 消息后,先发送一个消息,进行表情测试
// if (_atEmojiTestRegex.IsMatch(e.Message.Content))
// {
// var delay = 3 * 1000;
// var msg = await e.ReplyAsync(new()
// {
// Content = "表情测试",
// MessageID = e.Message.ID,
// });
// await Task.Delay(delay);
// var emoji = new Emoji()
// {
// ID = "128076",
// Type = EmojiType.Emoji,
// };
// await e.SetEmojiReactionAsync(msg, emoji);
// await Task.Delay(delay);
// var users = await e.GetEmojiReactionAsync(msg, emoji);
// var sb = new StringBuilder();
// sb.Append("表情表态列表:");
// foreach (var user in users)
// {
// sb.Append(user.Username);
// sb.Append(' ');
// }
// await e.ReplyAsync(new()
// {
// Content = sb.ToString(),
// MessageID = e.Message.ID,
// });
// await Task.Delay(delay);
// await e.DeleteEmojiReactionAsync(msg, emoji);
// }
// // 收到 “@Bot MarkDown测试” 消息后进行MarkDown测试
// if (_atMarkDownTestRegex.IsMatch(e.Message.Content))
// {
// var builder = new MarkDownBuilder();
// builder.At(e.Message.Author.ID);
// builder.Text(" MarkDown测试\n");
// builder.Command("/MarkDown测试");
// await e.ReplyAsync(new()
// {
// Markdown = builder.Build(),
// });
// }
// // 收到 “@Bot 频道列表测试” 消息后,回复频道列表
// // 腾讯你逆大天
// // 我长这么大第一次见GET请求中带Content的
// // 不愧是你
// if (_atGuildsRegex.IsMatch(e.Message.Content))
// {
// // 还有一件事
// // 这API为什么会死循环的啊已经设置了after返回的还是一样的内容
// var guilds = await e.GetGuildsAsync();
// var sb = new StringBuilder();
// sb.Append("频道列表:");
// foreach (var guild in guilds)
// {
// sb.Append(guild.Name);
// sb.Append(' ');
// }
// await e.ReplyAsync(new()
// {
// Content = sb.ToString(),
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 频道测试” 消息后,回复频道信息
// if (_atGuildRegex.IsMatch(e.Message.Content))
// {
// var guild = await e.GetGuildAsync(e.Message.GuildID);
// await e.ReplyAsync(new()
// {
// Content = $"频道ID{guild.ID}\n频道名称{guild.Name}\n频道简介{guild.Description}",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 子频道测试” 消息后,回复子频道信息
// if (_atChannelRegex.IsMatch(e.Message.Content))
// {
// var channels = await e.GetChannelsAsync(e.Message.GuildID);
// var sb = new StringBuilder();
// sb.Append("子频道列表:");
// foreach (var channel in channels)
// {
// sb.Append('[');
// sb.Append(channel.ID);
// sb.Append(']');
// sb.Append(channel.Name);
// sb.Append(' ');
// }
// await e.ReplyAsync(new()
// {
// Content = sb.ToString(),
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 子频道详情测试 ChannelID” 消息后,回复子频道详细信息
// if (_atChannelDetailRegex.IsMatch(e.Message.Content))
// {
// var segments = e.Message.Content.Split(' ');
// var channel = await e.GetChannelAsync(segments[2]);
// await e.ReplyAsync(new()
// {
// Content = $"子频道ID{channel.ID}\n子频道名称{channel.Name}\n子频道类型{channel.Type}",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 创建子频道测试” 消息后,创建子频道
// var match = _atCreateChannelRegex.Match(e.Message.Content);
// if (match.Success)
// {
// var channel = await e.CreateChannelAsync(e.Message.GuildID, new()
// {
// Name = match.Groups["Name"].Value,
// Type = ChannelType.Text,
// SubType = ChannelSubType.Chat,
// PrivateType = PrivateType.Public,
// SpeakPermission = SpeakPermission.All,
// });
// await e.ReplyAsync(new()
// {
// Content = $"创建子频道ID{channel.ID}\n子频道名称{channel.Name}\n子频道类型{channel.Type}",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 修改子频道测试 <ID> <Name>” 消息后,修改子频道
// match = _atModifyChannelRegex.Match(e.Message.Content);
// if (match.Success)
// {
// var id = match.Groups["ID"].Value;
// var channel = await e.GetChannelAsync(id);
// var name = match.Groups["Name"].Value;
// channel = await e.ModifyChannelAsync(id, new()
// {
// Name = name,
// ParentID = channel.ParentID,
// Position = channel.Position,
// PrivateType = channel.PrivateType,
// SpeakPermission = channel.SpeakPermission,
// });
// await e.ReplyAsync(new()
// {
// Content = $"修改子频道ID{channel.ID}\n子频道新名称{channel.Name}",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 删除子频道测试 <ID>” 消息后,删除子频道
// match = _atDeleteChannelRegex.Match(e.Message.Content);
// if (match.Success)
// {
// var id = match.Groups["ID"].Value;
// var channel = await e.GetChannelAsync(id);
// await e.DeleteChannelAsync(id);
// await e.ReplyAsync(new()
// {
// Content = $"删除子频道ID{channel.ID}\n子频道名称{channel.Name}",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “@Bot 获取子频道在线成员数测试 <ID>” 消息后,回复在线成员数
// match = _atChannelOnlineMemberCountRegex.Match(e.Message.Content);
// if (match.Success)
// {
// var id = match.Groups["ID"].Value;
// var count = await e.GetChannelOnlineMemberCountAsync(id);
// await e.ReplyAsync(new()
// {
// Content = $"子频道在线成员数:{count}",
// MessageID = e.Message.ID,
// });
// }
// }
// /// <summary>
// /// 频道私信事件
// /// </summary>
// private static async Task OnDirectMessageCreateAsync(object sender, DirectMessageEventArgs e)
// {
// // 收到 “测试” 消息后,回复 “私信测试”
// if (e.Message.Content == "测试")
// {
// await e.ReplyAsync(new()
// {
// Content = "私信测试",
// MessageID = e.Message.ID,
// });
// }
// // 收到 “撤回测试” 消息后,先发送一个消息,过几秒后撤回
// if (e.Message.Content == "撤回测试")
// {
// var delay = 5 * 1000;
// var msg = await e.ReplyAsync(new()
// {
// Content = $"该消息将在{delay / 1000}秒后撤回",
// MessageID = e.Message.ID,
// });
// await Task.Delay(delay);
// await e.DeleteDirectMessageAsync(msg);
// }
// }
// /// <summary>
// /// 文字子频道全量消息事件(仅私域)
// /// </summary>
// private static async Task OnMessageCreateAsync(object sender, GuildMessageEventArgs e)
// {
// // 收到 “测试” 消息后,回复 “文字频道测试”
// if (e.Message.Content == "测试")
// {
// await e.ReplyAsync(new()
// {
// Content = "文字频道测试",
// MessageID = e.Message.ID,
// });
// }
// }
// /// <summary>
// /// 消息表态添加事件
// /// </summary>
// private static async Task OnMessageReactionAddAsync(object sender, MessageReactionEventArgs e)
// {
// Log.Information("MessageReactionAdd");
// await Task.CompletedTask;
// }
// /// <summary>
// /// 消息表态移除事件
// /// </summary>
// private static async Task OnMessageReactionRemoveAsync(object sender, MessageReactionEventArgs e)
// {
// Log.Information("MessageReactionRemove");
// await Task.CompletedTask;
// }
// /// <summary>
// /// 按钮交互
// /// </summary>
// private static async Task OnInteractionCreateAsync(object sender, InteractionEventArgs e)
// {
// Log.Information("InteractionCreate");
// // 由于 websocket 推送事件是单向的,开发者收到事件之后,需要进行一次"回应"告知QQ后台事件已经收到否则客户端会一直处于loading状态直到超时。
// await e.RespondToInteractionAsync(e.Interaction.ID);
// }
// private static async Task OnGuildUpdateAsync(object sender, GuildUpdateEventArgs e)
// {
// Log.Information("GuildUpdate");
// await Task.CompletedTask;
// }
// private static async Task OnChannelCreateAsync(object sender, ChannelCreateEventArgs e)
// {
// Log.Information($"ChannelCreate:[{e.Channel.ID}]{e.Channel.Name}");
// await Task.CompletedTask;
// }
// #endregion
// #region QQ聊天测试
// /// <summary>
// /// 单聊事件
// /// </summary>
// private static async Task OnC2CMessageCreateAsync(object sender, Models.QQ.QQMessageEventArgs e)
// {
// await e.ReplyAsync(new()
// {
// Content = "私聊测试",
// Type = QQMessageType.Text,
// MessageID = e.Message.ID,
// });
// }
// /// <summary>
// /// 群聊事件
// /// </summary>
// private static async Task OnGroupAtMessageCreateAsync(object sender, Models.QQ.QQMessageEventArgs e)
// {
// await e.ReplyAsync(new()
// {
// Content = "群聊测试",
// Type = QQMessageType.Text,
// MessageID = e.Message.ID,
// });
// }
// #endregion
// }
//}

View File

@ -2,7 +2,7 @@
"profiles": {
"RainBOT": {
"commandName": "Project",
"commandLineArgs": "--debug -g766616821"
"commandLineArgs": "--debug --test -g766616821"
}
}
}

View File

@ -21,9 +21,12 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="OneBot-HTTPClient">
<HintPath>..\..\OneBot-HTTPClient\bin\Debug\net9.0\OneBot-HTTPClient.dll</HintPath>
</Reference>
<EditorConfigFiles Remove="C:\milimoe\RainBOT-CSharp\src\.editorconfig" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\FunGame.Core\FunGame.Core.csproj" />
<ProjectReference Include="..\..\OneBot-HTTPClient\src\OneBot-HTTPClient.csproj" />
</ItemGroup>
</Project>

233
src/Settings/AI.cs Normal file
View File

@ -0,0 +1,233 @@
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Milimoe.RainBOT.Settings
{
public class AI
{
public static bool CD { get; set; } = false;
public static HashSet<string> Context { get; set; } = [];
public static HashSet<string> List { get; set; } = [];
private static readonly string apiKey = GeneralSettings.AIAPIToken;
private static readonly string apiUrl = "https://api.deepseek.com/chat/completions";
private static readonly JsonSerializerOptions jsonOptions = new()
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true
};
public static void Add(string user, string msg)
{
if (msg.Trim() == "") return;
if (List.Count < 10)
{
if (msg.Length > 35) msg = msg[..35];
List.Add($"{user}说: {msg}");
}
}
public static async Task<string> Chat()
{
CD = true;
using HttpClient httpClient = new();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
ChatRequest request = new()
{
Messages = [
new() { Role = "system", Content = @"你是用户的一个傲娇好友小雪,下面是你的设定:
//
××
绿
MAX却会给流浪猫带高级罐头
1怀
...
2
...线
...
3-
...
......
4
++
...
QQ群2CS2的群
80" }
],
MaxTokens = 140
};
if (Context.Count > 0) request.Messages.Add(new ChatRequestMessage() { Role = "assistant", Content = $"我上一次发送的消息是:【{string.Join(" && ", Context)}】。这是我本次回复可以参考的内容,我需要注意不能重复这些内容。" });
request.Messages.AddRange(List.Select(s => new ChatRequestMessage { Role = "user", Content = s }));
Console.WriteLine($"本次发送 AI 请求内容:{string.Join(". ", List)}");
if (Context.Count >= 2) Context.Remove(Context.First());
List.Clear();
try
{
if (request.Stream)
{
// todo
}
else
{
string jsonRequest = JsonSerializer.Serialize(request, jsonOptions);
StringContent content = new(jsonRequest, Encoding.UTF8, "application/json");
HttpResponseMessage response = await httpClient.PostAsync(apiUrl, content);
string jsonResponse = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
ChatCompletionResponse completionResponse = JsonSerializer.Deserialize<ChatCompletionResponse>(jsonResponse, jsonOptions) ?? new();
string reply = completionResponse?.Choices?[0].Message.Content ?? "";
Context.Add(reply);
Console.WriteLine($"Assistant: {reply}");
return reply;
}
else
{
Console.WriteLine($"请求失败,状态码:{response.StatusCode}");
Console.WriteLine($"响应内容:{jsonResponse}");
}
}
return "";
}
catch (Exception ex)
{
Console.WriteLine($"发生异常:{ex.Message}");
}
return "";
}
public static async Task<string> GetBalance()
{
// DeepSeek API 查询余额的 URL
string url = "https://api.deepseek.com/user/balance";
using HttpClient httpClient = new();
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
try
{
HttpResponseMessage response = await httpClient.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
BalanceResponse balanceResponse = JsonSerializer.Deserialize<BalanceResponse>(responseBody, jsonOptions) ?? new();
bool isAvailable = balanceResponse.IsAvailable;
List<string> strings = [];
List<BalanceInfo> balanceInfos = balanceResponse.BalanceInfos;
strings.Add($"账户是否有余额可用:{isAvailable}");
strings.Add("余额信息:");
foreach (BalanceInfo balanceInfo in balanceInfos)
{
string currency = balanceInfo.Currency;
string totalBalance = balanceInfo.TotalBalance;
string grantedBalance = balanceInfo.GrantedBalance;
string toppedUpBalance = balanceInfo.ToppedUpBalance;
strings.Add($"货币:{currency}");
strings.Add($"总可用余额:{totalBalance}");
strings.Add($"赠金余额:{grantedBalance}");
strings.Add($"充值余额:{toppedUpBalance}");
}
return string.Join("\r\n", strings);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"HTTP 请求错误: {ex.Message}");
}
catch (JsonException ex)
{
Console.WriteLine($"JSON 解析错误: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"其他错误: {ex.Message}");
}
return "未查询到余额信息。";
}
}
public class ChatRequestMessage
{
public string Role { get; set; } = "";
public string Content { get; set; } = "";
}
public class ChatRequest
{
public string Model { get; set; } = "deepseek-chat";
public List<ChatRequestMessage> Messages { get; set; } = [];
public bool Stream { get; set; } = false;
public int MaxTokens { get; set; } = 50;
}
public class ChatCompletionResponse
{
public List<Choice> Choices { get; set; } = [];
}
public class Choice
{
public Message Message { get; set; } = new();
}
public class Message
{
public string Role { get; set; } = "";
public string Content { get; set; } = "";
}
public class BalanceInfo
{
[JsonPropertyName("currency")]
public string Currency { get; set; } = "";
[JsonPropertyName("total_balance")]
public string TotalBalance { get; set; } = "";
[JsonPropertyName("granted_balance")]
public string GrantedBalance { get; set; } = "";
[JsonPropertyName("topped_up_balance")]
public string ToppedUpBalance { get; set; } = "";
}
public class BalanceResponse
{
[JsonPropertyName("is_available")]
public bool IsAvailable { get; set; } = false;
[JsonPropertyName("balance_infos")]
public List<BalanceInfo> BalanceInfos { get; set; } = [];
}
}

View File

@ -36,8 +36,14 @@ namespace Milimoe.RainBOT.Settings
public static long PCallBrother { get; set; } = 4;
public static bool IsAI { get; set; } = true;
public static long PAI { get; set; } = 100;
public static bool IsDebug { get; set; } = false;
public static bool IsQQBot { get; set; } = false;
public static long DebugGroupID { get; set; } = 0;
public static long BlackTimes { get; set; } = 5;
@ -56,8 +62,14 @@ namespace Milimoe.RainBOT.Settings
public static List<long> FunGameGroup { get; set; } = [];
public static List<long> FunGameWebSocketGroup { get; set; } = [];
public static string FunGameServer { get; set; } = "";
public static string FunGameToken { get; set; } = "";
public static string AIAPIToken { get; set; } = "";
public static PluginConfig Configs { get; set; } = new("rainbot", "config");
public static void LoadSetting()
@ -128,6 +140,14 @@ namespace Milimoe.RainBOT.Settings
{
PCallBrother = (long)value;
}
if (configs.TryGetValue("IsAI", out value) && value != null)
{
IsAI = (bool)value;
}
if (configs.TryGetValue("PAI", out value) && value != null)
{
PAI = (long)value;
}
if (configs.TryGetValue("BlackTimes", out value) && value != null)
{
BlackTimes = (long)value;
@ -160,10 +180,22 @@ namespace Milimoe.RainBOT.Settings
{
FunGameGroup = (List<long>)value;
}
if (configs.TryGetValue("FunGameWebSocketGroup", out value) && value != null)
{
FunGameWebSocketGroup = (List<long>)value;
}
if (configs.TryGetValue("FunGameServer", out value) && value != null)
{
FunGameServer = (string)value;
}
if (configs.TryGetValue("FunGameToken", out value) && value != null)
{
FunGameToken = (string)value;
}
if (configs.TryGetValue("AIAPIToken", out value) && value != null)
{
AIAPIToken = (string)value;
}
}
public static void SaveConfig()
@ -183,6 +215,8 @@ namespace Milimoe.RainBOT.Settings
Configs.Add("PReverseAt", PReverseAt);
Configs.Add("IsCallBrother", IsCallBrother);
Configs.Add("PCallBrother", PCallBrother);
Configs.Add("IsAI", IsAI);
Configs.Add("PAI", PAI);
Configs.Add("BlackTimes", BlackTimes);
Configs.Add("BlackFrozenTime", BlackFrozenTime);
Configs.Add("MuteAccessGroup", MuteAccessGroup);
@ -191,7 +225,10 @@ namespace Milimoe.RainBOT.Settings
Configs.Add("SayNoAccessGroup", SayNoAccessGroup);
Configs.Add("OSMCoreGroup", OSMCoreGroup);
Configs.Add("FunGameGroup", FunGameGroup);
Configs.Add("FunGameWebSocketGroup", FunGameWebSocketGroup);
Configs.Add("FunGameServer", FunGameServer);
Configs.Add("FunGameToken", FunGameToken);
Configs.Add("AIAPIToken", AIAPIToken);
Configs.Save();
}
@ -218,6 +255,9 @@ namespace Milimoe.RainBOT.Settings
case "fungamegroup":
list = FunGameGroup;
break;
case "fungamewebsocketgroup":
list = FunGameWebSocketGroup;
break;
}
string msg = list.Count > 0 ? "权限组" + group + "拥有以下成员:" + "\r\n" + string.Join("\r\n", list) : "此权限组不存在或没有任何成员。";
_ = isgroup ? Bot.SendGroupMessage(target, "显示列表成员", msg) : Bot.SendFriendMessage(target, "显示列表成员", msg);

View File

@ -45,6 +45,10 @@ namespace Milimoe.RainBOT.Settings
{
ReverseAtIgnore = (List<long>)value;
}
if (configs.TryGetValue("CustomIgnore", out value) && value != null)
{
CustomIgnore = new HashSet<string>((List<string>)value);
}
}
public static void SaveConfig()

View File

@ -0,0 +1,271 @@
using System.Collections;
using Milimoe.FunGame.Core.Api.Utility;
using Milimoe.FunGame.Core.Controller;
using Milimoe.FunGame.Core.Library.Common.Network;
using Milimoe.FunGame.Core.Library.Constant;
using Milimoe.FunGame.Core.Model;
using Milimoe.OneBot.Model.Other;
using Milimoe.RainBOT.ListeningTask;
namespace Milimoe.RainBOT.Settings
{
public class OshimaController : RunTimeController
{
public static OshimaController Instance { get; set; } = new();
public static FunGameConfig Config { get; set; } = new();
public static int CurrentRetryTimes { get; set; } = -1;
public static int MaxRetryTimes => 30;
public const string ServerName = "oshima.fungame.anonymous";
public override bool BeforeConnect(ref string addr, ref int port, ArrayList args)
{
if (Config.FunGame_isRetrying)
{
Console.WriteLine("正在连接服务器,请耐心等待。");
return false;
}
string[] strings = ["oshima.fungame.fastauto"];
args.Add(strings);
args.Add(false);
if (!Config.FunGame_isConnected)
{
CurrentRetryTimes++;
if (CurrentRetryTimes == 0) Console.WriteLine("开始连接服务器...");
else Console.WriteLine("第" + CurrentRetryTimes + "次重试连接服务器...");
// 超过重连次数上限
if (CurrentRetryTimes + 1 > MaxRetryTimes)
{
Config.FunGame_isAutoRetry = false;
Console.WriteLine("无法连接至服务器。");
_ = Bot.SendFriendMessage(GeneralSettings.Master, "websocket", "重连服务器失败,重试次数已过多。");
return false;
}
Config.FunGame_isRetrying = true;
return true;
}
else
{
Console.WriteLine("已连接至服务器,请勿重复连接。");
return false;
}
}
public override void AfterConnect(ArrayList ConnectArgs)
{
Config.FunGame_isRetrying = false;
string msg = ConnectArgs[1]?.ToString() ?? "";
string serverName = ConnectArgs[2]?.ToString() ?? "";
string notice = ConnectArgs[3]?.ToString() ?? "";
if (msg != "") Console.WriteLine(msg);
if (serverName != "") Console.WriteLine(serverName);
if (notice != "") Console.WriteLine(notice);
}
public async Task Start()
{
ConnectResult result = ConnectResult.CanNotConnect;
while (result != ConnectResult.Success && Config.FunGame_isAutoRetry)
{
try
{
string[] strings = GeneralSettings.FunGameServer.Split(':');
int port = strings.Length > 1 ? int.Parse(strings[1]) : 443;
result = await ConnectAsync(TransmittalType.WebSocket, strings[0], port, true, "ws");
Config.FunGame_isRetrying = false;
if (result != ConnectResult.Success)
{
await Task.Delay(5000);
}
else
{
break;
}
}
catch (Exception e)
{
Error(e);
break;
}
}
}
public async Task Retry(bool send = false)
{
if (HTTPClient is null)
{
try
{
string[] strings = GeneralSettings.FunGameServer.Split(':');
int port = strings.Length > 1 ? int.Parse(strings[1]) : 443;
if (await ConnectAsync(TransmittalType.WebSocket, strings[0], port, true, "ws") == ConnectResult.Success)
{
Console.WriteLine("重连成功!");
if (send)
{
await Bot.SendFriendMessage(GeneralSettings.Master, "websocket", "重连服务器成功");
}
}
else
{
Console.WriteLine("重连失败!");
if (!Config.FunGame_isRetrying && Config.FunGame_isAutoRetry)
{
await Task.Delay(5000);
if (!Config.FunGame_isRetrying && Config.FunGame_isAutoRetry)
{
await Retry();
}
}
}
}
catch { }
}
}
public async Task ConnectToAnonymousServer()
{
if (HTTPClient != null)
{
Dictionary<string, object> data = [];
data.Add("access_token", GeneralSettings.FunGameToken);
await HTTPClient.Send(SocketMessageType.AnonymousGameServer, ServerName, data);
}
}
public async Task DisconnectFromAnonymousServer()
{
if (HTTPClient != null)
{
await HTTPClient.Send(SocketMessageType.EndGame);
}
}
public async Task DisconnectAsync()
{
if (HTTPClient != null)
{
await HTTPClient.Send(SocketMessageType.Disconnect);
Close_WebSocket();
}
}
public override async void Error(Exception e)
{
Console.WriteLine(e.ToString());
await DisconnectAsync();
if (!Config.FunGame_isRetrying && Config.FunGame_isAutoRetry)
{
CurrentRetryTimes = -1;
Config.FunGame_isAutoRetry = true;
await Task.Delay(5000);
if (!Config.FunGame_isRetrying && Config.FunGame_isAutoRetry)
{
await Retry();
}
}
}
public override void WritelnSystemInfo(string msg, LogLevel level = LogLevel.Info, bool useLevel = true)
{
Console.WriteLine(msg);
}
protected override void SocketHandler_Disconnect(SocketObject ServerMessage)
{
Console.WriteLine("断开服务器连接成功");
}
protected override async void SocketHandler_AnonymousGameServer(SocketObject ServerMessage)
{
Dictionary<string, object> data = ServerMessage.GetParam<Dictionary<string, object>>(0) ?? [];
if (data.Count > 0)
{
long qq = NetworkUtility.JsonDeserializeFromDictionary<long>(data, "qq");
string openid = NetworkUtility.JsonDeserializeFromDictionary<string>(data, "openid") ?? "";
long groupid = NetworkUtility.JsonDeserializeFromDictionary<long>(data, "groupid");
string msg = NetworkUtility.JsonDeserializeFromDictionary<string>(data, "msg") ?? "";
if (msg != "")
{
if (qq == 0 && openid != "" && QQOpenID.QQAndOpenID.TryGetValue(openid, out long tempqq))
{
qq = tempqq;
}
if (qq > 0 && groupid > 0)
{
await Bot.SendGroupMessageAt(qq, groupid, "匿名服务器消息", msg);
}
else
{
if (qq > 0)
{
foreach (Group g in Bot.Groups.Where(g => GeneralSettings.FunGameWebSocketGroup.Contains(g.group_id)))
{
Member m = Bot.GetMember(g.group_id, qq);
if (m.user_id == qq)
{
await Bot.SendGroupMessageAt(qq, g.group_id, "FunGame推送", msg);
break;
}
}
}
else if (groupid > 0 && Bot.Groups.Any(g => g.group_id == groupid))
{
await Bot.SendGroupMessage(groupid, "匿名服务器消息", msg);
}
}
}
}
}
public async Task SCAdd(long qq, long groupid, string content, double sc = 0)
{
if (HTTPClient != null && !GroupRecallTask.Recalls.ContainsKey(content))
{
if (sc == 0)
{
sc = Random.Shared.Next(-3, 4);
if (sc == 0)
{
return;
}
}
Dictionary<string, object> data = [];
data.Add("command", "scadd");
data.Add("qq", qq);
data.Add("groupid", groupid);
if (content.Length > 8)
{
content = content[..8] + "...";
}
data.Add("content", content);
data.Add("sc", sc);
await HTTPClient.Send(SocketMessageType.AnonymousGameServer, ServerName, data);
}
}
public async Task SCList(long groupid, long qq, bool reverse = false)
{
if (HTTPClient != null)
{
Dictionary<string, object> data = [];
data.Add("command", "sclist");
data.Add("groupid", groupid);
data.Add("qq", qq);
data.Add("reverse", reverse);
await HTTPClient.Send(SocketMessageType.AnonymousGameServer, ServerName, data);
}
}
public async Task SCRecord(long groupid, long qq)
{
if (HTTPClient != null)
{
Dictionary<string, object> data = [];
data.Add("command", "screcord");
data.Add("groupid", groupid);
data.Add("qq", qq);
await HTTPClient.Send(SocketMessageType.AnonymousGameServer, ServerName, data);
}
}
}
}

93
src/Settings/QQOpenID.cs Normal file
View File

@ -0,0 +1,93 @@
using System.Text.Json.Serialization;
using Milimoe.FunGame.Core.Api.Utility;
namespace Milimoe.RainBOT.Settings
{
public class QQOpenID
{
public static Dictionary<string, long> QQAndOpenID { get; set; } = [];
public static PluginConfig Configs { get; set; } = new("rainbot", "qqopenid");
public static void LoadConfig()
{
Configs.LoadConfig();
foreach (string str in Configs.Keys)
{
if (Configs.TryGetValue(str, out object? value) && value is long qq && qq != 0)
{
QQAndOpenID.TryAdd(str, qq);
}
}
}
public static void SaveConfig()
{
lock (Configs)
{
Configs.Clear();
foreach (string openid in QQAndOpenID.Keys)
{
Configs.Add(openid, QQAndOpenID[openid]);
}
Configs.SaveConfig();
}
}
public static string Bind(string openid, long qq)
{
if (openid.Trim() == "" || qq <= 0)
{
return "请输入正确的OpenID和QQ";
}
if (QQAndOpenID.Any(kv => kv.Value == qq || kv.Key != openid))
{
return $"此接入码已被其他人绑定或者你的QQ已经绑定了其他的接入码。如果你是此接入码的主人请联系客服处理。";
}
if (QQAndOpenID.TryAdd(openid, qq))
{
SaveConfig();
}
else
{
return $"绑定失败,请稍后再试!如持续绑定失败请联系客服处理。";
}
return "绑定成功!如果需要解除绑定,请发送【解绑+接入码】!";
}
public static string Unbind(string openid, long qq)
{
if (QQAndOpenID.TryGetValue(openid, out long bindqq) && bindqq == qq && QQAndOpenID.Remove(openid))
{
SaveConfig();
return NetworkUtility.JsonSerialize($"解绑成功!");
}
return NetworkUtility.JsonSerialize("解绑失败!没有查到绑定的信息或者此账号已被其他人绑定,如果你是此接入码的主人,请联系客服处理。");
}
}
public class ThirdPartyMessage
{
[JsonPropertyName("id")]
public string Id { get; set; } = "";
[JsonPropertyName("isgroup")]
public bool IsGroup { get; set; } = false;
[JsonPropertyName("detail")]
public string Detail { get; set; } = "";
[JsonPropertyName("timestamp")]
public string Timestamp { get; set; } = "";
[JsonPropertyName("openid")]
public string OpenId { get; set; } = "";
[JsonPropertyName("authoropenid")]
public string AuthorOpenId { get; set; } = "";
}
}

File diff suppressed because it is too large Load Diff