public string GetVPHAPIDelivery(string OrderId, string LogisticsCode, string Waybill, XMOrderInfoApp xMorderInfoApp, string LogisticsName)
        {
            try
            {
                string AppKey      = xMorderInfoApp.AppKey;
                string AppSecret   = xMorderInfoApp.AppSecret;
                string CallbackUrl = xMorderInfoApp.CallbackUrl;//"http://www.hozest.com";
                string AccessToken = xMorderInfoApp.AccessToken;
                string posturl     = xMorderInfoApp.ServerUrl;

                DvdDeliveryServiceHelper.DvdDeliveryServiceClient client = new DvdDeliveryServiceHelper.DvdDeliveryServiceClient();
                InvocationContext invocationContext = Factory.GetInstance();
                invocationContext.SetAppKey(AppKey);
                invocationContext.SetAppSecret(AppSecret);
                invocationContext.SetAppURL(posturl);

                List <PackageProduct> packageProduct_list = new List <PackageProduct>();
                PackageProduct        packageProduct      = new PackageProduct();
                packageProduct.SetBarcode("");
                packageProduct.SetAmount(1);
                packageProduct_list.Add(packageProduct);

                List <Package> package_list = new List <Package>();
                Package        package      = new Package();
                package.SetTransport_no(Waybill);
                package.SetPackage_product_list(packageProduct_list);
                package_list.Add(package);

                List <Ship> ship_list = new List <Ship>();
                Ship        ship      = new Ship();
                ship.SetOrder_id(OrderId);
                ship.SetCarrier_code(LogisticsCode);
                ship.SetCarrier_name(LogisticsName);
                ship.SetPackage_type("1");
                ship.SetPackages(package_list);
                ship_list.Add(ship);

                ShipResult rsp = client.ship(6480, ship_list);

                if (rsp != null)
                {
                    if (rsp.GetSuccess_num() > 0 && rsp.GetFail_num() == 0)
                    {
                        return(rsp.GetSuccess_num().ToString());
                    }
                    else
                    {
                        return(null);
                    }
                }
            }
            catch (Exception ex)
            {
                IoC.Resolve <IRecordErrorLogs>().WriteErrorLog("负责人:" + HozestERPContext.Current.User.CustomerID.ToString() + ";   方法名:GetVPHAPIDelivery;  异常提示:" + ex.Message.ToString() + ";   InnerException:" + ex.InnerException);
            }
            return(null);
        }
