private async Task HandleAllianceSearchRequest(IClient client, Message message, CancellationToken cancellationToken)
        {
            var asrMessage = (AllianceSearchRequestMessage)message;
            var level      = client.Session.Level;

            var clans  = new List <ClanCompleteMessageComponent>();
            var search = new ClanQuery
            {
                TextSearch     = asrMessage.TextSearch,
                WarFrequency   = asrMessage.WarFrequency == 0 ? (int?)null : asrMessage.WarFrequency,
                ClanLocation   = asrMessage.ClanLocation == 0 ? (int?)null : asrMessage.ClanLocation,
                MinimumMembers = asrMessage.MinimumMembers,
                MaximumMembers = asrMessage.MaximumMembers,
                PerkPoints     = asrMessage.TrophyLimit,
                OnlyCanJoin    = asrMessage.OnlyCanJoin,
                ExpLevels      = asrMessage.ExpLevels
            };

            var searchClans = await Server.Db.SearchClansAsync(level, search, cancellationToken);

            if (searchClans != null)
            {
                foreach (var c in searchClans)
                {
                    var clan = c.ToClan();
                    clans.Add(new ClanCompleteMessageComponent(clan));
                }
            }

            var asrrMessage = new AllianceSearchResponseMessage
            {
                TextSearch = asrMessage.TextSearch,
                Clans      = clans.ToArray()
            };

            client.SendMessage(asrrMessage);
        }
        public async Task <IEnumerable <ClanSave> > SearchClansAsync(Level level, ClanQuery search, CancellationToken cancellationToken)
        {
            using (var sql = new MySqlConnection(_connectionString))
            {
                await sql.OpenAsync();

                // Look for clan IDs with the basic criteria.
                var clanIds    = new List <long>(64);
                var commandTxt = "SELECT `clan_id` FROM `clans` WHERE `invite_type` < 3 AND name LIKE @TextSearch AND `perk_points` <= @PerkPoints AND `exp_levels` <= @ExpLevels";
                using (var command = new MySqlCommand(commandTxt, sql))
                {
                    command.Parameters.AddWithValue("TextSearch", search.TextSearch + '%');
                    command.Parameters.AddWithValue("PerkPoints", search.PerkPoints);
                    command.Parameters.AddWithValue("ExpLevels", search.ExpLevels);
                    if (search.ClanLocation != null)
                    {
                        command.CommandText += " AND `location` = @ClanLocation";
                        command.Parameters.AddWithValue("ClanLocation", search.ClanLocation);
                    }

                    if (search.WarFrequency != null)
                    {
                        command.CommandText += " AND `war_frequency` = @WarFrequency";
                        command.Parameters.AddWithValue("WarFrequency", search.WarFrequency);
                    }

                    if (search.OnlyCanJoin)
                    {
                        command.CommandText += " AND `required_trophies` <= @Trophies";
                        command.Parameters.AddWithValue("Trophies", search.PerkPoints);
                    }

                    // Select 64 random clans.
                    command.CommandText += " LIMIT 64";

                    using (var reader = await command.ExecuteReaderAsync(CommandBehavior.KeyInfo, cancellationToken))
                    {
                        while (await reader.ReadAsync())
                        {
                            clanIds.Add((long)reader[0]);
                        }
                    }
                }

                if (clanIds.Count > 0)
                {
                    var clans        = new List <ClanSave>();
                    var clanToDelete = new List <long>(clanIds.Count);
                    var clanToLoad   = new List <long>(clanIds.Count);

                    // Load up the clan member count in the db.
                    for (int i = 0; i < clanIds.Count; i++)
                    {
                        using (var command = new MySqlCommand("SELECT COUNT(`clan_id`) FROM `clan_members` WHERE `clan_id` = @ClanId", sql))
                        {
                            command.Parameters.AddWithValue("ClanId", clanIds[i]);

                            using (var reader = await command.ExecuteReaderAsync(cancellationToken))
                            {
                                if (await reader.ReadAsync())
                                {
                                    var count = (long)reader[0];
                                    // If clan is completely full the user can't join it.
                                    if (count >= 50 && search.OnlyCanJoin)
                                    {
                                        continue;
                                    }

                                    // Mark the clan for deletion if it has no clan members.
                                    if (count == 0)
                                    {
                                        clanToDelete.Add(clanIds[i]);
                                    }
                                    else if (count >= search.MinimumMembers && count <= search.MaximumMembers)
                                    {
                                        clanToLoad.Add(clanIds[i]);
                                    }
                                }
                            }
                        }
                    }

                    for (int i = 0; i < clanToLoad.Count; i++)
                    {
                        cancellationToken.ThrowIfCancellationRequested();

                        var clanId = clanToLoad[i];
                        var clan   = await LoadClanAsync(clanId, cancellationToken);

                        clans.Add(clan);
                    }

                    return(clans);
                }
                return(null);
            }
        }