Example #1
0
        private async static System.Threading.Tasks.Task <bool> Session_DisconnectedEvt(IMiraiHttpSession sender, Exception e)
        {
            logger("Connection", e.Message);
            while (true)
            {
                try
                {
                    logger("Connection", "Reconnecting...");
                    MiraiHttpSessionOptions options = new MiraiHttpSessionOptions(host, port, key);
                    await sender.ConnectAsync(me_qq);

                    if (!e.Message.Contains("未知的消息类型"))
                    {
                        MainHolder.broadcaster.BroadcastToAdminGroup("[断线重连]\n诊断报告:" + e.Message + "\n" + e.StackTrace);
                    }
                    break;
                }
                catch (Exception err)
                {
                    logger("Connection", err.Message);
                    await Task.Delay(1000);
                }
            }
            return(false);
        }
        private async Task <IMiraiHttpSession> InternalRetriveSessionAsync(long robotQQ, CancellationToken token)
        {
            try
            {
                if (_robotScopes.TryGetValue(robotQQ, out IServiceScope? dualcheck))
                {
                    return(dualcheck.ServiceProvider.GetRequiredService <IMiraiHttpSession>());
                }
                IServiceScope scope = _services.CreateScope();
                try
                {
                    IMiraiHttpSession session = scope.ServiceProvider.GetRequiredService <IMiraiHttpSession>();
                    await session.ConnectAsync(robotQQ, token).ConfigureAwait(false);

                    _robotScopes[robotQQ] = scope;
                    return(session);
                }
                catch
                {
                    scope.Dispose();
                    throw;
                }
            }
            finally
            {
                _robotInitTasks.TryRemove(robotQQ, out _);
            }
        }
Example #3
0
        public static async Task Main()
        {
            // 一套能用的框架, 必须要注册至少一个 Invoker, Parser, Client 和 Handler
            // Invoker 负责消息调度
            // Parser 负责解析消息到具体接口以便调度器调用相关 Handler 下的处理方法
            // Client 负责收发原始数据
            IServiceProvider services = new ServiceCollection().AddMiraiBaseFramework() // 表示使用基于基础框架的构建器
                                        .AddHandler <MiraiPlugin>()                     // 虽然可以把 HttpApiPlugin 作为泛型参数塞入, 但不建议这么做
                                        .Services
                                        .AddDefaultMiraiHttpFramework()                 // 表示使用 mirai-api-http 实现的构建器
                                        .ResolveParser <DynamicPlugin>()                // 只提前解析 DynamicPlugin 将要用到的消息解析器
                                        .AddInvoker <MiraiHttpMessageHandlerInvoker>()  // 使用默认的调度器
                                        .AddHandler <HttpApiPlugin>()                   // 可以如此添加更多消息处理器
                                        .AddClient <MiraiHttpSession>()                 // 使用默认的客户端
                                        .Services
                                                                                        // 由于 MiraiHttpSession 使用 IOptions<MiraiHttpSessionOptions>, 其作为 Singleton 被注册
                                                                                        // 配置此项将配置基于此 IServiceProvider 全局的连接配置
                                                                                        // 如果你想一个作用域一个配置的话
                                                                                        // 自行做一个实现类, 继承MiraiHttpSession, 构造参数中使用 IOptionsSnapshot<MiraiHttpSessionOptions>
                                                                                        // 并将其传递给父类的构造参数
                                                                                        // 然后在每一个作用域中!先!配置好 IOptionsSnapshot<MiraiHttpSessionOptions>, 再尝试获取 IMiraiHttpSession
                                        .Configure <MiraiHttpSessionOptions>(options =>
            {
                options.Host    = "域名/IP";
                options.Port    = 12345;                                                 // 端口
                options.AuthKey = "00000000000000000000000000000000";                    // 凭据
            })
                                        .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>(); // 大部分服务都基于接口注册, 请使用接口作为类型解析
            DynamicPlugin      plugin       = new DynamicPlugin();
            PluginResistration resistration = session.AddPlugin(plugin);                         // 实时添加
            await session.ConnectAsync(0);                                                       // 填入期望连接到的机器人QQ号

            while (true)
            {
                if (Console.ReadLine() == "exit")
                {
                    resistration.Dispose(); // 实时移除
                    break;
                }
            }
        }
Example #4
0
        public async Task HandleMessageAsync(IMiraiHttpSession session, IDisconnectedEventArgs e)
        {
            // e.Exception: 引发掉线的响应异常, 按需处理
            while (true)
            {
                try
                {
                    await session.ConnectAsync(e.LastConnectedQQNumber);

                    e.BlockRemainingHandlers = true;
                    break;
                }
                catch (ObjectDisposedException) // session 已被释放
                {
                    break;
                }
                catch (Exception)
                {
                    await Task.Delay(1000);
                }
            }
        }
        public async Task HandleMessageAsync(IMiraiHttpSession session, IDisconnectedEventArgs message)
        {
            _logger.LogWarning(message.Exception, $"连接被断开。上一次连接的QQ号为:{message.LastConnectedQQNumber}");
            while (!session.Connected) // 防止以前的handler未能正确阻断消息传递
            {
                try
                {
                    await session.ConnectAsync(message.LastConnectedQQNumber);

                    message.BlockRemainingHandlers = true;
                    _logger.LogInformation($"重连成功");
                    break;
                }
                catch (ObjectDisposedException)
                {
                    break;
                }
                catch (Exception e)
                {
                    _logger.LogError(e, $"重连失败。上一次连接的QQ号为:{message.LastConnectedQQNumber}");
                    await Task.Delay(1000);
                }
            }
        }
Example #6
0
        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();
                }
            }
        }
Example #7
0
 public async Task HandleMessageAsync(IMiraiHttpSession client, IDisconnectedEventArgs message)
 {
     _logger.Error("disconnected, reconnecting");
     await client.ConnectAsync(client.QQNumber.Value);
 }
Example #8
0
        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);
            }
        }
Example #9
0
        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;
                }
            }
        }