Example #2
0
        public async Task ProcessWhoCommand(ICommandContext context, string commandText)
        {
            if (_isWhoRunning)
            {
                await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("capsCommandRunning"));

                return;
            }

            if (!File.Exists(SettingsManager.FileShipsData))
            {
                if (!File.Exists(SettingsManager.FileShipsDataDefault))
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("errFileNotFound", SettingsManager.FileShipsData));

                    return;
                }
                File.Copy(SettingsManager.FileShipsDataDefault, SettingsManager.FileShipsData);
            }

            if (context.User.IsBot || string.IsNullOrEmpty(commandText))
            {
                return;
            }
            try
            {
                _isWhoRunning = true;
                var parts   = commandText.Split(' ');
                var command = parts[0];
                var mod     = parts.Length > 1 ? parts[1] : null;

                if ((!command.Equals("who", StringComparison.OrdinalIgnoreCase) && !command.Equals("all", StringComparison.OrdinalIgnoreCase) || (mod != null && !mod.Equals("online", StringComparison.OrdinalIgnoreCase) &&
                                                                                                                                                  !mod.Equals("o", StringComparison.OrdinalIgnoreCase))))
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("helpCaps", SettingsManager.Settings.Config.BotDiscordCommandPrefix, "caps"));

                    return;
                }

                var isAll        = command.Equals("all", StringComparison.OrdinalIgnoreCase);
                var isOnlineOnly = mod != null && (mod.Equals("online", StringComparison.OrdinalIgnoreCase) || mod.Equals("o", StringComparison.OrdinalIgnoreCase));


                var usersToCheck = new List <AuthUserEntity>();
                if (!isAll)
                {
                    foreach (var user in APIHelper.DiscordAPI.GetUsers(context.Channel.Id, isOnlineOnly))
                    {
                        var item = await SQLHelper.GetAuthUserByDiscordId(user.Id);

                        if (item != null && !string.IsNullOrEmpty(item.Data.Permissions) && SettingsManager.HasCharSkillsScope(item.Data.PermissionsList))
                        {
                            usersToCheck.Add(item);
                        }
                    }
                }
                else
                {
                    if (isOnlineOnly)
                    {
                        var dusers = APIHelper.DiscordAPI.GetUsers(0, true).Select(a => a.Id);
                        usersToCheck = (await SQLHelper.GetAuthUsers((int)UserStatusEnum.Authed)).Where(item => dusers.Contains(item.DiscordId) &&
                                                                                                        !string.IsNullOrEmpty(item.Data.Permissions) && SettingsManager.HasCharSkillsScope(item.Data.PermissionsList))
                                       .ToList();
                    }
                    else
                    {
                        usersToCheck = (await SQLHelper.GetAuthUsers((int)UserStatusEnum.Authed)).Where(item =>
                                                                                                        !string.IsNullOrEmpty(item.Data.Permissions) && SettingsManager.HasCharSkillsScope(item.Data.PermissionsList))
                                       .ToList();
                    }
                }

                if (!usersToCheck.Any())
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("capsNoUsersFound"));

                    return;
                }

                var data = JsonConvert.DeserializeObject <ShipsData>(File.ReadAllText(SettingsManager.FileShipsData));
                if (data == null)
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("errFileContainsInvalidData"));

                    return;
                }

                var dataDic = new Dictionary <string, List <ShipResult> >();
                var counts  = new Dictionary <string, int>();

                var usersData = new ConcurrentBag <ShipUserData>();
                await usersToCheck.ParallelForEachAsync(async userEntity =>
                {
                    var token = await APIHelper.ESIAPI.RefreshToken(userEntity.RefreshToken, SettingsManager.Settings.WebServerModule.CcpAppClientId,
                                                                    SettingsManager.Settings.WebServerModule.CcpAppSecret);
                    if (token == null)
                    {
                        await LogHelper.LogWarning($"Character {userEntity.Data.CharacterName}({userEntity.CharacterId}) has invalid token!");
                        return;
                    }
                    var skills = await APIHelper.ESIAPI.GetCharSkills(Reason, userEntity.CharacterId, token);
                    if (skills?.skills == null || skills.skills.Count == 0)
                    {
                        return;
                    }
                    usersData.Add(new ShipUserData
                    {
                        User   = userEntity,
                        Skills = skills
                    });
                }, 8);

                foreach (var pair in data.Groups)
                {
                    var groupName = pair.Key;
                    var group     = pair.Value;
                    counts.Add(groupName, 0);
                    dataDic.Add(groupName, new List <ShipResult>());

                    var shCountDic = new Dictionary <string, int>();
                    foreach (var skill in @group.ShipSkills)
                    {
                        shCountDic.Add(skill.Key, 0);
                    }

                    var useSiege  = group.FormatTemplate.Contains("{ST1}");
                    var useWeapon = group.FormatTemplate.Contains("{ST2}");


                    foreach (var user in usersData.Where(user => group.CommonSkills.All(skill =>
                    {
                        var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                        if (s == null)
                        {
                            return(false);
                        }
                        return(s.trained_skill_level >= skill.Minumim);
                    })))
                    {
                        var st1 = !useSiege ? null : (group.CommonSkills.Where(a => a.SkillType == SkillType.Siege).All(skill =>
                        {
                            var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                            if (s == null)
                            {
                                return(false);
                            }
                            return(s.trained_skill_level >= skill.T2);
                        })
                            ? "T2"
                            : "T1");

                        var userCounted = false;
                        foreach (var valuePair in @group.ShipSkills)
                        {
                            var shipName   = valuePair.Key;
                            var shipSkills = valuePair.Value;

                            var canDrive = shipSkills.All(skill =>
                            {
                                var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                                if (s == null)
                                {
                                    return(false);
                                }
                                if (skill.SkillType == SkillType.Weapon && skill.T2 > 0)
                                {
                                    return(true);
                                }
                                return(s.trained_skill_level >= skill.Minumim);
                            });
                            if (!canDrive)
                            {
                                continue;
                            }

                            var st2 = !useWeapon ? null : (shipSkills.Where(a => a.SkillType == SkillType.Weapon).Any(skill =>
                            {
                                var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                                if (s == null)
                                {
                                    return(false);
                                }
                                return(s.trained_skill_level >= skill.T2);
                            })
                                ? "T2"
                                : "T1");
                            if (!userCounted)
                            {
                                counts[groupName] = counts[groupName] + 1;
                                userCounted       = true;
                            }

                            var tmplt = group.FormatTemplate.Replace("{NAME}", user.User.Data.CharacterName)
                                        .Replace("{ST1}", st1)
                                        .Replace("{ST2}", st2);
                            for (int i = 1; i < 99; i++)
                            {
                                if (!tmplt.Contains($"{{SP{i}}}"))
                                {
                                    break;
                                }
                                var spId  = group.SpecialCounters.Values.ToList()[i - 1].Id;
                                var value = user.Skills.skills.FirstOrDefault(a => a.skill_id == spId)?.trained_skill_level ?? 0;
                                tmplt = tmplt.Replace($"{{SP{i}}}", value.ToString());
                            }
                            var result = new ShipResult
                            {
                                Name = shipName,
                                Text = tmplt
                            };
                            var sd = dataDic[groupName].FirstOrDefault(a => a.Name == result.Name);
                            if (sd != null)
                            {
                                sd.Text += $", {result.Text}";
                            }
                            else
                            {
                                dataDic[groupName].Add(result);
                            }
                            shCountDic[shipName] = shCountDic[shipName] + 1;
                        }
                    }

                    foreach (var counter in @group.SpecialCounters.Where(a => a.Value.IsVisible))
                    {
                        counter.Value.Count = usersData.Count(user =>
                                                              user.Skills.skills.FirstOrDefault(a => a.skill_id == counter.Value.Id && a.trained_skill_level >= counter.Value.Rank) != null);
                    }

                    //add empty ships
                    foreach (var valuePair in shCountDic.Where(a => a.Value == 0))
                    {
                        dataDic[groupName].Add(new ShipResult
                        {
                            Name = valuePair.Key,
                            Text = LM.Get("None")
                        });
                    }
                }

                var sb = new StringBuilder();
                foreach (var pair in dataDic)
                {
                    sb.AppendLine($"**{pair.Key}** ({counts[pair.Key]} {LM.Get("of")} {usersData.Count})");
                    sb.AppendLine($"*Format: {data.Groups[pair.Key].FormatDescription}*");
                    sb.AppendLine($"```");
                    var maxNameLen = pair.Value.GroupBy(a => a.Name).Max(a => a.Key.Length);

                    foreach (var group in pair.Value.GroupBy(a => a.Name))
                    {
                        var text = string.Join(", ", group.Select(a => a.Text));
                        sb.AppendLine($"{group.Key.FixedLength(maxNameLen)} - {(string.IsNullOrEmpty(text) ? LM.Get("None") : text)}");
                    }

                    if (data.Groups[pair.Key].SpecialCounters.Any(a => a.Value.IsVisible))
                    {
                        sb.AppendLine($"");
                        sb.AppendLine($"Specials");
                    }

                    foreach (var counter in data.Groups[pair.Key].SpecialCounters.Where(a => a.Value.IsVisible))
                    {
                        sb.AppendLine($"{counter.Key}: {counter.Value.Count} {LM.Get("of")} {usersData.Count}");
                    }
                    sb.AppendLine($"```");
                }


                foreach (var str in sb.ToString().SplitBy(5990))
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, $".\n{str}");
                }

                /* var sb = new StringBuilder();
                 * sb.AppendLine(".");
                 * sb.AppendLine($"**Dreads** ({dreadCount} {LM.Get("of")} {totalUsers})");
                 * sb.AppendLine($"*Format: NAME (CALIBRATION) [SIEGE,WEAPON]*");
                 * sb.AppendLine($"```");
                 * foreach (var pair in dredsDic)
                 * {
                 *   sb.AppendLine($"{pair.Key} - {(string.IsNullOrEmpty(pair.Value) ? LM.Get("None") : pair.Value.Substring(0, pair.Value.Length - 2))}");
                 * }
                 * sb.AppendLine($"```");
                 *
                 * if (split)
                 * {
                 *   await APIHelper.DiscordAPI.ReplyMessageAsync(context, sb.ToString());
                 *   sb = new StringBuilder();
                 *   sb.AppendLine(".");
                 * }
                 *
                 * sb.AppendLine($"**Carriers** ({carrierCount} {LM.Get("of")} {totalUsers})");
                 * sb.AppendLine($"*Format: NAME (CALIBRATION) [FIGHTERS]*");
                 * sb.AppendLine($"```");
                 * foreach (var pair in carrierDic)
                 * {
                 *   sb.AppendLine($"{pair.Key} - {(string.IsNullOrEmpty(pair.Value) ? LM.Get("None") : pair.Value.Substring(0, pair.Value.Length - 2))}");
                 * }
                 * sb.AppendLine($"```");
                 *
                 * if (split)
                 * {
                 *   await APIHelper.DiscordAPI.ReplyMessageAsync(context, sb.ToString());
                 *   sb = new StringBuilder();
                 *   sb.AppendLine(".");
                 * }
                 *
                 * sb.AppendLine($"**Logi** ({logiCount} {LM.Get("of")} {totalUsers})");
                 * sb.AppendLine($"*Format: NAME (CALIBRATION) [SIEGE]*");
                 * sb.AppendLine($"```");
                 * foreach (var pair in logiDic)
                 * {
                 *   sb.AppendLine($"{pair.Key} - {(string.IsNullOrEmpty(pair.Value) ? LM.Get("None") : pair.Value.Substring(0, pair.Value.Length - 2))}");
                 * }
                 * sb.AppendLine($"```");
                 *
                 * if (split)
                 * {
                 *   await APIHelper.DiscordAPI.ReplyMessageAsync(context, sb.ToString());
                 *   sb = new StringBuilder();
                 *   sb.AppendLine(".");
                 * }
                 *
                 * sb.AppendLine($"**{LM.Get("capsCalibr5")}**: {c5count} {LM.Get("of")} {totalUsers}");
                 * await APIHelper.DiscordAPI.ReplyMessageAsync(context, sb.ToString());
                 */
            }
            finally
            {
                _isWhoRunning = false;
            }
        }
        private InaraResponse ProcessResponse(Response response)
        {
            if (response?.Header == null)
            {
                return new InaraResponse {
                           Status = ResponseStatus.Unprocessed
                }
            }
            ;

            var result = new InaraResponse
            {
                Status     = response.Header.Status,
                StatusText = response.Header.StatusText,
                User       = response.Header.Data
            };

            if (response.Events == null || response.Events.Length == 0)
            {
                return(result);
            }

            foreach (var requestEvent in Request.Events)
            {
                // try match request and response
                var responseEvent = response.Events.FirstOrDefault(e => e.Id == requestEvent.Id);

                switch (requestEvent.Name)
                {
                case "getCommanderProfile":
                    result.Events.Add(CommanderResult.Process(responseEvent, _inara));
                    break;

                case "addCommanderShip":
                case "setCommanderShip":
                case "setCommanderShipTransfer":
                    result.Events.Add(ShipResult.Process(responseEvent, _inara));
                    break;

                case "addCommanderTravelDock":
                case "addCommanderTravelFSDJump":
                case "setCommanderTravelLocation":
                    result.Events.Add(TravelResult.Process(responseEvent, _inara));
                    break;

                case "getCommunityGoalsRecent":
                    break;

                default:
                    result.Events.Add(new EventResult
                    {
                        Name       = requestEvent.Name,
                        Status     = responseEvent?.Status ?? ResponseStatus.OK,
                        StatusText = responseEvent?.StatusText
                    });
                    break;
                }
            }

            return(result);
        }
    }
