private static void Main(string[] args) { #if DEBUG logger("DEBUG", "WARNING: Running in debug mode."); DEBUGMODE = true; Thread.Sleep(5000); #endif DateTime start = DateTime.Now; //string ipv4_ip = NetworkInfo.GetLocalIpAddress(); MainHolder.logger = logger; bool booted = false; Exception exc = null; #region 读取配置 StreamReader cfile = new StreamReader("config.json"); JObject config = (JObject)JsonConvert.DeserializeObject(cfile.ReadToEnd()); cfile.Close(); host = config["mirai"].Value <string>("server"); me_qq = config["mirai"].Value <long>("user"); key = config["mirai"].Value <string>("key"); try { port = config["mirai"].Value <int>("port"); } catch { port = 8080; } authenti = config["auth"].Value <string>("name"); MainHolder.LiveRoom = config["bili"].Value <int>("roomid"); MainHolder.BiliWatchUIDs = new List <int>(); foreach (JToken j in config["bili"]["uids"]) { MainHolder.BiliWatchUIDs.Add(j.Value <int>()); } MainHolder.useBiliRecFuncs = config["auth"].Value <bool>("rectfunc"); MainHolder.enableNativeFuncs = config["auth"].Value <bool>("nativefuncs"); //如果是本地ip就走本地 //if (host == ipv4_ip && Environment.OSVersion.Platform != PlatformID.Win32NT) //{ // logger("MainThread", "Running on the same server! Using 127.0.0.1 to connect mirai."); // host = "127.0.0.1"; //} #endregion while (true)//故障自动重启 { try { //Console.Title = "ManageBot By Developer_ken - Initializing..."; logger("MainThread", "Pushing up the engine...", ConsoleColor.Black, ConsoleColor.Green); { IServiceProvider services = new ServiceCollection().AddMiraiBaseFramework() // 表示使用基于基础框架的构建器 .AddHandler <tech.msgp.groupmanager.Code.EventHandlers.EventHandler>() .Services .AddDefaultMiraiHttpFramework() // 表示使用 mirai-api-http 实现的构建器 .ResolveParser <tech.msgp.groupmanager.Code.EventHandlers.EventHandler>() // 只提前解析 DynamicPlugin 将要用到的消息解析器 .AddInvoker <MiraiHttpMessageHandlerInvoker>() // 使用默认的调度器 .AddClient <MiraiHttpSession>() // 使用默认的客户端 .Services // 由于 IMiraiHttpSession 使用 IOptions<MiraiHttpSessionOptions>, 其作为 Singleton 被注册 // 配置此项将配置基于此 IServiceProvider 全局的连接配置 // 如果你想一个作用域一个配置的话 // 自行做一个实现类, 继承IMiraiHttpSession, 构造参数中使用 IOptionsSnapshot<MiraiHttpSessionOptions> // 并将其传递给父类的构造参数 // 然后在每一个作用域中!先!配置好 IOptionsSnapshot<MiraiHttpSessionOptions>, 再尝试获取 IMiraiHttpSession .Configure <MiraiHttpSessionOptions>(options => { options.Host = host; options.Port = port; // 端口 options.AuthKey = key; // 凭据 }) .AddLogging() .BuildServiceProvider(); IServiceScope scope = services.CreateScope(); //var x = (IAsyncDisposable)scope; //await using AsyncServiceScope scope = services.CreateAsyncScope(); // 自 .NET 6.0 起才可以如此操作代替上边两句 services = scope.ServiceProvider; IMiraiHttpSession session = services.GetRequiredService <IMiraiHttpSession>(); // 大部分服务都基于接口注册, 请使用接口作为类型解析 session.ConnectAsync(me_qq).Wait(); // 填入期望连接到的机器人QQ号 MainHolder.session = session; } //MainHolder.session.GetFriendListAsync().Wait(); logger("MainThread", "BotAPI is up.", ConsoleColor.Black, ConsoleColor.Green); pool = new pThreadPool(); MainHolder.pool = pool; logger("MainThread", "Threadpool is UP.", ConsoleColor.Black, ConsoleColor.Green); pool.submitWorkload(() => { while (true) { /* * logger("threadpool", "threads= " + pool.min_size + "<" + pool.size + "/" + pool.busythread + "<" + pool.max_size + * " | works= " + pool.queuelen + "<" + pool.queue_max_len + " | errors= " + pool.excepttionlen + "<" + pool.exceptionmaxlen * ); */ Dictionary <Guid, Exception> err = pool.popException(); if (err != null) { foreach (KeyValuePair <Guid, Exception> e in err) { logger("threadpool_exception", "Work-" + e.Key + " -> " + e.Value.Message, ConsoleColor.DarkRed); logger("threadpool_exception", "Work-" + e.Key + " -> " + e.Value.StackTrace, ConsoleColor.DarkRed); } } pool.clearExceptions(); Thread.Sleep(1000); } }); pool.onWorkloadStartProcess += startwork; pool.onWorkloadStopProcess += stopwork; logger("MainThread", "Events registered.", ConsoleColor.Black, ConsoleColor.Green); MainHolder.INIT(config); //string xml = "<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><msg serviceID=\"35\" templateID=\"1\" action=\"viewMultiMsg\" brief=\"[聊天记录]\" m_resid=\"y0oBW4IOb1T2mMOQXiMI9tajqUkTEioFVMFc66YCia2fQEx2+Sp1Bogtcn80e6R+\" m_fileName=\"6858932750478640422\" tSum=\"34\" sourceMsgId=\"0\" url=\"\" flag=\"3\" adverSign=\"0\" multiMsgFlag=\"0\"><item layout=\"1\" advertiser_id=\"0\" aid=\"0\"><title size=\"34\" maxLines=\"2\" lineSpace=\"12\">群聊的聊天记录</title><title size=\"26\" color=\"#777777\" maxLines=\"4\" lineSpace=\"12\">古小艺: 《迷惑行为》新增1个影像</title><title size=\"26\" color=\"#777777\" maxLines=\"4\" lineSpace=\"12\">柠檬味的海鲜龙: 嗯呢</title><title size=\"26\" color=\"#777777\" maxLines=\"4\" lineSpace=\"12\">一只鸡蛋: 新的机器人核心功能已经快移植好了\n现在是离线状态\n这几天要辛苦大家手动处理这些…</ title >< title size =\"26\" color=\"#777777\" maxLines=\"4\" lineSpace=\"12\">呆 萌呆萌瓜: ohhhhhhh</title><hr hidden=\"false\" style=\"0\" /><summary size=\"26\" color=\"#777777\">查看34条转发消息</summary></item><source name=\"聊天记录\" icon=\"\" action=\"\" appid=\"-1\" /></msg>"; //api.sendXmlMessage(417944217, xml, MsgType.GROUP); //Console.Title = "ManageBot By Developer_ken - Standby"; try { /* * MainHolder.session.GroupMessageEvt += new Event_GroupMessage().GroupMessage; * MainHolder.session.GroupApplyEvt += new GroupEnterRequest().GroupApply; * MainHolder.session.GroupMemberJoinedEvt += new GroupMemberIncrease().GroupMemberJoined; * GroupMemberLeave gleave = new GroupMemberLeave(); * MainHolder.session.GroupMemberKickedEvt += gleave.GroupMemberKicked; * MainHolder.session.GroupMemberPositiveLeaveEvt += gleave.GroupMemberPositiveLeave; * PrivMessageHan pmsg = new PrivMessageHan(); * MainHolder.session.TempMessageEvt += pmsg.TempMessage; * MainHolder.session.FriendMessageEvt += pmsg.FriendMessage; * /* * han.onGroupMessageReceive += new Event_GroupMessage().GroupMessage; * han.onPrivateMessageReceive += new Event_PrivMessage().PrivateMessage; * han.onGroupMemberIncrease += new Event_GroupMemberIncrease().GroupMemberIncrease; * han.onGroupMemberDecrease += new Event_GroupMemberLeave().GroupMemberDecrease; * han.onGroupEnterRequest += new Event_GroupMemberRequest().GroupAddRequest; * han.onGroupMessageSendOkay += onSendSuccess; */ logger("MainThread", "Event Recevier is UP.", ConsoleColor.Black, ConsoleColor.White); } catch (Exception) { logger("MainThread", "Event Recevier FAILED.", ConsoleColor.Black, ConsoleColor.Red); } logger("MainThread", "Stand by. The bot is up and ready to go. Type to set an log filter.", ConsoleColor.Black, ConsoleColor.Green); #if RELEASE MainHolder.broadcaster.BroadcastToAdminGroup("[启动报告]\n" + (DEBUGMODE ? "⚠当前处于调试模式,不适合长期运行⚠\n" : "") + "当前版本:" + codeName + version + "\n" + "启用耗时:" + (DateTime.Now - start).TotalSeconds + "s\n" + "当前授权:" + authenti + "\n" + "授权约束:" + (MainHolder.useBiliRecFuncs ? "" : "[MainHolder.useBiliRecFuncs=False]\n") + (MainHolder.enableNativeFuncs ? "" : "[MainHolder.enableNativeFuncs=False]\n")) ; #endif if (booted) { MainHolder.broadcaster.BroadcastToAdminGroup("严重故障\n机器人遭遇了不可恢复的错误,主线程无法继续运行。为了确保稳定运行," + "主线程已被系统重置。该操作成功完成,程序将会继续运行,但未保存的工作可能已经丢失。\n"); MainHolder.broadcaster.BroadcastToAdminGroup("错误报告\n" + exc.Message + "\nStackTrace >" + exc.StackTrace); } booted = true; while (true) { try { string field = ""; do { ConsoleKeyInfo k = Console.ReadKey(true); if (k.Key == ConsoleKey.Enter) { break; } if (k.Key == ConsoleKey.Backspace) { if (field.Length >= 1) { field = field.Substring(0, field.Length - 1); } continue; } if (k.Key == ConsoleKey.Delete) { field = ""; continue; } field += k.KeyChar; //Console.Title = "input>" + field + " | Press [Enter] to " + (field.Length >= 1 ? "set" : "remove") + " a filter."; } while (true); keyword = field; if (keyword != "") { logger("control", "Filter set.", ConsoleColor.Black, ConsoleColor.Green); //Console.Title = "Filter: " + keyword + " | Press [Enter] to remove filter"; } else { logger("control", "Filter removed.", ConsoleColor.Black, ConsoleColor.Green); //Console.Title = "ManageBot By Developer_ken - Standby"; } } catch { Thread.Sleep(int.MaxValue); } } ; } catch (Exception err) { exc = err; logger("EXCEPTION", "E_FATAL " + err.Message, ConsoleColor.Black, ConsoleColor.Red); logger("EXCEPTION", "STACKTRACE " + err.StackTrace, ConsoleColor.Black, ConsoleColor.Red); //throw; } } }
#pragma warning disable CS1998 // 此异步方法缺少 "await" 运算符,将以同步方式运行。请考虑使用 "await" 运算符等待非阻止的 API 调用,或者使用 "await Task.Run(...)" 在后台线程上执行占用大量 CPU 的工作。 public async Task HandleMessageAsync(IMiraiHttpSession client, IGroupMessageEventArgs e) #pragma warning restore CS1998 // 此异步方法缺少 "await" 运算符,将以同步方式运行。请考虑使用 "await" 运算符等待非阻止的 API 调用,或者使用 "await Task.Run(...)" 在后台线程上执行占用大量 CPU 的工作。 { try { var session = MainHolder.session; WatchDog.FeedDog("grpmsg"); pThreadPool pool = MainHolder.pool; //MainHolder.Logger.Debug("CQPLUGIN", "Event_GroupMessageFired"); MainHolder.MsgCount++; SecondlyTask.lastrecv = DateTime.Now; if (true) { IGroupInfo gpinfo = e.Sender.Group; IGroupMemberInfo gminfo = e.Sender; string gpname = DataBase.me.getGroupName(gpinfo.Id); if (!DataBase.me.connected) { MainHolder.Logger.Error("数据库", "数据库未连接"); } foreach (IChatMessage msg in e.Chain) { if (msg is not UnknownChatMessage)//不处理UnknownChatMessage { switch (msg.Type) { case "Plain": { PlainMessage message = (PlainMessage)msg; if (!DataBase.me.recQQmsg(e.Sender.Id, e.Sender.Group.Id, message.Message)) { MainHolder.Logger.Error("数据库", "未能将消息存入数据库"); } //message.Message { string abvn = AVFinder.abvFromString(message.Message); if (abvn != null && abvn != "") { processVideoBilibili(e, abvn); } } Commands.Proc(session, e, message.Message); } break; case "Xml": { XmlMessage message = (XmlMessage)msg; if (!DataBase.me.recQQmsg(e.Sender.Id, e.Sender.Group.Id, message.Xml)) { MainHolder.Logger.Error("数据库", "未能将消息存入数据库"); } if (Commands.cocogroup == e.Sender.Group.Id) { MainHolder.broadcaster.SendToGroup(e.Sender.Group.Id, "[Xml解析]\n" + message.Xml); } XmlDocument doc = new XmlDocument(); doc.LoadXml(message.Xml); { if (doc["msg"] == null) { MainHolder.broadcaster.SendToAnEgg(e.Sender.Group.Id + "无msg标签的Xml消息\n" + message.Xml); } if (doc["msg"].HasAttribute("action") && doc["msg"].GetAttribute("action") == "viewMultiMsg" && DataBase.me.isAdminGroup(e.Sender.Group.Id)) { string fname = doc["msg"].GetAttribute("m_fileName"); string fresid = doc["msg"].GetAttribute("m_resid"); int tsum = int.Parse(doc["msg"].GetAttribute("tSum")); int flag = int.Parse(doc["msg"].GetAttribute("flag")); int serviceID = int.Parse(doc["msg"].GetAttribute("serviceID")); int m_fileSize = int.Parse(doc["msg"].GetAttribute("m_fileSize")); DataBase.me.saveMessageGroup(fname, fresid, tsum, flag, serviceID, m_fileSize); MainHolder.broadcaster.SendToGroup(e.Sender.Group.Id, "[消息存证]\n该条消息记录已提交至腾讯服务器\n存根ID:" + fname); return; //不再处理该条消息 } if (doc["msg"]["source"] != null && doc["msg"]["source"].HasAttribute("name")) { switch (doc["msg"]["source"].GetAttribute("name")) { case "哔哩哔哩": //B站分享 if (doc["msg"].GetAttribute("url").IndexOf("/live.bilibili.com/") > 0) //直播分享 { } if (doc["msg"].GetAttribute("url").IndexOf("/b23.tv/") > 0) //可能是视频分享 { try { string bvn = BiliApi.AVFinder.bvFromB23url(doc["msg"].GetAttribute("url")); if (bvn != null) //真的是视频分享 { processVideoBilibili(e, bvn); return; } } catch (Exception) { } } break; case "网页分享": if (doc["msg"].GetAttribute("url").IndexOf("/live.bilibili.com/") > 0) //直播分享 { } if (doc["msg"].GetAttribute("url").IndexOf("/www.bilibili.com/video/") > 0) //视频分享 { string bvn = BiliApi.AVFinder.bvFromPlayURL(doc["msg"].GetAttribute("url")); if (bvn != null) //真的是视频分享 { processVideoBilibili(e, bvn); return; } } break; default: break; } } } } break; case "Json": { JsonMessage message = (JsonMessage)msg; if (Commands.cocogroup == e.Sender.Group.Id) { MainHolder.broadcaster.SendToGroup(e.Sender.Group.Id, "[Json解析]\n" + message.Json); } if (!DataBase.me.recQQmsg(e.Sender.Id, e.Sender.Group.Id, message.Json)) { MainHolder.Logger.Error("数据库", "未能将消息存入数据库"); } } break; case "App": { AppMessage message = (AppMessage)msg; if (Commands.cocogroup == e.Sender.Group.Id) { MainHolder.broadcaster.SendToGroup(e.Sender.Group.Id, "[AppContent解析]\n" + message.Content); } if (!DataBase.me.recQQmsg(e.Sender.Id, e.Sender.Group.Id, message.Content)) { MainHolder.Logger.Error("数据库", "未能将消息存入数据库"); } { string abvn = null; try { JObject jb = JObject.Parse(message.Content); abvn = AVFinder.bvFromB23url(jb["meta"]["detail_1"]["qqdocurl"].ToString()); } catch { } if (abvn != null && abvn != "") { processVideoBilibili(e, abvn); } } } break; case "Source": break; case "Image": { /*try * { * ImageMessage message = (ImageMessage)msg; * Ticket t = TicketCoder.Decode(new Bitmap(PicLoader.loadPictureFromURL(message.Url))); * string l = "未知"; * switch (t.Data.Level) * { * case Ticket.CrewLevel.舰长: * l = "舰长"; * break; * case Ticket.CrewLevel.总督: * l = "总督"; * break; * case Ticket.CrewLevel.提督: * l = "提督"; * break; * } * BiliUser bu = new BiliUser(t.Data.Uid, MainHolder.biliapi); * MainHolder.broadcaster.SendToGroup(e.Sender.Group.Id, "[船票]\n" + * "版本=" + t.Data.SpecType + "\n" + * "绑定账号=" + bu.name + "#" + t.Data.Uid + "\n" + * "签发时间=" + t.Data.GenerateTime.ToString("yyyy MM dd HH:mm:ss") + "\n" + * "等级=" + l + "\n" + * "签名有效"); * } * catch (SignatureInvalidException err) * { * MainHolder.broadcaster.SendToGroup(e.Sender.Group.Id, "该船票签名无效"); * } * catch { } */ } break; default: break; } } } } } catch (Exception err) { MainHolder.broadcaster.BroadcastToAdminGroup("[Exception]\n这条消息可能意味着机器人发生了错误。它仍在继续运行,但可能不是很稳定。下面的信息用来帮助鸡蛋定位错误,管理不必在意。\n[群消息接收处理]" + err.Message + "\n\n堆栈跟踪:\n" + err.StackTrace); } return; }