private async Task SendPictureAsync2(IMiraiHttpSession session, string path) // 发图, 不同的是使用 IMessageChainBuilder 构造消息链 { IImageMessage msg = await session.UploadPictureAsync(UploadTarget.Group, path); Builders.IMessageChainBuilder builder = session.GetMessageChainBuilder(); builder.Add(msg); await session.SendGroupMessageAsync(0, builder); // 自己填群号, 一般由 IGroupMessageEventArgs 提供 }
public Task HandleMessageAsync(IMiraiHttpSession session, IGroupMemberKickedEventArgs e) { if (!CheckPreconditions(e.Member) || !BotInfo.SendMemberBeKickedMessage) { return(Task.CompletedTask); } return(session.SendGroupMessageAsync(e.Member.Group.Id, ReplaceMessage(session.GetMessageChainBuilder(), BotInfo.MemberBeKickedMessage, e.Member, e.Operator))); }
public async Task HandleMessageAsync2(IMiraiHttpSession session, IGroupMessageEventArgs e) // 法2: 使用 params IMessageBase[] { IChatMessage plain1 = new PlainMessage($"收到了来自{e.Sender.Name}[{e.Sender.Id}]{{{e.Sender.Permission}}}的群消息:{string.Join(null, (IEnumerable<IChatMessage>)e.Chain)}"); // / 发送者群名片 / / 发送者QQ号 / / 发送者在群内权限 / / 消息链 / IChatMessage plain2 = new PlainMessage("QAQ"); // 在下边的 SendGroupMessageAsync, 你可以串起n个 IMessageBase await session.SendGroupMessageAsync(e.Sender.Group.Id, plain1 /*, plain2, /* etc... */); // 向消息来源群异步发送由以上chain表示的消息 e.BlockRemainingHandlers = false; // 不阻断消息传递。如需阻断请返回true }
private async Task SendPictureAsync(IMiraiHttpSession session, string path) // 发图 { // 你也可以使用另一个重载 UploadPictureAsync(PictureTarget, Stream) // 当 mirai-api-http 在v1.7.0以下时将使用本地的HttpListener做图片中转 // UploadTarget.Friend 对应 IMiraiSession.SendFriendMessageAsync IImageMessage msg = await session.UploadPictureAsync(UploadTarget.Group, path); IChatMessage[] chain = new IChatMessage[] { msg }; // 数组里边可以加上更多的 IMessageBase, 以此达到例如图文并发的情况 await session.SendGroupMessageAsync(0, chain); // 自己填群号, 一般由 IGroupMessageEventArgs 提供 }
public async Task HandleMessageAsync(IMiraiHttpSession session, IGroupMessageEventArgs e) // 法3: 使用 IMessageBuilder { IMessageChainBuilder builder = session.GetMessageChainBuilder(); builder.AddPlainMessage($"收到了来自{e.Sender.Name}[{e.Sender.Id}]{{{e.Sender.Permission}}}的群消息:{string.Join(null, (IEnumerable<IChatMessage>)e.Chain)}"); // / 发送者群名片 / / 发送者QQ号 / / 发送者在群内权限 / / 消息链 / // builder.AddPlainMessage("QAQ").AddPlainMessage("OvO")/* .AddAtMessage(123456) etc... */; await session.SendGroupMessageAsync(e.Sender.Group.Id, builder /*, plain2, /* etc... */); // 向消息来源群异步发送由以上chain表示的消息 // e.BlockRemainingHandlers = true; // 默认不阻断消息传递。如需阻断请删除注释 }
public async Task HandleMessageAsync(IMiraiHttpSession session, IGroupMessageEventArgs e) // 法1: 使用 IMessageBase[] { // 临时消息和群消息一致, 不多写例子了 IChatMessage[] chain = new IChatMessage[] { new PlainMessage($"收到了来自{e.Sender.Name}[{e.Sender.Id}]{{{e.Sender.Permission}}}的群消息:{string.Join(null, (IEnumerable<IChatMessage>)e.Chain)}") // / 发送者群名片 / / 发送者QQ号 / / 发送者在群内权限 / / 消息链 / // 你还可以在这里边加入更多的 IMessageBase }; await session.SendGroupMessageAsync(e.Sender.Group.Id, chain); // 向消息来源群异步发送由以上chain表示的消息 e.BlockRemainingHandlers = false; // 不阻断消息传递。如需阻断请返回true }
public async Task HandleMessageAsync(IMiraiHttpSession session, IGroupMessageEventArgs e) { if (!CheckPreconditions(e.Sender)) { return; } LogHelper.WriteInfoLog($"收到来自{e.Sender.Id}的群消息"); int quoteId = (e.Chain[0] as SourceMessage).Id; for (int i = 0; i < e.Chain.Length; i++) { //获取@群名片 if (e.Chain[i] is IAtMessage atMsg) { IGroupMemberInfo[] groupMemberInfos = await session.GetGroupMemberListAsync(e.Sender.Group.Id); IGroupMemberInfo targetQQ = groupMemberInfos.Where(m => m.Id == atMsg.Target).FirstOrDefault(); string nickName = targetQQ?.Name; e.Chain[i] = new AtMessage(atMsg.Target, nickName); } } bool isHandle = await MessageHandler.HandleMesage(e.Chain.ToOnionsMessages(e.Sender.Id, e.Sender.Name), e.Sender.Group.Id, async outMsg => { if (outMsg != null) { int iRevokeTime = outMsg.RevokeTime; var msg = await outMsg.ToMiraiApiHttpMessages(session, UploadTarget.Group); _ = session.SendGroupMessageAsync(e.Sender.Group.Id, msg, outMsg.Reply ? quoteId : null).ContinueWith(async sendedCallBack => { if (iRevokeTime > 0) { await Task.Delay(1000 * iRevokeTime); _ = session.RevokeMessageAsync(sendedCallBack.Result); } }); } }); e.BlockRemainingHandlers = isHandle; }
static async Task Main(string[] args) { Options opt = null; Parser.Default.ParseArguments <Options>(args).WithParsed <Options>(o => { opt = o; }); var bot = new Bot(); IServiceProvider services = new ServiceCollection().AddMiraiBaseFramework() // 表示使用基于基础框架的构建器 .AddHandler <Bot>(p => bot, ServiceLifetime.Singleton) .Services .AddDefaultMiraiHttpFramework() // 表示使用 mirai-api-http 实现的构建器 .ResolveParser <Bot>(ServiceLifetime.Singleton) .AddInvoker <MiraiHttpMessageHandlerInvoker>() // 使用默认的调度器 .AddClient <MiraiHttpSession>() // 使用默认的客户端 .Services // 由于 MiraiHttpSession 使用 IOptions<MiraiHttpSessionOptions>, 其作为 Singleton 被注册 // 配置此项将配置基于此 IServiceProvider 全局的连接配置 // 如果你想一个作用域一个配置的话 // 自行做一个实现类, 继承MiraiHttpSession, 构造参数中使用 IOptionsSnapshot<MiraiHttpSessionOptions> // 并将其传递给父类的构造参数 // 然后在每一个作用域中!先!配置好 IOptionsSnapshot<MiraiHttpSessionOptions>, 再尝试获取 IMiraiHttpSession .Configure <MiraiHttpSessionOptions>(options => { options.Host = "127.0.0.1"; options.Port = 8080; // 端口 options.AuthKey = opt.AuthKey; // 凭据 }) .AddLogging() .BuildServiceProvider(); IServiceScope scope = services.CreateScope(); await using var x = (IAsyncDisposable)scope; //await using AsyncServiceScope scope = services.CreateAsyncScope(); // 自 .NET 6.0 起才可以如此操作代替上边两句 services = scope.ServiceProvider; IMiraiHttpSession session = services.GetRequiredService <IMiraiHttpSession>(); // 大部分服务都基于接口注册, 请使用接口作为类型解析 //session.AddPlugin(bot); // 实时添加 bot.SetSession(session); await session.ConnectAsync(opt.QQ); // 填入期望连接到的机器人QQ号 await bot.Start(); while (true) { var readline = await Console.In.ReadLineAsync(); if (readline == "exit") { return; } else if (readline.StartsWith("notice ", StringComparison.OrdinalIgnoreCase)) { var message = $"[通知]{readline.Substring(7)}"; var groups = GensouSakuya.QQBot.Core.QQManager.GroupMemberManager.GroupMembers.Values .Select(p => p.GroupId).Distinct().ToList(); groups.ForEach(p => { session.SendGroupMessageAsync(p, new PlainMessage(message)); }); } else if (readline.StartsWith("togroup ", StringComparison.OrdinalIgnoreCase)) { var splited = readline.Split(" "); if (!long.TryParse(splited[1], out var groupNo)) { continue; } var message = string.Join(" ", splited.Skip(2)); await session.SendGroupMessageAsync(groupNo, new PlainMessage(message)); } else if (readline.Equals("save", StringComparison.OrdinalIgnoreCase)) { await DataManager.Save(); } else if (readline.Equals("load", StringComparison.OrdinalIgnoreCase)) { await DataManager.Load(); } } }
public static async Task Connect(long qqId, string ip, ushort port, string authKey, Action <bool, string> ConnectedEvent) { try { // 一套能用的框架, 必须要注册至少一个 Invoker, Parser, Client 和 Handler // Invoker 负责消息调度 // Parser 负责解析消息到具体接口以便调度器调用相关 Handler 下的处理方法 // Client 负责收发原始数据 IServiceProvider services = new ServiceCollection().AddMiraiBaseFramework() // 表示使用基于基础框架的构建器 .Services .AddDefaultMiraiHttpFramework() // 表示使用 mirai-api-http 实现的构建器 .AddInvoker <MiraiHttpMessageHandlerInvoker>() // 使用默认的调度器 .AddHandler <GroupMessage>() // 群消息 .AddHandler <FriendMessage>() // 好友消息 .AddHandler <TempMessage>() // 临时消息 .AddClient <MiraiHttpSession>() // 使用默认的客户端 .Services // 由于 MiraiHttpSession 使用 IOptions<MiraiHttpSessionOptions>, 其作为 Singleton 被注册 // 配置此项将配置基于此 IServiceProvider 全局的连接配置 // 如果你想一个作用域一个配置的话 // 自行做一个实现类, 继承MiraiHttpSession, 构造参数中使用 IOptionsSnapshot<MiraiHttpSessionOptions> // 并将其传递给父类的构造参数 // 然后在每一个作用域中!先!配置好 IOptionsSnapshot<MiraiHttpSessionOptions>, 再尝试获取 IMiraiHttpSession .Configure <MiraiHttpSessionOptions>(options => { options.Host = ip; options.Port = port; // 端口 options.AuthKey = authKey; // 凭据 }) .AddLogging() .BuildServiceProvider(); await using AsyncServiceScope scope = services.CreateAsyncScope(); // 自 .NET 6.0 起才可以如此操作代替上边两句 services = scope.ServiceProvider; IMiraiHttpSession session = services.GetRequiredService <IMiraiHttpSession>(); // 大部分服务都基于接口注册, 请使用接口作为类型解析 await session.ConnectAsync(qqId); // 填入期望连接到的机器人QQ号 Cache.SetTaskAtFixedTime(); IFriendInfo[] IFriendInfos = await session.GetFriendListAsync(); string nickname = "未知"; var self = IFriendInfos.Where(m => m.Id == qqId).FirstOrDefault(); //获取自身昵称失败, 部分QQ号好友中不存在自己? if (self != null) { nickname = self.Name; } ConnectedEvent?.Invoke(true, nickname); BotInfo.QQId = session.QQNumber.Value; BotInfo.IsLogin = true; PluginManager.Connected( BotInfo.QQId, async(targetId, msg) => await session.SendFriendMessageAsync(targetId, await msg.ToMiraiApiHttpMessages(session, UploadTarget.Friend)), async(targetId, msg) => await session.SendGroupMessageAsync(targetId, await msg.ToMiraiApiHttpMessages(session, UploadTarget.Group)), async(targetId, targetGroup, msg) => await session.SendTempMessageAsync(targetId, targetGroup, await msg.ToMiraiApiHttpMessages(session, UploadTarget.Temp)) ); RssWorker.StartRssTask(async(msgs, targetId, groupId) => { if (targetId != -1) { _ = session.SendFriendMessageAsync(targetId, await msgs.ToMiraiApiHttpMessages(session, UploadTarget.Friend)); } else if (groupId != -1) { _ = session.SendGroupMessageAsync(groupId, await msgs.ToMiraiApiHttpMessages(session, UploadTarget.Group)); } }); while (true) { BotInfo.IsLogin = true; if (Console.ReadLine() == "exit") { BotInfo.IsLogin = false; PluginManager.Disconnected(); session.Dispose(); ConnectedEvent?.Invoke(false, ""); break; } Task.Delay(100).Wait(); } } catch (Exception ex) { LogHelper.WriteErrorLog(ex); ConnectedEvent?.Invoke(false, ex.Message); } }