private static void CheckClient(object sender, ClientIdT clid)
        {
            var        cl    = (Ts3FullClient)sender;
            ClientUidT cluid = Clientlib.ClientGetUidFromClid(cl, clid);

            Console.WriteLine($"clid={clid} cluid={cluid}");
            if (done.Contains(cluid))
            {
                return;
            }
            var dbid   = uint.Parse(cl.Send("clientgetdbidfromuid", new CommandParameter("cluid", cluid)).FirstOrDefault()["cldbid"]);
            var friend = TSSettings.isFriend(cluid);

            Console.WriteLine($"#{clid} dbid={dbid} cluid={cluid} friend={friend}");
            switch (friend)
            {
            case FriendStatus.Blocked:
                Clientlib.SetAllChannelGroup(cl, banCGID, dbid, cids);
                break;

            case FriendStatus.Friend:
                Clientlib.SetAllChannelGroup(cl, modCGID, dbid, cids);
                break;

            default:
                break;
            }
            done.Add(cluid);
        }
        private static void CheckGroups(Ts3FullClient client)
        {
            var response = Clientlib.GetAllChannelGroups(client);

            foreach (ChannelGroupListResponse gCLR in response)
            {
                if (gCLR.type == PermissionGroupDatabaseType.Regular)
                {
                    foreach (string name in admin_names)
                    {
                        if (gCLR.cgName.ToString().ToLower().Contains(name.ToLower()))
                        {
                            adminCGID = gCLR.cgID; continue;
                        }
                    }
                    foreach (string name in mod_names)
                    {
                        if (gCLR.cgName.ToString().ToLower().Contains(name.ToLower()))
                        {
                            modCGID = gCLR.cgID; continue;
                        }
                    }
                    foreach (string name in banned_names)
                    {
                        if (gCLR.cgName.ToString().ToLower().Contains(name.ToLower()))
                        {
                            banCGID = gCLR.cgID; continue;
                        }
                    }
                }
            }
        }
        private static void OnClientMoved(object sender, IEnumerable <ClientMoved> e)
        {
            var ownClient = (Ts3FullClient)sender;

            foreach (var client in e)
            {
                locked = true;
                if (client.InvokerUid == ownerUID)
                {
                    continue;
                }
                if (client.Reason == MoveReason.UserAction && Clientlib.GetMyChannelID(ownClient) == client.TargetChannelId)
                {
                    //Console.WriteLine($"#{client.ClientId} {String.Join(",", cids)}.Contains({client.TargetChannelId}) = {cids.Contains(client.TargetChannelId)}");
                    if (cids.Contains(client.TargetChannelId))
                    {
                        CheckClient((Ts3FullClient)sender, client.ClientId);
                    }
                }
                //Console.WriteLine($"ClientId={client.ClientId} InvokerId={client.InvokerId}  InvokerName={client.InvokerName}  InvokerUid={client.InvokerUid}  NotifyType={client.NotifyType}  Reason={client.Reason} TargetChannelId={client.TargetChannelId}");
            }
            if (locked)
            {
                locked = false;
            }
        }
        private static void OnConnected(object sender, EventArgs e)
        {
            try {
                int myId   = Interlocked.Increment(ref cnt);
                var client = (Ts3FullClient)sender;
                if (myId == 0)
                {
                    CheckGroups(client);
                }
                Console.WriteLine("Connected id={0} clid={1}", myId, client.ClientId);
                var channel = channels[myId].Split(',');

                /*var response = client.Send("channellist");
                 * var channel_name_in_use = false;
                 * foreach (var chan in response) {
                 *      if (chan["channel_name"] == channel[0])
                 *              channel_name_in_use = true; break;
                 * }*/
                ulong cid = 0;

                /*if (channel_name_in_use) {
                 * } else {*/
                try {
                    cid = Clientlib.ChannelCreate(client, channel[0], channel[1], channel[2], channel[3]).ChannelId;
                } catch (Ts3CommandException err) {
                    if (err.ErrorStatus.Id == Ts3ErrorCode.channel_name_inuse)
                    {
                        cid = Clientlib.ChannelCreate(client, channel[0] + "_", channel[1], channel[2], channel[3]).ChannelId;
                    }
                    Console.WriteLine("Error while creating channel " + channel[0] + " " + err.ErrorStatus + "\n" + err.Message);
                }
                cids.Add(cid);
                ownerDBID = uint.Parse(client.Send("clientgetdbidfromuid", new CommandParameter("cluid", ownerUID)).FirstOrDefault()["cldbid"]);
                try {
                    Clientlib.SetClientChannelGroup(client, modCGID, cid, ownerDBID);
                } catch (Ts3CommandException err) {
                    Console.WriteLine("Error while setting channelgroup " + channel[0] + " " + err.ErrorStatus + "\n" + err.Message);
                    return;
                }
                client.Send("clientupdate",
                            new CommandParameter("client_badges", "badges=c9e97536-5a2d-4c8e-a135-af404587a472")
                            );
            } catch (Exception ex) {
                Console.WriteLine($"Catched exception in OnConnected:\n{ex}");
            }
        }
        static void Main()
        {
            AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
            clients  = new List <Ts3FullClient>();
            channels = File.ReadAllLines(chanfile);
            var parser = new FileIniDataParser();

            cfg = parser.ReadFile(cfgfile);
            RandomNick rndnick = new RandomNick();

            rndnick.Init();
            TSSettings.OpenDB();
            Console.CancelKeyPress += (s, e) => {
                if (e.SpecialKey == ConsoleSpecialKey.ControlC)
                {
                    e.Cancel = true;
                    Dispose();
                    Environment.Exit(0);
                }
            };
            con.Address  = cfg["general"]["Address"];
            con.Password = cfg["general"]["ServerPassword"];
            ownerUID     = cfg["general"]["OwnerUID"];

            /*
             * adminCGID = uint.Parse(cfg["general"]["adminCGID"]);
             * modCGID = uint.Parse(cfg["general"]["modCGID"]);
             * banCGID = uint.Parse(cfg["general"]["banCGID"]);
             */
            if (!File.Exists(idfile))
            {
                using (File.Create(idfile)) { }
            }
            ids = File.ReadAllLines(idfile);
            for (int i = 0; i < channels.Length; i++)
            {
                if (isExit)
                {
                    return;
                }
                con.Username = rndnick.GetRandomNick();                 //cfg["general"]["Nickname"];
                var client = new Ts3FullClient(EventDispatchType.DoubleThread);
                client.OnConnected           += OnConnected;
                client.OnDisconnected        += OnDisconnected;
                client.OnErrorEvent          += OnErrorEvent;
                client.OnTextMessageReceived += OnTextMessageReceived;
                client.OnClientMoved         += OnClientMoved;
                client.OnClientEnterView     += OnClientEnterView;
                var          _identity = ids.Select(x => x.Split(',')).ToList();
                IdentityData ID;
                try {
                    ID = Ts3Crypt.LoadIdentity(_identity[i][0], ulong.Parse(_identity[i][1]));
                    if (i > 0)
                    {
                        Thread.Sleep(int.Parse(cfg["general"]["ConnectSleepMS"]));
                    }
                } catch (Exception) {
                    ID = Ts3Crypt.GenerateNewIdentity(int.Parse(cfg["general"]["MinLVL"]));
                    File.AppendAllText(idfile, ID.PrivateKeyString + "," + ID.ValidKeyOffset + "\r\n");
                }
                Console.WriteLine("#" + i + " UID: " + ID.ClientUid);
                con.Identity = ID;
                //Array values = Enum.GetValues(typeof(VersionSign));
                //Random random = new Random();
                //con.VersionSign = (VersionSign)values.GetValue(random.Next(values.Length));
                //var t = typeof(VersionSign).GetFields();
                con.VersionSign = VersionSign.VER_WIN_3_UNKNOWN;
                //con.VersionSign = new VersionSign("YaTQA-3.9pre [Build: 32503680000]", "ServerQuery", String.Empty);
                con.HWID = $"{Clientlib.RandomString(32)},{Clientlib.RandomString(32)}";
                Console.WriteLine("#" + i + " HWID: " + con.HWID);
                client.Connect(con);
                clients.Add(client);
            }
            AntiAFK = new Timer(OnTick, "on", 114 * 10000, 114 * 10000);
            Console.WriteLine("End");
            Console.ReadLine();
            Dispose();
        }