public int CallFunction(FunctionEnums.Functions ApiName, params object[] args) { JObject json = new JObject { new JProperty("ApiName", JsonConvert.SerializeObject(ApiName)), new JProperty("Args", JsonConvert.SerializeObject(args)) }; if ((ApiName != FunctionEnums.Functions.Disable && ApiName != FunctionEnums.Functions.Exit && ApiName != FunctionEnums.Functions.Enable && ApiName != FunctionEnums.Functions.StartUp) && Loading) { LogHelper.WriteLog(LogLevel.Warning, "OPQBot框架", "插件逻辑处理", "插件模块处理中...", "x 不处理"); return(-1); } //遍历插件列表,遇到标记消息阻断则跳出 foreach (var item in Plugins) { Dll dll = item.dll; //先看此插件是否已禁用 if (item.Enable is false) { continue; } if (Save.TestPluginsList.Any(x => x == item.appinfo.Name)) { Debug.WriteLine($"{item.appinfo.Name} 插件测试中,忽略消息投递"); continue; } try { int result = dll.CallFunction(ApiName, args); //调用函数, 返回 1 表示消息阻塞, 跳出后续 if (result == 1) { return(Plugins.IndexOf(item) + 1); } } catch (Exception e) { LogHelper.WriteLog(LogLevel.Error, "函数执行异常", $"插件 {item.appinfo.Name} {ApiName} 函数发生错误,错误信息:{e.Message} {e.StackTrace}"); Thread thread = new Thread(() => { var b = ErrorHelper.ShowErrorDialog($"错误模块:{item.appinfo.Name}\n{ApiName} 函数发生错误,错误信息:\n{e.Message} {e.StackTrace}"); switch (b) { case ErrorHelper.TaskDialogResult.ReloadApp: ReLoad(); break; case ErrorHelper.TaskDialogResult.Exit: NotifyIconHelper.HideNotifyIcon(); Environment.Exit(0); break; } //报错误但仍继续执行 }); thread.Start(); } } return(0); }
static void Main(string[] args) { IniConfig ini = new IniConfig("Config.ini"); ini.Load(); try { Save.curentQQ = ini.Object["Config"]["QQ"].GetValueOrDefault((long)0); Save.url = ini.Object["Config"]["url"].GetValueOrDefault("http://127.0.0.1:8888/"); } catch { ini.Clear(); ini.Object.Add(new ISection("Config")); ini.Object["Config"].Add("QQ", 0); ini.Object["Config"].Add("url", ""); long qq; while (true) { Console.Write("请输入目前服务端挂着的QQ号:"); if (long.TryParse(Console.ReadLine(), out qq)) { break; } } Save.curentQQ = qq; Console.Write("请输入用于连接服务端的url:"); string url = Console.ReadLine(); if (url.Reverse().First() != '/') { url += '/'; } ini.Object["Config"]["QQ"] = new IValue(qq); ini.Object["Config"]["url"] = new IValue(Save.url); ini.Save(); Console.WriteLine("需要修改请在目录下的Config.ini内修改"); } socket = new Client(Save.url); socket.Opened += SocketOpened; socket.Message += SocketMessage; socket.SocketConnectionClosed += SocketConnectionClosed; socket.Error += SocketError; string QQ = Save.curentQQ.ToString();//框架在线的QQ号 pluginManagment.Load(); LogHelper.WriteLine("遍历启动事件……"); pluginManagment.CallFunction("StartUp"); pluginManagment.CallFunction("Enable"); NotifyIconHelper.ShowNotifyIcon(); LogHelper.WriteLine("插件载入完成,开始连接服务器"); socket.Connect(); // register for 'connect' event with io server socket.On("connect", (fn) => { LogHelper.WriteLine(((ConnectMessage)fn).ConnectMsg.ToString()); //重连成功 取得 在线QQ的websocket 链接connid //Ack socket.Emit("GetWebConn", QQ, null, (callback) => { //var jsonMsg = callback as string; //LogHelper.WriteLine(string.Format("callback [root].[messageAck]: {0} \r\n", jsonMsg)); LogHelper.WriteLine($"服务器连接成功,开始处理事件……"); } ); //获取已登录QQ的群列表 //socket.Emit("GetGroupList", QQ); //获取已登录QQ的好友列表 //socket.Emit("GetQQUserList", QQ); //获取已登录QQ的群123456789成员列表 // //string JSON = "{" + string.Format("\"Uid\":\"{0}\",\"Group\":{1}", QQ, 123456789) + "}"; //socket.Emit("GetGroupUserList", JSON.Replace("\"", "\\\""));//json 需要处理一下转义 //获取登录二维码 socket.Emit("GetQrcode", "", null, (callback) => { var jsonMsg = callback as string; LogHelper.WriteLine(string.Format("GetQrcode From Websocket: {0} \r\n", jsonMsg)); } ); }); //二维码检测事件 socket.On("OnCheckLoginQrcode", (fn) => { LogHelper.WriteLine("OnCheckLoginQrcode\n" + ((JSONMessage)fn).MessageText); }); //收到群消息的回调事件 socket.On("OnGroupMsgs", (fn) => { //群文件合并到此事件 //{"FileID":"/9d784a08-d918-11ea-a715-5452007bdaa4","FileName":"Log.lua","FileSize":1159,"Tips":"[群文件]"} //语音消息 //{"Tips":"[语音]","Url":"http://grouptalk.c2c.qq.com/?ver=0\u0026rkey=3062020101045b30590201010201010204b40f1411042439306a33504b526d42394567685178716f6f464c4c67676639234e5f4a42535a7734764202045f2e03de041f0000000866696c6574797065000000013100000005636f64656300000001310400\u0026filetype=1\u0026voice_codec=1"} Task task = new Task(() => { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ReceiveMessage groupMessage = JsonConvert.DeserializeObject <ReceiveMessage>(((JSONMessage)fn).MessageText); string message = ProgressMessage.Start(groupMessage); ReceiveMessage.Data data = groupMessage.CurrentPacket.Data; if (groupMessage.CurrentPacket.Data.FromUserId == Save.curentQQ) { Dll.AddMsgToSave(new Deserizition.Message(Save.MsgList.Count + 1, data.MsgRandom, data.MsgSeq, data.FromGroupId, data.MsgTime, message)); return; } LogHelper.WriteLine(CQLogLevel.InfoReceive, "[↓]收到消息", $"来源群:{data.FromGroupId}({data.FromGroupName}) 来源QQ:{data.FromUserId}({data.FromNickName}) {message}"); var c = new Deserizition.Message(Save.MsgList.Count + 1, data.MsgRandom, data.MsgSeq, data.FromGroupId, data.MsgTime, message); Dll.AddMsgToSave(c); pluginManagment.CallFunction("GroupMsg", 2, Save.MsgList.Count + 1, data.FromGroupId, data.FromUserId, "", Marshal.StringToHGlobalAnsi(message), 0); stopwatch.Stop(); LogHelper.WriteLine($"耗时 {stopwatch.ElapsedMilliseconds} ms"); }); task.Start(); // new Event_GroupMessage().GroupMessage(new object(), e); }); //收到好友消息的回调事件 socket.On("OnFriendMsgs1", (fn) => { Task task = new Task(() => { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); ReceiveMessage groupMessage = JsonConvert.DeserializeObject <ReceiveMessage>(((JSONMessage)fn).MessageText); string message = ProgressMessage.Start(groupMessage); ReceiveMessage.Data data = groupMessage.CurrentPacket.Data; if (groupMessage.CurrentPacket.Data.FromUserId == Save.curentQQ) { Dll.AddMsgToSave(new Deserizition.Message(Save.MsgList.Count + 1, data.MsgRandom, data.MsgSeq, data.FromGroupId, data.MsgTime, message)); return; } LogHelper.WriteLine(CQLogLevel.InfoReceive, "[↓]收到消息", $"来源群:{data.FromGroupId}({data.FromGroupName}) 来源QQ:{data.FromUserId}({data.FromNickName}) {message}"); var c = new Deserizition.Message(Save.MsgList.Count + 1, data.MsgRandom, data.MsgSeq, data.FromGroupId, data.MsgTime, message); Dll.AddMsgToSave(c); pluginManagment.CallFunction("PrivateMsg", 11, Save.MsgList.Count + 1, data.FromUserId, Marshal.StringToHGlobalAnsi(message), 0); stopwatch.Stop(); LogHelper.WriteLine($"耗时 {stopwatch.ElapsedMilliseconds} ms"); }); task.Start(); }); //统一事件管理如好友进群事件 好友请求事件 退群等事件集合 socket.On("OnEvents", (fn) => { Task task = new Task(() => { JObject events = JObject.Parse(((JSONMessage)fn).MessageText); Requests request = new Requests(); switch (events["CurrentPacket"]["Data"]["EventName"].ToString()) { case "ON_EVENT_GROUP_JOIN": //入群事件 _eventSystem_GroupMemberIncrease id=7 long GroupJoin_JoinGroup, GroupJoin_JoinUin, GroupJoin_InviteUin; string GroupJoin_JoinUserName; JToken GroupJoin_data = events["CurrentPacket"]["Data"]["EventData"]; GroupJoin_JoinGroup = Convert.ToInt64(events["CurrentPacket"]["Data"]["EventMsg"]["FromUin"].ToString()); GroupJoin_JoinUin = Convert.ToInt64(GroupJoin_data["UserID"].ToString()); GroupJoin_JoinUserName = GroupJoin_data["UserName"].ToString(); GroupJoin_InviteUin = Convert.ToInt64(GroupJoin_data["InviteUin"].ToString()); if (GroupJoin_JoinUin != Save.curentQQ) { pluginManagment.CallFunction("GroupMemberIncrease", 1, GetTimeStamp(), GroupJoin_JoinGroup, 10000, GroupJoin_JoinUin); } LogHelper.WriteLine($"入群事件 群{GroupJoin_JoinGroup}加入{GroupJoin_JoinUserName}({GroupJoin_JoinUin})"); break; case "ON_EVENT_GROUP_EXIT": //退群事件 _eventSystem_GroupMemberDecrease id=6 long GroupExit_FromUin, GroupExit_UserID; JToken GroupExit_data = events["CurrentPacket"]["Data"]; GroupExit_FromUin = Convert.ToInt64(GroupExit_data["EventMsg"]["FromUin"].ToString()); GroupExit_UserID = Convert.ToInt64(GroupExit_data["EventData"]["UserID"].ToString()); pluginManagment.CallFunction("GroupMemberDecrease", 1, GetTimeStamp(), GroupExit_FromUin, 10000, GroupExit_UserID); LogHelper.WriteLine($"退群事件 {GroupExit_UserID}退出群{GroupExit_FromUin} "); break; case "ON_EVENT_GROUP_ADMIN": //群管变动事件 _eventSystem_GroupAdmin id=5 long GroupAdmin_GroupID, GroupAdmin_UserID, GroupAdmin_Flag; JToken GroupAdmin_data = events["CurrentPacket"]["Data"]["EventData"]; GroupAdmin_GroupID = Convert.ToInt64(GroupAdmin_data["GroupID"].ToString()); GroupAdmin_UserID = Convert.ToInt64(GroupAdmin_data["UserID"].ToString()); GroupAdmin_Flag = Convert.ToInt64(GroupAdmin_data["Flag"].ToString()); pluginManagment.CallFunction("AdminChange", 1, GetTimeStamp(), GroupAdmin_GroupID, GroupAdmin_UserID); LogHelper.WriteLine($"群管理员变动事件 {GroupAdmin_UserID}{(GroupAdmin_Flag == 1 ? "升为" : "消去")}群{GroupAdmin_GroupID}的管理员"); break; case "ON_EVENT_GROUP_ADMINSYSNOTIFY": //加群请求事件 _eventRequest_AddGroup id=12 request.type = "GroupRequest"; request.json = ((JSONMessage)fn).MessageText; Dll.AddRequestToSave(request); long GroupRequest_GroupId, GroupRequest_InviteUin, GroupRequest_Who; string GroupRequest_WhoName, GroupRequest_GroupName, GroupRequest_InviteName; JToken GroupRequest_extdata = events["CurrentPacket"]["Data"]["EventData"]; GroupRequest_GroupId = Convert.ToInt64(GroupRequest_extdata["GroupId"].ToString()); GroupRequest_InviteUin = Convert.ToInt64(GroupRequest_extdata["InviteUin"].ToString()); GroupRequest_Who = Convert.ToInt64(GroupRequest_extdata["Who"].ToString()); GroupRequest_WhoName = GroupRequest_extdata["WhoName"].ToString(); GroupRequest_GroupName = GroupRequest_extdata["GroupName"].ToString(); GroupRequest_InviteName = GroupRequest_extdata["InviteName"].ToString(); pluginManagment.CallFunction("GroupAddRequest", 1, GetTimeStamp(), GroupRequest_GroupId, GroupRequest_Who, Marshal.StringToHGlobalAnsi(""), ""); LogHelper.WriteLine($"加群请求事件 {GroupRequest_WhoName}({GroupRequest_Who})" + $" {(GroupRequest_InviteUin != 0 ? $"受{GroupRequest_InviteName}({GroupRequest_InviteUin})邀请" : "")}" + $"加入群{GroupRequest_GroupName}({GroupRequest_GroupId})"); break; case "ON_EVENT_FRIEND_ADD": //好友请求事件 _eventRequest_AddFriend id=11 request.type = "FriendRequest"; request.json = ((JSONMessage)fn).MessageText; Dll.AddRequestToSave(request); string FriendRequest_Content; long FriendRequest_UserID; JToken FriendRequest_data = events["CurrentPacket"]["Data"]["EventData"]; FriendRequest_Content = FriendRequest_data["Content"].ToString(); FriendRequest_UserID = Convert.ToInt64(FriendRequest_data["UserID"].ToString()); pluginManagment.CallFunction("FriendRequest", 1, GetTimeStamp(), FriendRequest_UserID, Marshal.StringToHGlobalAnsi(FriendRequest_Content), ""); LogHelper.WriteLine($"好友请求事件 QQ号:{FriendRequest_UserID} 验证信息:{FriendRequest_Content}"); break; case "ON_EVENT_NOTIFY_PUSHADDFRD": //好友添加完成事件 _eventFriend_Add id=10 long FriendAdded_UserID; JToken FriendAdded_data = events["CurrentPacket"]["Data"]["EventData"]; FriendAdded_UserID = Convert.ToInt64(FriendAdded_data["UserID"].ToString()); pluginManagment.CallFunction("FriendAdded", 1, GetTimeStamp(), FriendAdded_UserID); LogHelper.WriteLine($"好友添加完成事件 与{FriendAdded_UserID}成为了好友"); break; case "ON_EVENT_GROUP_SHUT": //群禁言事件 _eventSystem_GroupBan id=8 long GroupShut_groupid, GroupShut_qqid, GroupShut_shuttime; JToken GroupShut_data = events["CurrentPacket"]["Data"]["EventData"]; GroupShut_groupid = Convert.ToInt64(GroupShut_data["GroupID"].ToString()); GroupShut_qqid = Convert.ToInt64(GroupShut_data["UserID"].ToString()); GroupShut_shuttime = Convert.ToInt64(GroupShut_data["ShutTime"].ToString()); pluginManagment.CallFunction("GroupBan", (GroupShut_shuttime == 0 ? 1 : 2), GetTimeStamp(), GroupShut_groupid, 0, GroupShut_qqid); LogHelper.WriteLine($"群 {GroupShut_groupid} UserID {GroupShut_qqid} 禁言时间 {GroupShut_shuttime}秒"); break; } }); task.Start(); }); // make the socket.io connection while (true) { Thread.Sleep(100); Application.DoEvents(); } }
/// <summary> /// 以绝对路径路径载入拥有同名json的dll插件 /// </summary> /// <param name="filepath">插件dll的绝对路径</param> /// <returns>载入是否成功</returns> public bool Load(string filepath) { FileInfo plugininfo = new FileInfo(filepath); if (!File.Exists(plugininfo.FullName.Replace(".dll", ".json"))) { LogHelper.WriteLog(LogLevel.Error, "插件载入", $"插件 {plugininfo.Name} 加载失败,原因:缺少json文件"); return(false); } JObject json = JObject.Parse(File.ReadAllText(plugininfo.FullName.Replace(".dll", ".json"))); int authcode = new Random().Next(); Dll dll = new Dll(); if (!Directory.Exists(@"data\tmp")) { Directory.CreateDirectory(@"data\tmp"); } //复制需要载入的插件至临时文件夹,可直接覆盖原dll便于插件重载 string destpath = @"data\tmp\" + plugininfo.Name; File.Copy(plugininfo.FullName, destpath, true); //复制它的json File.Copy(plugininfo.FullName.Replace(".dll", ".json"), destpath.Replace(".dll", ".json"), true); IntPtr iLib = dll.Load(destpath, json);//将dll插件LoadLibrary,并进行函数委托的实例化; AppDomainSetup ads = new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory, DisallowBindingRedirects = false, DisallowCodeDownload = true, ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile }; AppDomain newappDomain = AppDomain.CreateDomain(iLib.ToString(), null, ads); AppDomainSave.Add(iLib, newappDomain); Proxy.Init(iLib, json); if (iLib == (IntPtr)0) { LogHelper.WriteLog(LogLevel.Error, "插件载入", $"插件 {plugininfo.Name} 加载失败,返回句柄为空,GetLastError={Dll.GetLastError()}"); } //执行插件的init,分配一个authcode dll.DoInitialize(authcode); //获取插件的appinfo,返回示例 9,me.cqp.luohuaming.Sign,分别为ApiVer以及AppID KeyValuePair <int, string> appInfotext = dll.GetAppInfo(); AppInfo appInfo = new AppInfo(appInfotext.Value, 0, appInfotext.Key , json["name"].ToString(), json["version"].ToString(), Convert.ToInt32(json["version_id"].ToString()) , json["author"].ToString(), json["description"].ToString(), authcode); bool enabled = GetPluginState(appInfo);//获取插件启用状态 //保存至插件列表 Plugin plugin = (Plugin)newappDomain.CreateInstanceAndUnwrap(typeof(Plugin).Assembly.FullName , typeof(Plugin).FullName , false , BindingFlags.CreateInstance , null , new object[] { iLib, appInfo, json.ToString(), dll, enabled, appInfotext.Value } , null, null); Plugins.Add(plugin); LogHelper.WriteLog(LogLevel.InfoSuccess, "插件载入", $"插件 {appInfo.Name} 加载成功"); cq_start(Marshal.StringToHGlobalAnsi(destpath), authcode); //将它的窗口写入托盘右键菜单 NotifyIconHelper.LoadMenu(json); return(true); }