Example #4
0
        public async Task ProcessWhoCommand(ICommandContext context, string commandText)
        {
            if (_isWhoRunning)
            {
                await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("capsCommandRunning"));

                return;
            }

            if (!File.Exists(SettingsManager.FileShipsData))
            {
                if (!File.Exists(SettingsManager.FileShipsDataDefault))
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("errFileNotFound", SettingsManager.FileShipsData));

                    return;
                }
                File.Copy(SettingsManager.FileShipsDataDefault, SettingsManager.FileShipsData);
            }

            if (context.User.IsBot || string.IsNullOrEmpty(commandText))
            {
                return;
            }
            try
            {
                _isWhoRunning = true;
                var parts     = commandText.Split(' ');
                var command   = parts[0];
                var mod       = parts.Length > 1 && IsMod(parts[1], "online") ? parts[1] : null;
                var inputName = parts.Length > 2 ? parts[2] : (parts.Length > 1 && !IsMod(parts[1], "online") ? parts[1] : null);
                //who | who online | who online name | who name
                //all | all online

                if ((!IsCommand(command, "who") && !IsCommand(command, "all")) || (mod != null && !IsMod(mod, "online")))
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("helpShips", SettingsManager.Settings.Config.BotDiscordCommandPrefix, "ships"));

                    return;
                }

                var isAll        = IsCommand(command, "all");
                var isOnlineOnly = mod != null && IsMod(mod, "online");

                //load data
                var data = JsonConvert.DeserializeObject <ShipsData>(File.ReadAllText(SettingsManager.FileShipsData));
                if (data == null)
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("errFileContainsInvalidData"));

                    return;
                }

                var    singleGroup = new KeyValuePair <string, ShipDataGroup>();
                string singleShip  = null;
                if (!string.IsNullOrEmpty(inputName))
                {
                    singleGroup = data.Groups.FirstOrDefault(a => a.Key.Equals(inputName, StringComparison.OrdinalIgnoreCase));
                    if (singleGroup.Value == null)
                    {
                        foreach (var group in data.Groups)
                        {
                            singleShip = group.Value.ShipSkills.FirstOrDefault(a => a.Key.Equals(inputName, StringComparison.OrdinalIgnoreCase)).Key;
                            if (singleShip != null)
                            {
                                singleGroup = group;
                                break;
                            }
                        }
                    }

                    if (singleGroup.Value == null)
                    {
                        await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("errShipsNameNotFound", inputName));

                        return;
                    }
                }


                var usersToCheck = new List <AuthUserEntity>();
                if (!isAll)
                {
                    foreach (var userId in APIHelper.DiscordAPI.GetUserIdsFromChannel(context.Guild.Id, context.Channel.Id, isOnlineOnly))
                    {
                        var item = await SQLHelper.GetAuthUserByDiscordId(userId);

                        if (item != null && !string.IsNullOrEmpty(item.Data.Permissions) && SettingsManager.HasCharSkillsScope(item.Data.PermissionsList))
                        {
                            usersToCheck.Add(item);
                        }
                    }
                }
                else
                {
                    if (isOnlineOnly)
                    {
                        var dusers = APIHelper.DiscordAPI.GetUserIdsFromChannel(context.Guild.Id, 0, true);
                        usersToCheck = (await SQLHelper.GetAuthUsers((int)UserStatusEnum.Authed)).Where(item => dusers.Contains(item.DiscordId) &&
                                                                                                        !string.IsNullOrEmpty(item.Data.Permissions) && SettingsManager.HasCharSkillsScope(item.Data.PermissionsList))
                                       .ToList();
                    }
                    else
                    {
                        usersToCheck = (await SQLHelper.GetAuthUsers((int)UserStatusEnum.Authed)).Where(item =>
                                                                                                        !string.IsNullOrEmpty(item.Data.Permissions) && SettingsManager.HasCharSkillsScope(item.Data.PermissionsList))
                                       .ToList();
                    }
                }

                if (!usersToCheck.Any())
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, LM.Get("capsNoUsersFound"));

                    return;
                }



                var dataDic = new Dictionary <string, List <ShipResult> >();
                var counts  = new Dictionary <string, int>();

                var usersData = new ConcurrentBag <ShipUserData>();
                await usersToCheck.ParallelForEachAsync(async userEntity =>
                {
                    var token = (await APIHelper.ESIAPI.RefreshToken(userEntity.RefreshToken, SettingsManager.Settings.WebServerModule.CcpAppClientId,
                                                                     SettingsManager.Settings.WebServerModule.CcpAppSecret, $"From {Category} | Char ID: {userEntity.CharacterId} | Char name: {userEntity.Data.CharacterName}"))?.Result;
                    if (string.IsNullOrEmpty(token))
                    {
                        await LogHelper.LogWarning($"Character {userEntity.Data.CharacterName}({userEntity.CharacterId}) has invalid token!");
                        return;
                    }
                    var skills = await APIHelper.ESIAPI.GetCharSkills(Reason, userEntity.CharacterId, token);
                    if (skills?.skills == null || skills.skills.Count == 0)
                    {
                        return;
                    }
                    usersData.Add(new ShipUserData
                    {
                        User   = userEntity,
                        Skills = skills
                    });
                }, SettingsManager.MaxConcurrentThreads);

                var groupsToCheck = singleGroup.Value != null ? new Dictionary <string, ShipDataGroup> {
                    { singleGroup.Key, singleGroup.Value }
                } : data.Groups;

                foreach (var pair in groupsToCheck)
                {
                    var groupName = pair.Key;
                    var group     = pair.Value;
                    counts.Add(groupName, 0);
                    dataDic.Add(groupName, new List <ShipResult>());

                    var shCountDic = new Dictionary <string, int>();
                    foreach (var skill in @group.ShipSkills)
                    {
                        shCountDic.Add(skill.Key, 0);
                    }

                    var useSiege  = group.FormatTemplate.Contains("{ST1}");
                    var useWeapon = group.FormatTemplate.Contains("{ST2}");


                    foreach (var user in usersData.Where(user => group.CommonSkills.All(skill =>
                    {
                        var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                        if (s == null)
                        {
                            return(false);
                        }
                        return(s.trained_skill_level >= skill.Minumim);
                    })))
                    {
                        var st1 = !useSiege ? null : (group.CommonSkills.Where(a => a.SkillType == SkillType.Siege).All(skill =>
                        {
                            var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                            if (s == null)
                            {
                                return(false);
                            }
                            return(s.trained_skill_level >= skill.T2);
                        })
                            ? "T2"
                            : "T1");

                        var userCounted = false;

                        var k            = group.ShipSkills.FirstOrDefault(a => a.Key.Equals(singleShip, StringComparison.OrdinalIgnoreCase));
                        var shipsToCheck = string.IsNullOrEmpty(singleShip)
                            ? group.ShipSkills
                            : new Dictionary <string, List <SkillRequirement> > {
                            { k.Key, k.Value }
                        };

                        foreach (var valuePair in shipsToCheck)
                        {
                            var shipName   = valuePair.Key;
                            var shipSkills = valuePair.Value;

                            var canDrive = shipSkills.All(skill =>
                            {
                                var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                                if (s == null)
                                {
                                    return(false);
                                }
                                if (skill.SkillType == SkillType.Weapon && skill.T2 > 0)
                                {
                                    return(true);
                                }
                                return(s.trained_skill_level >= skill.Minumim);
                            });
                            if (!canDrive)
                            {
                                continue;
                            }

                            var st2 = !useWeapon ? null : (shipSkills.Where(a => a.SkillType == SkillType.Weapon).Any(skill =>
                            {
                                var s = user.Skills.skills.FirstOrDefault(a => a.skill_id == skill.Id);
                                if (s == null)
                                {
                                    return(false);
                                }
                                return(s.trained_skill_level >= skill.T2);
                            })
                                ? "T2"
                                : "T1");
                            if (!userCounted)
                            {
                                counts[groupName] = counts[groupName] + 1;
                                userCounted       = true;
                            }

                            var tmplt = group.FormatTemplate.Replace("{NAME}", user.User.Data.CharacterName)
                                        .Replace("{ST1}", st1)
                                        .Replace("{ST2}", st2);
                            for (int i = 1; i < 99; i++)
                            {
                                if (!tmplt.Contains($"{{SP{i}}}"))
                                {
                                    break;
                                }
                                var spId  = group.SpecialCounters.Values.ToList()[i - 1].Id;
                                var value = user.Skills.skills.FirstOrDefault(a => a.skill_id == spId)?.trained_skill_level ?? 0;
                                tmplt = tmplt.Replace($"{{SP{i}}}", value.ToString());
                            }
                            var result = new ShipResult
                            {
                                Name = shipName,
                                Text = tmplt
                            };
                            var sd = dataDic[groupName].FirstOrDefault(a => a.Name == result.Name);
                            if (sd != null)
                            {
                                sd.Text += $", {result.Text}";
                            }
                            else
                            {
                                dataDic[groupName].Add(result);
                            }
                            shCountDic[shipName] = shCountDic[shipName] + 1;
                        }
                    }

                    foreach (var counter in @group.SpecialCounters.Where(a => a.Value.IsVisible))
                    {
                        counter.Value.Count = usersData.Count(user =>
                                                              user.Skills.skills.FirstOrDefault(a => a.skill_id == counter.Value.Id && a.trained_skill_level >= counter.Value.Rank) != null);
                    }

                    //add empty ships
                    if (string.IsNullOrEmpty(singleShip))
                    {
                        foreach (var valuePair in shCountDic.Where(a => a.Value == 0))
                        {
                            dataDic[groupName].Add(new ShipResult
                            {
                                Name = valuePair.Key,
                                Text = LM.Get("None")
                            });
                        }
                    }
                }

                var sb = new StringBuilder();
                foreach (var pair in dataDic)
                {
                    sb.AppendLine($"**{pair.Key}** ({counts[pair.Key]} {LM.Get("of")} {usersData.Count})");
                    sb.AppendLine($"*Format: {data.Groups[pair.Key].FormatDescription}*");
                    sb.AppendLine($"```");
                    var maxNameLen = pair.Value.Any() ? pair.Value.GroupBy(a => a.Name).Max(a => a.Key.Length) : 1;

                    foreach (var group in pair.Value.GroupBy(a => a.Name))
                    {
                        var text = string.Join(", ", group.Select(a => a.Text));
                        sb.AppendLine($"{group.Key.FixedLength(maxNameLen)} - {(string.IsNullOrEmpty(text) ? LM.Get("None") : text)}");
                    }

                    if (data.Groups[pair.Key].SpecialCounters.Any(a => a.Value.IsVisible))
                    {
                        sb.AppendLine($"");
                        sb.AppendLine($"Specials");
                    }

                    foreach (var counter in data.Groups[pair.Key].SpecialCounters.Where(a => a.Value.IsVisible))
                    {
                        sb.AppendLine($"{counter.Key}: {counter.Value.Count} {LM.Get("of")} {usersData.Count}");
                    }
                    sb.AppendLine($"```");
                }


                foreach (var str in sb.ToString().SplitBy(5990))
                {
                    await APIHelper.DiscordAPI.ReplyMessageAsync(context, $".\n{str}");
                }
            }
            finally
            {
                _isWhoRunning = false;
            }
        }