Example #1
0
        public async Task ServerInfo(string serverKey, ServerInfo serverInfo, OnlinePlayer[] onlinePlayers)
        {
            var context = _contextManager.GetServer(serverKey);

            if (context == null)
            {
                return;
            }

            // store the server key in this connection (could probably do this within authentication later)
            if (!Context.Items.ContainsKey("serverKey"))
            {
                Context.Items.Add("serverKey", serverKey);
            }
            else
            {
                Context.Items["serverKey"] = serverKey;
            }

            context.Data.ServerInfo = serverInfo;

            var unixTime = DateTimeOffset.FromUnixTimeMilliseconds(context.Data.ServerInfo.UtcTime);
            await _databaseRepo.AddorUpdatePlayers(onlinePlayers.Select(x =>
            {
                var loginTime = unixTime.AddSeconds(x.Time - context.Data.ServerInfo.GameTime).UtcDateTime;
                return(ulong.Parse(x.SteamId), serverKey, (DateTime?)loginTime, DateTime.UtcNow, true);
            }).ToArray());
        }
Example #2
0
        private void OnManuallyTriggerServerUpdate(string serverKey)
        {
            var context = _contextManager.GetServer(serverKey);

            if (context == null)
            {
                MessageBox.Show($"Could not find server instance '{serverKey}'", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            _contextManager.QueueUpdateServerManual(context);
        }
Example #3
0
        public async Task Servers([Remainder] string arguments = null)
        {
            var args = CommandHelper.ParseArgs(arguments, new { cluster = false, clusters = false }, x =>
                                               x.For(y => y.cluster, flag: true)
                                               .For(y => y.clusters, flag: true));

            if (_config.Servers != null)
            {
                var embed = new EmbedBuilder();
                embed.WithTitle("Server List");

                foreach (var server in _config.Servers)
                {
                    var serverContext = _contextManager.GetServer(server.Key);

                    var address = server.DisplayAddress ?? $"{server.Ip}:{server.QueryPort}";

                    var cluster = args.cluster || args.clusters ? $" (cluster **`{server.ClusterKey}`**)" : "";

                    embed.AddField($"{ address}", $"steam://connect/{address} (key: `{server.Key}`){cluster}", true);
                }

                await Context.Channel.SendMessageAsync("", false, embed.Build());
            }
            else
            {
                await Context.Channel.SendMessageAsync("There are no servers available.");

                return;
            }
        }
Example #4
0
        public async Task <HttpResponseMessage> SaveWorld(string id)
        {
            var serverContext = _contextManager.GetServer(id);

            if (serverContext == null)
            {
                return(Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Server instance key not found!"));
            }

            var result = await serverContext.Steam.SendRconCommand($"SaveWorld");

            if (result == null)
            {
                return(Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Timeout while waiting for command response..."));
            }

            return(Request.CreateResponse(HttpStatusCode.OK, new AdministerResponseViewModel
            {
                Message = "World saved! Please wait for server update (new data)..."
            }));
        }
Example #5
0
        public async Task Rcon([Remainder] string arguments = null)
        {
            var args = CommandHelper.ParseArgs(arguments, new
            {
                ServerKey = "",
                Command   = ""
            }, x =>
                                               x.For(y => y.ServerKey, noPrefix: true, isRequired: true)
                                               .For(y => y.Command, noPrefix: true, isRequired: true, untilNextToken: true));

            var sb = new StringBuilder();

            var serverContext = args?.ServerKey != null?_contextManager.GetServer(args.ServerKey) : null;

            if (serverContext == null)
            {
                await Context.Channel.SendMessageAsync($"**Rcon commands need to be prefixed with a valid server instance key.**");

                return;
            }

            if (args == null)
            {
                var syntaxHelp = MethodBase.GetCurrentMethod().GetCustomAttribute <SyntaxHelpAttribute>()?.SyntaxHelp;
                var name       = MethodBase.GetCurrentMethod().GetCustomAttribute <CommandAttribute>()?.Text;

                await Context.Channel.SendMessageAsync(string.Join(Environment.NewLine, new string[] {
                    $"**My logic circuits cannot process this command! I am just a bot after all... :(**",
                    !string.IsNullOrWhiteSpace(syntaxHelp) ? $"Help me by following this syntax: **!{name}** {syntaxHelp}" : null
                }.Where(x => x != null)));

                return;
            }

            var result = await serverContext.Steam.SendRconCommand(args.Command);

            if (result == null)
            {
                sb.AppendLine("**Failed to send rcon command... :(**");
            }
            else
            {
                sb.AppendLine($"```{result}```");
            }

            var msg = sb.ToString();

            if (!string.IsNullOrWhiteSpace(msg))
            {
                await CommandHelper.SendPartitioned(Context.Channel, sb.ToString());
            }
        }
Example #6
0
        public ServerViewModel Get(string id) //, int? limit)
        {
            var context = _contextManager.GetServer(id);

            if (context == null)
            {
                return(null);
            }

            var demoMode = IsDemoMode() ? new DemoMode() : null;
            var result   = new ServerViewModel
            {
                MapName = context.SaveState?.MapName
            };

            if (HasFeatureAccess("server", "players") && context.Players != null)
            {
                result.Players.AddRange(context.Players.Select(x =>
                {
                    var tribe = x.TribeId != null ? context.Tribes?.FirstOrDefault(y => y.Id == x.TribeId) : null;
                    return(new PlayerReferenceViewModel
                    {
                        Id = x.Id,
                        SteamId = x.SteamId,
                        FakeSteamId = demoMode?.GetSteamId(x.SteamId),
                        CharacterName = demoMode?.GetPlayerName(x.Id) ?? x.CharacterName,
                        SteamName = null,
                        TribeName = tribe != null ? demoMode?.GetTribeName(tribe.Id) ?? tribe.Name : null,
                        TribeId = x.TribeId,
                        LastActiveTime = x.LastActiveTime
                    });
                }).OrderByDescending(x => x.LastActiveTime).Where(x => x.LastActiveTime >= DateTime.UtcNow.AddDays(-90)));
            }

            if (HasFeatureAccess("server", "tribes") && context.Tribes != null)
            {
                result.Tribes.AddRange(context.Tribes.Select(x =>
                {
                    var members = context.Players?.Where(y => x.MemberIds.Contains((int)y.Id)).ToList() ?? new List <ArkPlayer>();
                    return(new TribeReferenceViewModel
                    {
                        Id = x.Id,
                        Name = demoMode?.GetTribeName(x.Id) ?? x.Name,
                        MemberSteamIds = members.Select(y => y.SteamId).ToList(),
                        LastActiveTime = x.LastActiveTime
                    });
                }).OrderByDescending(x => x.LastActiveTime).Where(x => x.LastActiveTime >= DateTime.UtcNow.AddDays(-90)));
            }

            return(result);
        }
Example #7
0
        public async Task TimerUpdateVotes()
        {
            using (var db = _databaseContextFactory.Create())
            {
                var elapsedBans = db.Votes.OfType <BanVote>().Where(x => x.Result == VoteResult.Passed && x.BannedUntil.HasValue && x.BannedUntil <= DateTime.Now).ToArray();
                foreach (var ban in elapsedBans)
                {
                    var serverContext = _contextManager.GetServer(ban.ServerKey);
                    if (serverContext == null)
                    {
                        Logging.Log($"Failed to automatically unban player {ban.SteamId} on server ({ban.ServerKey}) because the server was not found.", typeof(ArkDiscordBot), LogLevel.WARN);
                        continue;
                    }

                    if (await serverContext.Steam.SendRconCommand($"unbanplayer {ban.SteamId}") != null)
                    {
                        ban.BannedUntil = null;
                    }
                }

                db.SaveChanges();
            }
        }
Example #8
0
        public ServerViewModel Get(string id) //, int? limit)
        {
            var context = _contextManager.GetServer(id);

            if (context == null)
            {
                return(null);
            }

            var result = new ServerViewModel
            {
            };

            if (context.Players != null)
            {
                result.Players.AddRange(context.Players.Select(x =>
                {
                    return(new PlayerReferenceViewModel
                    {
                        Id = x.Id,
                        SteamId = x.SteamId,
                        CharacterName = x.CharacterName,
                        SteamName = null,
                        TribeName = x.TribeId != null ? context.Tribes?.FirstOrDefault(y => y.Id == x.TribeId)?.Name : null,
                        TribeId = x.TribeId,
                        LastActiveTime = x.SavedAt
                    });
                }).OrderByDescending(x => x.LastActiveTime).Where(x => x.LastActiveTime >= DateTime.UtcNow.AddDays(-90)));
            }

            if (context.Tribes != null)
            {
                result.Tribes.AddRange(context.Tribes.Select(x =>
                {
                    var members = context.Players?.Where(y => x.MemberIds.Contains((int)y.Id)).ToList() ?? new List <ArkPlayer>();
                    return(new TribeReferenceViewModel
                    {
                        Id = x.Id,
                        Name = x.Name,
                        MemberSteamIds = members.Select(y => y.SteamId).ToList(),
                        LastActiveTime = members.Count > 0 ? members.Max(y => y.SavedAt) : x.SavedAt
                    });
                }).OrderByDescending(x => x.LastActiveTime).Where(x => x.LastActiveTime >= DateTime.UtcNow.AddDays(-90)));
            }

            return(result);
        }
Example #9
0
        public async Task Servers([Remainder] string arguments = null)
        {
            var args = CommandHelper.ParseArgs(arguments, new { cluster = false, clusters = false }, x =>
                                               x.For(y => y.cluster, flag: true)
                                               .For(y => y.clusters, flag: true));

            if (_config.Servers != null)
            {
                var sb = new StringBuilder();
                sb.AppendLine("**Server List**");

                foreach (var server in _config.Servers)
                {
                    var    serverContext = _contextManager.GetServer(server.Key);
                    var    info          = serverContext.Steam.GetServerInfoCached();
                    string name          = null;
                    if (info != null)
                    {
                        var m = new Regex(@"^(?<name>.+?)\s+-\s+\(v(?<version>\d+\.\d+)\)$",
                                          RegexOptions.IgnoreCase | RegexOptions.Singleline).Match(info.Name);
                        name = m.Success ? m.Groups["name"].Value : info.Name;
                    }

                    var address = $"{server.Ip}:{server.Port}";

                    var cluster = args.cluster || args.clusters ? $" (cluster **{server.Cluster}**)" : "";

                    sb.AppendLine(
                        $"● **{name ?? address}**{(name != null ? $" ({address})" : "")} (key: **{server.Key}**){cluster}");
                }

                await CommandHelper.SendPartitioned(Context.Channel, sb.ToString());
            }
            else
            {
                await Context.Channel.SendMessageAsync("There are no servers available.");

                return;
            }
        }
Example #10
0
        public async Task Servers([Remainder] string arguments = null)
        {
            var args = CommandHelper.ParseArgs(arguments, new { cluster = false, clusters = false }, x =>
                                               x.For(y => y.cluster, flag: true)
                                               .For(y => y.clusters, flag: true));

            if (_config.Servers != null)
            {
                var embed = new EmbedBuilder();
                embed.WithTitle("Server List");

                foreach (var server in _config.Servers)
                {
                    var    serverContext = _contextManager.GetServer(server.Key);
                    var    info          = serverContext.Steam.GetServerInfoCached();
                    string name          = null;
                    if (info != null)
                    {
                        var m = new Regex(@"^(?<name>.+?)\s+-\s+\(v(?<version>\d+\.\d+)\)$",
                                          RegexOptions.IgnoreCase | RegexOptions.Singleline).Match(info.Name);
                        name = m.Success ? m.Groups["name"].Value : info.Name;
                    }

                    var address = server.DisplayAddress ?? $"{server.Ip}:{server.QueryPort}";

                    var cluster = args.cluster || args.clusters ? $" (cluster **`{server.ClusterKey}`**)" : "";

                    embed.AddField($"{ name ?? address}", $"steam://connect/{address} (key: `{server.Key}`){cluster}", true);
                }

                await Context.Channel.SendMessageAsync("", false, embed.Build());
            }
            else
            {
                await Context.Channel.SendMessageAsync("There are no servers available.");

                return;
            }
        }
Example #11
0
        public async Task <IActionResult> SaveWorld(string id)
        {
            var serverContext = _contextManager.GetServer(id);

            if (serverContext == null)
            {
                return(BadRequest("Server instance key not found!"));
            }

            var result = await serverContext.Steam.SendRconCommand($"SaveWorld");

            if (result == null)
            {
                return(InternalServerError("Timeout while waiting for command response..."));
            }

            return(Ok(new AdministerResponseViewModel
            {
                Message = "World saved! Please wait for server update (new data)..."
            }));
        }
Example #12
0
        public async Task Run(CommandEventArgs e)
        {
            if (!e.Channel.IsPrivate)
            {
                return;
            }

            var args = CommandHelper.ParseArgs(e, new { logs = false, json = false, save = false, database = false, stats = false, clear = false, key = "", data = "" }, x =>
                                               x.For(y => y.logs, flag: true)
                                               .For(y => y.json, flag: true)
                                               .For(y => y.save, flag: true)
                                               .For(y => y.database, flag: true)
                                               .For(y => y.stats, flag: true)
                                               .For(y => y.clear, flag: true)
                                               .For(y => y.key, untilNextToken: true)
                                               .For(y => y.data, untilNextToken: true));

            if (args == null)
            {
                await e.Channel.SendMessage(string.Join(Environment.NewLine, new string[] {
                    $"**My logic circuits cannot process this command! I am just a bot after all... :(**",
                    !string.IsNullOrWhiteSpace(SyntaxHelp) ? $"Help me by following this syntax: **!{Name}** {SyntaxHelp}" : null
                }.Where(x => x != null)));

                return;
            }

            if (args.stats)
            {
                var sb = new StringBuilder();
                sb.AppendLine("**ARK Survival Discord Bot Statistics**");
                if (File.Exists(_constants.DatabaseFilePath))
                {
                    sb.AppendLine($"● **Database size:** {FileHelper.ToFileSize(new FileInfo(_constants.DatabaseFilePath).Length)}");
                }

                await CommandHelper.SendPartitioned(e.Channel, sb.ToString());
            }
            else if (args.logs)
            {
                var pattern = "*.log";

                var files = Directory.GetFiles(".\\logs\\", pattern, SearchOption.TopDirectoryOnly);
                if (files == null || files.Length <= 0)
                {
                    await e.Channel.SendMessage("Could not find any logs... :(");

                    return;
                }

                if (args.clear)
                {
                    foreach (var file in files)
                    {
                        File.Delete(file);
                    }

                    await e.Channel.SendMessage("Cleared all log files!");

                    return;
                }
                else
                {
                    var path = Path.Combine(_config.TempFileOutputDirPath, "logs_" + DateTime.Now.ToString("yyyy-MM-dd.HH.mm.ss.ffff") + ".zip");
                    try
                    {
                        FileHelper.CreateZipArchive(files, path);
                        await e.Channel.SendFile(path);
                    }
                    catch
                    {
                        await e.Channel.SendMessage("Failed to archive log files... :(");

                        return;
                    }
                    finally
                    {
                        if (File.Exists(path))
                        {
                            File.Delete(path);
                        }
                    }
                }
            }
            else if (args.json)
            {
                if (_config.DisableDeveloperFetchSaveData)
                {
                    await e.Channel.SendMessage("The administrator have disabled this feature.");

                    return;
                }

                var files     = new List <string>();
                var tempfiles = new List <string>();
                var basepath  = _config.JsonOutputDirPath;
                if (!string.IsNullOrEmpty(args.key))
                {
                    //todo: no cluster data support
                    var server = _contextManager.GetServer(args.key);
                    if (server == null)
                    {
                        await e.Channel.SendMessage("The key did not exist.");

                        return;
                    }

                    var data = args.data?.Split(',', ';', '|');
                    if (!(data?.Length > 0))
                    {
                        await e.Channel.SendMessage("No data items supplied.");

                        return;
                    }

                    foreach (var d in data)
                    {
                        var     key = d.Trim().ToLower();
                        dynamic obj = null;
                        switch (key)
                        {
                        case "wild":
                            obj = server.WildCreatures;
                            break;

                        case "tamed":
                            obj = server.TamedCreatures;
                            break;

                        case "players":
                            obj = server.Players;
                            break;

                        case "tribes":
                            obj = server.Tribes;
                            break;

                        case "items":
                            obj = server.Items;
                            break;

                        case "structures":
                            obj = server.Structures;
                            break;
                        }

                        if (obj != null)
                        {
                            var json     = JsonConvert.SerializeObject(obj);
                            var jsonPath = Path.Combine(_config.TempFileOutputDirPath, $"json_{key}_" + DateTime.Now.ToString("yyyy-MM-dd.HH.mm.ss.ffff") + ".json");
                            tempfiles.Add(jsonPath);
                            files.Add(jsonPath);
                            File.WriteAllText(jsonPath, json);
                        }
                    }

                    basepath = _config.TempFileOutputDirPath;
                }
                else
                {
                    var pattern = "*.json";
                    var _files  = Directory.GetFiles(_config.JsonOutputDirPath, pattern, SearchOption.AllDirectories);
                    if (_files == null || _files.Length <= 0)
                    {
                        await e.Channel.SendMessage("Could not find any json files... :(");

                        return;
                    }
                    files.AddRange(_files);
                }

                var      path    = Path.Combine(_config.TempFileOutputDirPath, "json_" + DateTime.Now.ToString("yyyy-MM-dd.HH.mm.ss.ffff") + ".zip");
                string[] results = null;
                try
                {
                    results = FileHelper.CreateDotNetZipArchive(new[] { new Tuple <string, string, string[]>(basepath, "", files.ToArray()) }, path, 5 * 1024 * 1024);
                    tempfiles.AddRange(results);
                    foreach (var item in results)
                    {
                        await e.Channel.SendFile(item);
                    }
                }
                catch
                {
                    await e.Channel.SendMessage("Failed to archive json files... :(");

                    return;
                }
                finally
                {
                    foreach (var p in tempfiles)
                    {
                        if (File.Exists(p))
                        {
                            File.Delete(p);
                        }
                    }
                }

                await Task.Delay(500);

                await e.Channel.SendMessage($"[parts {results.Length}]");
            }
            else if (args.save)
            {
                if (_config.DisableDeveloperFetchSaveData)
                {
                    await e.Channel.SendMessage("The administrator have disabled this feature.");

                    return;
                }

                var saveFilePath    = _config.SaveFilePath;
                var clusterSavePath = _config.ClusterSavePath;
                if (!string.IsNullOrEmpty(args.key))
                {
                    var server = _config.Servers?.FirstOrDefault(x => x.Key.Equals(args.key, StringComparison.OrdinalIgnoreCase));
                    if (server == null)
                    {
                        await e.Channel.SendMessage("The key did not exist.");

                        return;
                    }
                    saveFilePath = server.SaveFilePath;
                    var cluster = !string.IsNullOrEmpty(server.Cluster) ? _config.Clusters?.FirstOrDefault(x => x.Key.Equals(server.Cluster, StringComparison.OrdinalIgnoreCase)) : null;
                    clusterSavePath = cluster?.SavePath;
                }

                var dir   = Path.GetDirectoryName(saveFilePath);
                var files = new[]
                {
                    File.Exists(saveFilePath) ? new Tuple <string, string, string[]>("", "", new [] { saveFilePath }) : null,
                    Directory.Exists(dir) ? new Tuple <string, string, string[]>("", "", Directory.GetFiles(dir, "*.arkprofile", SearchOption.TopDirectoryOnly)) : null,
                    Directory.Exists(dir) ? new Tuple <string, string, string[]>("", "", Directory.GetFiles(dir, "*.arktribe", SearchOption.TopDirectoryOnly)) : null,
                    !string.IsNullOrEmpty(clusterSavePath) ? new Tuple <string, string, string[]>(clusterSavePath, "cluster", Directory.GetFiles(clusterSavePath, "*", SearchOption.AllDirectories)) : null
                }.Where(x => x != null && x.Item2 != null).ToArray();
                if (files == null || !files.Any(x => x.Item2 != null && x.Item2.Length > 0))
                {
                    await e.Channel.SendMessage("Could not find any save files... :(");

                    return;
                }

                var      path    = Path.Combine(_config.TempFileOutputDirPath, "save_" + (!string.IsNullOrEmpty(args.key) ? $"{args.key}_" : "") + DateTime.Now.ToString("yyyy-MM-dd.HH.mm.ss.ffff") + ".zip");
                string[] results = null;
                try
                {
                    results = FileHelper.CreateDotNetZipArchive(files, path, 5 * 1024 * 1024);
                    foreach (var item in results)
                    {
                        await e.Channel.SendFile(item);
                    }
                }
                catch
                {
                    await e.Channel.SendMessage("Failed to archive save files... :(");

                    return;
                }
                finally
                {
                    if (results != null)
                    {
                        foreach (var item in results)
                        {
                            if (File.Exists(item))
                            {
                                File.Delete(item);
                            }
                        }
                    }
                }

                await Task.Delay(500);

                await e.Channel.SendMessage($"[parts {results.Length}]");
            }
            else if (args.database)
            {
                var file = File.Exists(_constants.DatabaseFilePath) ? _constants.DatabaseFilePath : null;
                if (file == null)
                {
                    await e.Channel.SendMessage("Could not find the database file... :(");

                    return;
                }

                var      path    = Path.Combine(_config.TempFileOutputDirPath, "database_" + DateTime.Now.ToString("yyyy-MM-dd.HH.mm.ss.ffff") + ".zip");
                string[] results = null;
                try
                {
                    results = FileHelper.CreateDotNetZipArchive(new[] { new Tuple <string, string, string[]>("", "", new[] { file }) }, path, 5 * 1024 * 1024);
                    foreach (var item in results)
                    {
                        await e.Channel.SendFile(item);
                    }
                }
                catch
                {
                    await e.Channel.SendMessage("Failed to archive database file... :(");

                    return;
                }
                finally
                {
                    if (results != null)
                    {
                        foreach (var item in results)
                        {
                            if (File.Exists(item))
                            {
                                File.Delete(item);
                            }
                        }
                    }
                }
            }
        }
Example #13
0
        public async Task Run(CommandEventArgs e)
        {
            if (!_context.IsInitialized)
            {
                await e.Channel.SendMessage($"**The data is loading but is not ready yet...**");

                return;
            }

            //var args = CommandHelper.ParseArgs(e, new { Extended = false }, x =>
            //    x.For(y => y.Extended, flag: true));
            var playersx = e.Message.Text.StartsWith("!playersx", StringComparison.OrdinalIgnoreCase);

            var serverContext = _contextManager.GetServer(_config.ServerKey);
            var serverInfo    = serverContext.Steam.GetServerInfoCached();
            var playerInfo    = serverContext.Steam.GetServerPlayersCached();

            var sb = new StringBuilder();

            if (serverInfo == null || playerInfo == null)
            {
                sb.AppendLine($"**Player list is currently unavailable!**");
            }
            else
            {
                var players = playerInfo?.Where(x => !string.IsNullOrEmpty(x.Name)).ToArray() ?? new PlayerInfo[] { };

                var m    = new Regex(@"^(?<name>.+?)\s+-\s+\(v(?<version>\d+\.\d+)\)$", RegexOptions.IgnoreCase | RegexOptions.Singleline).Match(serverInfo.Name);
                var name = m.Success ? m.Groups["name"].Value : serverInfo.Name;

                sb.AppendLine($"**{name} ({serverInfo.Players - (playerInfo.Count - players.Length)}/{serverInfo.MaxPlayers})**");

                if (playersx)
                {
                    using (var db = _databaseContextFactory.Create())
                    {
                        var playerNames = players.Select(x => x.Name).ToArray();
                        var d           = _context.Players.Where(x => playerNames.Contains(x.PlayerName, StringComparer.Ordinal)).Select(x =>
                        {
                            long steamId;
                            return(new Tuple <Data.Player, Database.Model.User, User, long?, TimeSpan>(
                                       x,
                                       null,
                                       null,
                                       long.TryParse(x.SteamId, out steamId) ? steamId : (long?)null,
                                       TimeSpan.Zero));
                        }).ToDictionary(x => x.Item1.PlayerName, StringComparer.OrdinalIgnoreCase);

                        var ids      = new List <int>();
                        var steamIds = d.Values.Select(x => x.Item4).Where(x => x != null).ToArray();
                        foreach (var user in db.Users.Where(y => steamIds.Contains(y.SteamId)))
                        {
                            var item = d.Values.FirstOrDefault(x => x.Item4 == user.SteamId);
                            if (item == null)
                            {
                                continue;
                            }

                            ids.Add(item.Item1.Id);

                            var discordUser         = e.User?.Client?.Servers?.Select(x => x.GetUser((ulong)user.DiscordId)).FirstOrDefault();
                            var playedLastSevenDays = TimeSpan.FromSeconds(user?.Played?.OrderByDescending(x => x.Date).Take(7).Sum(x => x.TimeInSeconds) ?? 0);

                            d[item.Item1.PlayerName] = new Tuple <Data.Player, Database.Model.User, User, long?, TimeSpan>(item.Item1, user, discordUser, item.Item4, playedLastSevenDays);
                        }

                        var remaining = d.Values.Where(x => !ids.Contains(x.Item1.Id)).Where(x => x.Item4 != null).Select(x => x.Item4.Value).ToArray();
                        foreach (var user in db.Played.Where(x => x.SteamId.HasValue && remaining.Contains(x.SteamId.Value))
                                 .GroupBy(x => x.SteamId)
                                 .Select(x => new { key = x.Key, items = x.OrderByDescending(y => y.Date).Take(7).ToList() })
                                 .ToArray())
                        {
                            var item = d.Values.FirstOrDefault(x => x.Item4 == user.key);
                            if (item == null)
                            {
                                continue;
                            }

                            var playedLastSevenDays = TimeSpan.FromSeconds(user?.items?.Sum(x => x.TimeInSeconds) ?? 0);
                            d[item.Item1.PlayerName] = new Tuple <Data.Player, Database.Model.User, User, long?, TimeSpan>(item.Item1, item.Item2, item.Item3, item.Item4, playedLastSevenDays);
                        }

                        //var playerslist = players.Select(x => {
                        //    var extra = d.ContainsKey(x.Name) ? d[x.Name] : null;
                        //    return new
                        //    {
                        //        Steam = x.Name,
                        //        Name = extra?.Item1?.Name,
                        //        Tribe = extra?.Item1?.TribeName,
                        //        Discord = extra != null && extra.Item3 != null ? $"{extra.Item3.Name}#{extra.Item3.Discriminator}" : null,
                        //        TimeOnline = x.Time.ToStringCustom(),
                        //        PlayedLastSevenDays = extra != null && extra.Item5.TotalMinutes > 1 ? extra?.Item5.ToStringCustom() : null
                        //    };
                        //}).ToArray();

                        //sb.AppendLine("```");
                        //sb.AppendLine(FixedWidthTableHelper.ToString(playerslist, x => x
                        //    .For(y => y.TimeOnline, "Online For", alignment: 1)
                        //    .For(y => y.PlayedLastSevenDays, "Played/last 7 days", alignment: 1)));
                        //sb.AppendLine("```");

                        foreach (var player in players)
                        {
                            var extra = d.ContainsKey(player.Name) ? d[player.Name] : null;

                            sb.AppendLine($"● **{player.Name}"
                                          + (extra != null && extra.Item1.Name != null ? $" ({extra.Item1.Name})" + (extra.Item1.TribeName != null ? $" [{extra.Item1.TribeName}]" : "") : "")
                                          + "**"
                                          + (extra != null && extra.Item3 != null ? $" - **{extra.Item3.Name}#{extra.Item3.Discriminator}**" : "")
                                          + (player.Time != TimeSpan.Zero ? " (" + player.Time.ToStringCustom() + ")" : "")
                                          + (extra != null && extra.Item5.TotalMinutes > 1 ? " [" + extra.Item5.ToStringCustom() + " last 7d]" : null));
                        }
                    }
                }
                else
                {
                    foreach (var player in players)
                    {
                        sb.AppendLine($"● **{player.Name}** ({player.Time.ToStringCustom()})");
                    }
                }
            }

            await CommandHelper.SendPartitioned(e.Channel, sb.ToString());
        }
Example #14
0
        public async Task Admin([Remainder] string arguments = null)
        {
            //if (!e.Channel.IsPrivate) return;

            var args = CommandHelper.ParseArgs(arguments, new
            {
                ServerKey             = "",
                StartServer           = false,
                StartServers          = false,
                ShutdownServer        = false,
                ShutdownServers       = false,
                StopServer            = false,
                StopServers           = false,
                TerminateServer       = false,
                RestartServer         = false,
                RestartServers        = false,
                UpdateServer          = false,
                UpdateServers         = false,
                Backups               = false,
                SteamId               = 0L,
                SaveWorld             = false,
                DestroyWildDinos      = false,
                EnableVoting          = false,
                SetVotingAllowed      = 0L, //steam id
                KickPlayer            = 0L, //steam id
                BanPlayer             = 0L, //steam id
                UnbanPlayer           = 0L, //steam id
                KillPlayer            = 0L, //ark player id
                DoExit                = false,
                Broadcast             = "",
                ListPlayers           = false,
                RenamePlayer          = "",
                RenameTribe           = "",
                NewName               = "",
                ServerChat            = "",
                ServerChatTo          = 0L, //steam id
                ServerChatToPlayer    = "",
                Message               = "",
                GetPlayerIDForSteamID = 0L, //steam id
                GetSteamIDForPlayerID = 0L, //ark player id
                GetTribeIdPlayerList  = 0L,
                SetTimeOfDay          = "",
                Countdown             = "",
                True  = false,
                False = false
            }, x =>
                                               x.For(y => y.ServerKey, noPrefix: true)
                                               .For(y => y.StartServer, flag: true)
                                               .For(y => y.StartServers, flag: true)
                                               .For(y => y.ShutdownServer, flag: true)
                                               .For(y => y.ShutdownServers, flag: true)
                                               .For(y => y.StopServer, flag: true)
                                               .For(y => y.StopServers, flag: true)
                                               .For(y => y.TerminateServer, flag: true)
                                               .For(y => y.RestartServer, flag: true)
                                               .For(y => y.RestartServers, flag: true)
                                               .For(y => y.UpdateServer, flag: true)
                                               .For(y => y.UpdateServers, flag: true)
                                               .For(y => y.Backups, flag: true)
                                               .For(y => y.SaveWorld, flag: true)
                                               .For(y => y.DestroyWildDinos, flag: true)
                                               .For(y => y.EnableVoting, flag: true)
                                               .For(y => y.DoExit, flag: true)
                                               .For(y => y.ListPlayers, flag: true)
                                               .For(y => y.Broadcast, untilNextToken: true)
                                               .For(y => y.RenamePlayer, untilNextToken: true)
                                               .For(y => y.RenameTribe, untilNextToken: true)
                                               .For(y => y.NewName, untilNextToken: true)
                                               .For(y => y.ServerChat, untilNextToken: true)
                                               .For(y => y.ServerChatToPlayer, untilNextToken: true)
                                               .For(y => y.Message, untilNextToken: true)
                                               .For(y => y.Countdown, untilNextToken: true)
                                               .For(y => y.True, flag: true)
                                               .For(y => y.False, flag: true));

            var _rTimeOfDay = new Regex(@"^\s*\d{2,2}\:\d{2,2}(\:\d{2,2})?\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase);
            var _rCountdown = new Regex(@"^\s*(?<min>\d+)\s+(?<reason>.+)$", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
            var sb          = new StringBuilder();

            var isCountdown          = !string.IsNullOrEmpty(args.Countdown) && _rCountdown.IsMatch(args.Countdown);
            var isMultiServerCommand = args != null && (isCountdown ||
                                                        args.StartServer || args.StartServers || args.StopServer || args.StopServers ||
                                                        args.ShutdownServer || args.ShutdownServers || args.RestartServer || args.RestartServers ||
                                                        args.UpdateServer || args.UpdateServers);

            var serverContext = args?.ServerKey != null?_contextManager.GetServer(args.ServerKey) : null;

            if (serverContext == null && !isMultiServerCommand)
            {
                await Context.Channel.SendMessageAsync($"**Admin commands need to be prefixed with a valid server instance key.**");

                return;
            }

            // collection of servers that this countdown applies to
            var serverContexts = serverContext == null && !string.IsNullOrWhiteSpace(args.ServerKey) ? null
                : serverContext == null?_contextManager.Servers.ToArray()
                                     : new ArkServerContext[]
            {
                serverContext
            };

            if (serverContexts == null)
            {
                await Context.Channel.SendMessageAsync($"**The given server instance key is not valid.**");

                return;
            }

            if (isCountdown)
            {
                var m              = _rCountdown.Match(args.Countdown);
                var reason         = m.Groups["reason"].Value;
                var delayInMinutes = int.Parse(m.Groups["min"].Value);
                if (delayInMinutes < 1)
                {
                    delayInMinutes = 1;
                }

                Func <Task> react = null;
                if (args.StopServer || args.StopServers || args.ShutdownServer || args.ShutdownServers)
                {
                    react = new Func <Task>(async() =>
                    {
                        var tasks = serverContexts.Select(x => Task.Run(async() =>
                        {
                            string message = null;
                            if (!await _arkServerService.ShutdownServer(x.Config.Key, (s) => { message = s; return(Task.FromResult((IUserMessage)null)); }))
                            {
                                Logging.Log($@"Countdown to shutdown server ({x.Config.Key}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG);
                            }
                        })).ToArray();

                        await Task.WhenAll(tasks);
                    });
                }
                else if (args.UpdateServer || args.UpdateServers)
                {
                    react = new Func <Task>(async() =>
                    {
                        var tasks = serverContexts.Select(x => Task.Run(async() =>
                        {
                            string message = null;
                            if (!await _arkServerService.UpdateServer(x.Config.Key, (s) => { message = s; return(Task.FromResult((IUserMessage)null)); }, (s) => s.FirstCharToUpper(), 300))
                            {
                                Logging.Log($@"Countdown to update server ({x.Config.Key}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG);
                            }
                        })).ToArray();

                        await Task.WhenAll(tasks);
                    });
                }
                else if (args.RestartServer || args.RestartServers)
                {
                    react = new Func <Task>(async() =>
                    {
                        var tasks = serverContexts.Select(x => Task.Run(async() =>
                        {
                            string message = null;
                            if (!await _arkServerService.RestartServer(x.Config.Key, (s) => { message = s; return(Task.FromResult((IUserMessage)null)); }))
                            {
                                Logging.Log($@"Countdown to restart server ({x.Config.Key}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG);
                            }
                        })).ToArray();

                        await Task.WhenAll(tasks);
                    });
                }

                sb.AppendLine($"**Countdown{(serverContext == null ? "" : $" on server {serverContext.Config.Key}")} have been initiated. Announcement will be made.**");
                await _scheduledTasksManager.StartCountdown(serverContext, reason, delayInMinutes, react);
            }
Example #15
0
        public WildCreaturesViewModel Get(string id)
        {
            var context = _contextManager.GetServer(id);

            if (context == null)
            {
                return(null);
            }

            var demoMode = IsDemoMode() ? new DemoMode() : null;
            var result   = new WildCreaturesViewModel
            {
            };

            // access control
            var incWildCreatures          = HasFeatureAccess("server", "wildcreatures", id);
            var incWildCreaturesBaseStats = HasFeatureAccess("server", "wildcreatures-basestats", id);
            var incStatistics             = HasFeatureAccess("server", "wildcreatures-statistics", id);

            var speciesGroups = context.WildCreatures.GroupBy(x => x.ClassName)
                                .ToDictionary(x => x.Key, x => new { items = x.ToArray(), aliases = ArkSpeciesAliases.Instance.GetAliases(x.Key) });

            if (incWildCreatures)
            {
                var species = speciesGroups.Select(x =>
                {
                    var vms = new WildCreatureSpeciesViewModel
                    {
                        ClassName  = x.Key,
                        Name       = x.Value.aliases?.FirstOrDefault(),
                        Aliases    = x.Value.aliases?.Skip(2).ToArray() ?? new string[] { }, //skip primary name and class name
                        IsTameable = !UntameableClassNames.Contains(x.Key, StringComparer.OrdinalIgnoreCase)
                    };

                    vms.Creatures.AddRange(x.Value.items.Select(y =>
                    {
                        var vmc = new WildCreatureViewModel
                        {
                            Id1        = y.Id1,
                            Id2        = y.Id2,
                            Gender     = y.Gender.ToString(),
                            BaseLevel  = y.BaseLevel,
                            X          = y.Location?.X.Round(0),
                            Y          = y.Location?.Y.Round(0),
                            Z          = y.Location?.Z.Round(0),
                            IsTameable = y.IsTameable,
                            Latitude   = y.Location?.Latitude,
                            Longitude  = y.Location?.Longitude,
                            TopoMapX   = y.Location?.TopoMapX,
                            TopoMapY   = y.Location?.TopoMapY
                        };
                        if (incWildCreaturesBaseStats)
                        {
                            //0: health
                            //1: stamina
                            //2: torpor
                            //3: oxygen
                            //4: food
                            //5: water
                            //6: temperature
                            //7: weight
                            //8: melee damage
                            //9: movement speed
                            //10: fortitude
                            //11: crafting speed

                            vmc.BaseStats = new CreatureBaseStatsViewModel
                            {
                                Health        = y.BaseStats[0],
                                Stamina       = y.BaseStats[1],
                                Oxygen        = y.BaseStats[3],
                                Food          = y.BaseStats[4],
                                Weight        = y.BaseStats[7],
                                Melee         = y.BaseStats[8],
                                MovementSpeed = y.BaseStats[9]
                            };
                        }

                        return(vmc);
                    }).OrderByDescending(y => y.BaseLevel).ThenBy(y => y.Gender));

                    return(vms);
                }).ToArray();

                foreach (var s in species)
                {
                    result.Species.Add(s.ClassName, s);
                }
            }

            var totalCount = context.WildCreatures.Length;
            var stats      = new WildCreatureStatistics
            {
                CreatureCount = totalCount
            };

            if (incStatistics)
            {
                stats.Species.AddRange(speciesGroups.Select(x =>
                {
                    var vmcs = new WildCreatureSpeciesStatistics
                    {
                        ClassName = x.Key,
                        Name      = x.Value.aliases?.FirstOrDefault(),
                        Aliases   = x.Value.aliases?.Skip(2).ToArray() ?? new string[] { }, //skip primary name and class name
                        Count     = x.Value.items.Count(),
                        Fraction  = x.Value.items.Count() / (float)totalCount
                    };

                    return(vmcs);
                }).OrderBy(x => x.Name).ThenByDescending(x => x.Count));
            }

            result.Statistics = stats;

            return(result);
        }
Example #16
0
        public async Task Run(CommandEventArgs e)
        {
            //if (!e.Channel.IsPrivate) return;

            var args = CommandHelper.ParseArgs(e, new
            {
                ServerKey             = "",
                StartServer           = false,
                ShutdownServer        = false,
                StopServer            = false,
                RestartServer         = false,
                UpdateServer          = false,
                Backups               = false,
                SaveWorld             = false,
                DestroyWildDinos      = false,
                EnableVoting          = false,
                SetVotingAllowed      = 0L, //steam id
                KickPlayer            = 0L, //steam id
                BanPlayer             = 0L, //steam id
                UnbanPlayer           = 0L, //steam id
                KillPlayer            = 0L, //ark player id
                DoExit                = false,
                Broadcast             = "",
                ListPlayers           = false,
                RenamePlayer          = "",
                RenameTribe           = "",
                NewName               = "",
                ServerChat            = "",
                ServerChatTo          = 0L, //steam id
                ServerChatToPlayer    = "",
                Message               = "",
                GetPlayerIDForSteamID = 0L, //steam id
                GetSteamIDForPlayerID = 0L, //ark player id
                GetTribeIdPlayerList  = 0L,
                SetTimeOfDay          = "",
                Countdown             = "",
                True  = false,
                False = false
            }, x =>
                                               x.For(y => y.ServerKey, noPrefix: true, isRequired: true)
                                               .For(y => y.StartServer, flag: true)
                                               .For(y => y.ShutdownServer, flag: true)
                                               .For(y => y.StopServer, flag: true)
                                               .For(y => y.RestartServer, flag: true)
                                               .For(y => y.UpdateServer, flag: true)
                                               .For(y => y.Backups, flag: true)
                                               .For(y => y.SaveWorld, flag: true)
                                               .For(y => y.DestroyWildDinos, flag: true)
                                               .For(y => y.EnableVoting, flag: true)
                                               .For(y => y.DoExit, flag: true)
                                               .For(y => y.ListPlayers, flag: true)
                                               .For(y => y.Broadcast, untilNextToken: true)
                                               .For(y => y.RenamePlayer, untilNextToken: true)
                                               .For(y => y.RenameTribe, untilNextToken: true)
                                               .For(y => y.NewName, untilNextToken: true)
                                               .For(y => y.ServerChat, untilNextToken: true)
                                               .For(y => y.ServerChatToPlayer, untilNextToken: true)
                                               .For(y => y.Message, untilNextToken: true)
                                               .For(y => y.Countdown, untilNextToken: true)
                                               .For(y => y.True, flag: true)
                                               .For(y => y.False, flag: true));

            var _rTimeOfDay = new Regex(@"^\s*\d{2,2}\:\d{2,2}(\:\d{2,2})?\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase);
            var _rCountdown = new Regex(@"^\s*(?<min>\d+)\s+(?<reason>.+)$", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
            var sb          = new StringBuilder();

            var serverContext = args?.ServerKey != null?_contextManager.GetServer(args.ServerKey) : null;

            if (serverContext == null)
            {
                await e.Channel.SendMessage($"**Admin commands need to be prefixed with a valid server instance key.**");

                return;
            }


            if (args.StartServer)
            {
                await _arkServerService.StartServer(serverContext.Config.Key, (s) => e.Channel.SendMessageDirectedAt(e.User.Id, s));
            }
            else if (args.Countdown == null && (args.ShutdownServer || args.StopServer))
            {
                await _arkServerService.ShutdownServer(serverContext.Config.Key, (s) => e.Channel.SendMessageDirectedAt(e.User.Id, s));
            }
            else if (args.Countdown == null && args.RestartServer)
            {
                await _arkServerService.RestartServer(serverContext.Config.Key, (s) => e.Channel.SendMessageDirectedAt(e.User.Id, s));
            }
            else if (args.Countdown == null && args.UpdateServer)
            {
                await _arkServerService.UpdateServer(serverContext.Config.Key, (s) => e.Channel.SendMessageDirectedAt(e.User.Id, s), (s) => e.Channel.GetMessageDirectedAtText(e.User.Id, s), 300);
            }
            else if (args.SaveWorld)
            {
                await _arkServerService.SaveWorld(serverContext.Config.Key, (s) => e.Channel.SendMessageDirectedAt(e.User.Id, s), 180);
            }
            else if (args.Backups)
            {
                var result = _savegameBackupService.GetBackupsList(serverContext.Config.Key);
                if (result?.Count > 0)
                {
                    var data = result.OrderByDescending(x => x.DateModified).Take(25).Select(x => new
                    {
                        Path     = x.Path,
                        Age      = (DateTime.Now - x.DateModified).ToStringCustom(),
                        FileSize = x.ByteSize.ToFileSize()
                    }).ToArray();
                    var table = FixedWidthTableHelper.ToString(data, x => x
                                                               .For(y => y.Path, header: "Backup")
                                                               .For(y => y.Age, alignment: 1)
                                                               .For(y => y.FileSize, header: "File Size", alignment: 1));
                    sb.Append($"```{table}```");
                }
                else
                {
                    sb.AppendLine("**Could not find any savegame backups...**");
                }
            }
            else if (args.DestroyWildDinos)
            {
                var result = await serverContext.Steam.SendRconCommand("destroywilddinos");

                if (result == null)
                {
                    sb.AppendLine("**Failed to wipe wild dinos... :(**");
                }
                else
                {
                    sb.AppendLine("**Wild dinos wiped!**");
                }
            }
            else if (args.DoExit)
            {
                var result = await serverContext.Steam.SendRconCommand("doexit");

                if (result == null)
                {
                    sb.AppendLine("**Failed to shutdown server... :(**");
                }
                else
                {
                    sb.AppendLine("**Server shutting down!**");
                }
            }
            else if (args.ListPlayers)
            {
                var result = await serverContext.Steam.SendRconCommand("listplayers");

                if (result == null)
                {
                    sb.AppendLine("**Failed to get a list of players... :(**");
                }
                else
                {
                    sb.AppendLine(result);
                }
            }
            else if (!string.IsNullOrWhiteSpace(args.Broadcast))
            {
                var result = await serverContext.Steam.SendRconCommand($"broadcast {args.Broadcast}");

                if (result == null)
                {
                    sb.AppendLine("**Failed to broadcast message... :(**");
                }
                else
                {
                    sb.AppendLine("**Broadcast successfull!**");
                }
            }
            else if (!string.IsNullOrWhiteSpace(args.ServerChat))
            {
                var result = await serverContext.Steam.SendRconCommand($"serverchat {args.ServerChat}");

                if (result == null)
                {
                    sb.AppendLine("**Failed to send chat message... :(**");
                }
                else
                {
                    sb.AppendLine("**Chat message send!**");
                }
            }
            else if (args.ServerChatTo > 0 && !string.IsNullOrWhiteSpace(args.Message))
            {
                var result = await serverContext.Steam.SendRconCommand($@"serverchatto {args.ServerChatTo} ""{args.Message}""");

                if (result == null)
                {
                    sb.AppendLine("**Failed to send direct chat message... :(**");
                }
                else
                {
                    sb.AppendLine("**Direct chat message send!**");
                }
            }
            else if (!string.IsNullOrWhiteSpace(args.ServerChatToPlayer) && !string.IsNullOrWhiteSpace(args.Message))
            {
                var result = await serverContext.Steam.SendRconCommand($@"serverchattoplayer ""{args.ServerChatToPlayer}"" ""{args.Message}""");

                if (result == null)
                {
                    sb.AppendLine("**Failed to send direct chat message... :(**");
                }
                else
                {
                    sb.AppendLine("**Direct chat message send!**");
                }
            }
            else if (!string.IsNullOrWhiteSpace(args.RenamePlayer) && !string.IsNullOrWhiteSpace(args.NewName))
            {
                var result = await serverContext.Steam.SendRconCommand($@"renameplayer ""{args.RenamePlayer}"" {args.NewName}");

                if (result == null)
                {
                    sb.AppendLine("**Failed to rename player... :(**");
                }
                else
                {
                    sb.AppendLine("**Player renamed!**");
                }
            }
            else if (!string.IsNullOrWhiteSpace(args.RenameTribe) && !string.IsNullOrWhiteSpace(args.NewName))
            {
                var result = await serverContext.Steam.SendRconCommand($@"renametribe ""{args.RenameTribe}"" {args.NewName}");

                if (result == null)
                {
                    sb.AppendLine("**Failed to rename tribe... :(**");
                }
                else
                {
                    sb.AppendLine("**Tribe renamed!**");
                }
            }
            else if (!string.IsNullOrWhiteSpace(args.SetTimeOfDay) && _rTimeOfDay.IsMatch(args.SetTimeOfDay))
            {
                var result = await serverContext.Steam.SendRconCommand($"settimeofday {args.SetTimeOfDay}");

                if (result == null)
                {
                    sb.AppendLine("**Failed to set time of day... :(**");
                }
                else
                {
                    sb.AppendLine("**Time of day set!**");
                }
            }
            else if (args.KickPlayer > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"kickplayer {args.KickPlayer}");

                if (result == null)
                {
                    sb.AppendLine($"**Failed to kick player with steamid {args.KickPlayer}... :(**");
                }
                else
                {
                    sb.AppendLine($"**Kicked player with steamid {args.KickPlayer}!**");
                }
            }
            else if (args.EnableVoting)
            {
                if (!(args.True || args.False))
                {
                    sb.AppendLine($"**This command requires additional arguments!**");
                }
                else
                {
                    using (var context = _databaseContextFactory.Create())
                    {
                        _savedstate.VotingDisabled = !args.True;
                        _savedstate.Save();
                        sb.AppendLine($"**Voting system is now {(_savedstate.VotingDisabled ? "disabled" : "enabled")}!**");
                    }
                }

                //var result = await CommandHelper.SendRconCommand(_config, $"kickplayer {args.KickPlayer}");
                //if (result == null) sb.AppendLine($"**Failed to kick player with steamid {args.KickPlayer}... :(**");
                //else sb.AppendLine($"**Kicked player with steamid {args.KickPlayer}!**");
            }
            else if (args.SetVotingAllowed > 0)
            {
                if (!(args.True || args.False))
                {
                    sb.AppendLine($"**This command requires additional arguments!**");
                }
                else
                {
                    using (var context = _databaseContextFactory.Create())
                    {
                        var user = context.Users.FirstOrDefault(x => x != null && x.DiscordId == (long)e.User.Id);
                        if (user != null)
                        {
                            user.DisallowVoting = !args.True;
                            context.SaveChanges();
                            sb.AppendLine($"**The user is now {(user.DisallowVoting ? "unable" : "allowed")} to vote!**");
                        }
                        else
                        {
                            sb.AppendLine($"**The user is not linked!**");
                        }
                    }
                }

                //var result = await CommandHelper.SendRconCommand(_config, $"kickplayer {args.KickPlayer}");
                //if (result == null) sb.AppendLine($"**Failed to kick player with steamid {args.KickPlayer}... :(**");
                //else sb.AppendLine($"**Kicked player with steamid {args.KickPlayer}!**");
            }
            else if (args.BanPlayer > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"ban {args.BanPlayer}");

                if (result == null)
                {
                    sb.AppendLine($"**Failed to ban player with steamid {args.BanPlayer}... :(**");
                }
                else
                {
                    sb.AppendLine($"**Banned player with steamid {args.BanPlayer}!**");
                }
            }
            else if (args.UnbanPlayer > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"unban {args.UnbanPlayer}");

                if (result == null)
                {
                    sb.AppendLine($"**Failed to unban player with steamid {args.UnbanPlayer}... :(**");
                }
                else
                {
                    sb.AppendLine($"**Unbanned player with steamid {args.UnbanPlayer}!**");
                }
            }
            else if (args.KillPlayer > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"killplayer {args.KillPlayer}");

                if (result == null)
                {
                    sb.AppendLine($"**Failed to kill player with id {args.KillPlayer}... :(**");
                }
                else
                {
                    sb.AppendLine($"**Killed player with id {args.KillPlayer}!**");
                }
            }
            else if (args.GetSteamIDForPlayerID > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"GetSteamIDForPlayerID {args.GetSteamIDForPlayerID}");

                if (result == null)
                {
                    sb.AppendLine($"**Failed to get steamid from id {args.GetSteamIDForPlayerID}... :(**");
                }
                else
                {
                    sb.AppendLine(result);
                }
            }
            else if (args.GetPlayerIDForSteamID > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"GetPlayerIDForSteamID {args.GetPlayerIDForSteamID}");

                if (result == null)
                {
                    sb.AppendLine($"**Failed to get id from steamid {args.GetPlayerIDForSteamID}... :(**");
                }
                else
                {
                    sb.AppendLine(result);
                }
            }
            else if (args.GetTribeIdPlayerList > 0)
            {
                var result = await serverContext.Steam.SendRconCommand($"GetTribeIdPlayerList {args.GetTribeIdPlayerList}");

                if (result == null)
                {
                    sb.AppendLine("**Failed to get a list of players in tribe... :(**");
                }
                else
                {
                    sb.AppendLine(result);
                }
            }
            else if (!string.IsNullOrEmpty(args.Countdown) && _rCountdown.IsMatch(args.Countdown))
            {
                var m              = _rCountdown.Match(args.Countdown);
                var reason         = m.Groups["reason"].Value;
                var delayInMinutes = int.Parse(m.Groups["min"].Value);
                if (delayInMinutes < 1)
                {
                    delayInMinutes = 1;
                }

                Func <Task> react = null;
                if (args.StopServer || args.ShutdownServer)
                {
                    react = new Func <Task>(async() =>
                    {
                        string message = null;
                        if (!await _arkServerService.ShutdownServer(serverContext.Config.Key, (s) => { message = s; return(Task.FromResult((Message)null)); }))
                        {
                            Logging.Log($@"Countdown to shutdown server ({serverContext.Config.Key}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG);
                        }
                    });
                }
                else if (args.UpdateServer)
                {
                    react = new Func <Task>(async() =>
                    {
                        string message = null;
                        if (!await _arkServerService.UpdateServer(serverContext.Config.Key, (s) => { message = s; return(Task.FromResult((Message)null)); }, (s) => s.FirstCharToUpper(), 300))
                        {
                            Logging.Log($@"Countdown to update server ({serverContext.Config.Key}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG);
                        }
                    });
                }
                else if (args.RestartServer)
                {
                    react = new Func <Task>(async() =>
                    {
                        string message = null;
                        if (!await _arkServerService.RestartServer(serverContext.Config.Key, (s) => { message = s; return(Task.FromResult((Message)null)); }))
                        {
                            Logging.Log($@"Countdown to restart server ({serverContext.Config.Key}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG);
                        }
                    });
                }

                sb.AppendLine($"**Countdown have been initiated. Announcement will be made.**");
                await _scheduledTasksManager.StartCountdown(serverContext, reason, delayInMinutes, react);
            }
            else
            {
                await e.Channel.SendMessage(string.Join(Environment.NewLine, new string[] {
                    $"**My logic circuits cannot process this command! I am just a bot after all... :(**",
                    !string.IsNullOrWhiteSpace(SyntaxHelp) ? $"Help me by following this syntax: **!{Name}** {SyntaxHelp}" : null
                }.Where(x => x != null)));

                return;
            }

            var msg = sb.ToString();

            if (!string.IsNullOrWhiteSpace(msg))
            {
                await CommandHelper.SendPartitioned(e.Channel, sb.ToString());
            }
        }
Example #17
0
        public async Task Run(CommandEventArgs e)
        {
            if (!_context.IsInitialized)
            {
                await e.Channel.SendMessage($"**The data is loading but is not ready yet...**");

                return;
            }

            var serverContext = _contextManager.GetServer(_config.ServerKey);
            var info          = serverContext.Steam.GetServerInfoCached();
            var rules         = serverContext.Steam.GetServerRulesCached();

            var sb = new StringBuilder();

            if (info == null || rules == null)
            {
                sb.AppendLine($"**Server status is currently unavailable!**");
            }
            else
            {
                var m                  = new Regex(@"^(?<name>.+?)\s+-\s+\(v(?<version>\d+\.\d+)\)$", RegexOptions.IgnoreCase | RegexOptions.Singleline).Match(info.Name);
                var name               = m.Success ? m.Groups["name"].Value : info.Name;
                var version            = m.Success ? m.Groups["version"] : null;
                var currentTime        = rules.FirstOrDefault(x => x.Name == "DayTime_s")?.Value;
                var tamedDinosCount    = _context.Creatures?.Count();
                var uploadedDinosCount = _context.Cluster?.Creatures?.Count();
                var wildDinosCount     = _context.Wild?.Count();
                var tamedDinosMax      = 6000; //todo: remove hardcoded value
                var structuresCount    = _context.Tribes?.SelectMany(x => x.Structures).Sum(x => x.Count);
                var totalPlayers       = _context.Players?.Count();
                var totalTribes        = _context.Tribes?.Count();

                //server uptime
                DateTime?serverStarted = null;
                try
                {
                    serverStarted = Process.GetProcessesByName(_constants.ArkServerProcessName)?.FirstOrDefault()?.StartTime;
                }
                catch { /* ignore exceptions */ }

                sb.AppendLine($"**{name}**");
                sb.AppendLine($"● **Address:** {info.Address}");
                if (version != null)
                {
                    sb.AppendLine($"● **Version:** {version}");
                }
                sb.AppendLine($"● **Online:** {info.Players}/{info.MaxPlayers}");
                sb.AppendLine($"● **Map:** {info.Map}");
                if (currentTime != null)
                {
                    sb.AppendLine($"● **In-game time:** {currentTime}");
                }
                if (serverStarted != null)
                {
                    sb.AppendLine($"Server uptime: {(DateTime.Now - serverStarted.Value).ToStringCustom(true)}");
                }

                sb.AppendLine().AppendLine($"**Server Statistics**");
                if (tamedDinosCount.HasValue)
                {
                    sb.AppendLine($"● **Tamed dinos:** {tamedDinosCount.Value:N0}/{tamedDinosMax:N0}");
                }
                if (uploadedDinosCount.HasValue)
                {
                    sb.AppendLine($"● **Uploaded dinos:** {uploadedDinosCount.Value:N0}");
                }
                if (wildDinosCount.HasValue)
                {
                    sb.AppendLine($"● **Wild dinos:** {wildDinosCount.Value:N0}");
                }
                if (structuresCount.HasValue)
                {
                    sb.AppendLine($"● **Structures:** {structuresCount.Value:N0}");
                }
                if (totalPlayers.HasValue)
                {
                    sb.AppendLine($"● **Players:** {totalPlayers.Value:N0}");
                }
                if (totalTribes.HasValue)
                {
                    sb.AppendLine($"● **Tribes:** {totalTribes.Value:N0}");
                }

                var nextUpdate       = _context.ApproxTimeUntilNextUpdate;
                var nextUpdateTmp    = nextUpdate?.ToStringCustom();
                var nextUpdateString = (nextUpdate.HasValue ? (!string.IsNullOrWhiteSpace(nextUpdateTmp) ? $"~{nextUpdateTmp}" : "waiting for new update ...") : null);
                var lastUpdate       = _context.LastUpdate;
                var lastUpdateString = lastUpdate.ToStringWithRelativeDay();

                sb.AppendLine($"● **Last update:** {lastUpdateString}");
                if (nextUpdateString != null)
                {
                    sb.AppendLine($"● **Next update:** {nextUpdateString}");
                }
            }

            await CommandHelper.SendPartitioned(e.Channel, sb.ToString());
        }
Example #18
0
        public async Task <ServerStatusAllViewModel> Get()
        {
            var result = new ServerStatusAllViewModel();

            foreach (var context in _contextManager.Servers)
            {
                var serverContext = _contextManager.GetServer(context.Config.Key);
                var status        = serverContext.Steam.GetServerStatusCached();
                if (status == null || status.Item1 == null || status.Item2 == null)
                {
                    //Server status is currently unavailable
                }
                else
                {
                    var info        = status.Item1;
                    var rules       = status.Item2;
                    var playerinfos = status.Item3;

                    var m               = new Regex(@"^(?<name>.+?)\s+-\s+\(v(?<version>\d+\.\d+)\)$", RegexOptions.IgnoreCase | RegexOptions.Singleline).Match(info.Name);
                    var name            = m.Success ? m.Groups["name"].Value : info.Name;
                    var version         = m.Success ? m.Groups["version"] : null;
                    var currentTime     = rules.FirstOrDefault(x => x.Name == "DayTime_s")?.Value;
                    var tamedDinosCount = context.TamedCreatures?.Count();
                    //var uploadedDinosCount = _context.Cluster?.Creatures?.Count();
                    var wildDinosCount = context.WildCreatures?.Count();
                    //var tamedDinosMax = 6000; //todo: remove hardcoded value
                    var structuresCount = context.Structures?.Count();
                    var totalPlayers    = context.Players?.Count();
                    var totalTribes     = context.Tribes?.Count();

                    //server uptime
                    //DateTime? serverStarted = null;
                    //try
                    //{
                    //    serverStarted = Process.GetProcessesByName(_constants.ArkServerProcessName)?.FirstOrDefault()?.StartTime;

                    //}
                    //catch { /* ignore exceptions */ }

                    var nextUpdate       = context.ApproxTimeUntilNextUpdate;
                    var nextUpdateTmp    = nextUpdate?.ToStringCustom();
                    var nextUpdateString = (nextUpdate.HasValue ? (!string.IsNullOrWhiteSpace(nextUpdateTmp) ? $"~{nextUpdateTmp}" : "waiting for new update ...") : null);
                    var lastUpdate       = context.LastUpdate;
                    var lastUpdateString = lastUpdate.ToStringWithRelativeDay();

                    var sr = new ServerStatusViewModel
                    {
                        Key                = context.Config.Key,
                        Name               = name,
                        Address            = info.Address,
                        Version            = version.ToString(),
                        OnlinePlayerCount  = info.Players,
                        OnlinePlayerMax    = info.MaxPlayers,
                        MapName            = info.Map,
                        InGameTime         = currentTime,
                        TamedCreatureCount = tamedDinosCount ?? 0,
                        WildCreatureCount  = wildDinosCount ?? 0,
                        StructureCount     = structuresCount ?? 0,
                        PlayerCount        = totalPlayers ?? 0,
                        TribeCount         = totalTribes ?? 0,
                        LastUpdate         = lastUpdateString,
                        NextUpdate         = nextUpdateString
                    };

                    var players = playerinfos?.Where(x => !string.IsNullOrEmpty(x.Name)).ToArray() ?? new PlayerInfo[] { };
                    using (var db = _databaseContextFactory.Create())
                    {
                        Dictionary <string, Tuple <ArkPlayer, Database.Model.User, User, long?, TimeSpan, ArkTribe> > d = null;
                        if (context.Players != null)
                        {
                            var playerNames = players.Select(x => x.Name).ToArray();
                            d = context.Players.Where(x => playerNames.Contains(x.Name, StringComparer.Ordinal)).Select(x =>
                            {
                                long steamId;
                                return(new Tuple <ArkPlayer, Database.Model.User, User, long?, TimeSpan, ArkTribe>(
                                           x,
                                           null,
                                           null,
                                           long.TryParse(x.SteamId, out steamId) ? steamId : (long?)null,
                                           TimeSpan.Zero, null));
                            }).ToDictionary(x => x.Item1.Name, StringComparer.OrdinalIgnoreCase);

                            var ids      = new List <ulong>();
                            var steamIds = d.Values.Select(x => x.Item4).Where(x => x != null).ToArray();
                            foreach (var user in db.Users.Where(y => steamIds.Contains(y.SteamId)))
                            {
                                var item = d.Values.FirstOrDefault(x => x.Item4 == user.SteamId);
                                if (item == null)
                                {
                                    continue;
                                }

                                ids.Add(item.Item1.Id);

                                var discordUser         = (User)null;        //e.User?.Client?.Servers?.Select(x => x.GetUser((ulong)user.DiscordId)).FirstOrDefault();
                                var playedLastSevenDays = TimeSpan.MinValue; //TimeSpan.FromSeconds(user?.Played?.OrderByDescending(x => x.Date).Take(7).Sum(x => x.TimeInSeconds) ?? 0);

                                d[item.Item1.Name] = Tuple.Create(item.Item1, user, discordUser, item.Item4, playedLastSevenDays, item.Item1.TribeId.HasValue ? context.Tribes?.FirstOrDefault(x => x.Id == item.Item1.TribeId.Value) : null);
                            }

                            var remaining = d.Values.Where(x => !ids.Contains(x.Item1.Id)).Where(x => x.Item4 != null).Select(x => x.Item4.Value).ToArray();
                            foreach (var user in db.Played.Where(x => x.SteamId.HasValue && remaining.Contains(x.SteamId.Value))
                                     .GroupBy(x => x.SteamId)
                                     .Select(x => new { key = x.Key, items = x.OrderByDescending(y => y.Date).Take(7).ToList() })
                                     .ToArray())
                            {
                                var item = d.Values.FirstOrDefault(x => x.Item4 == user.key);
                                if (item == null)
                                {
                                    continue;
                                }

                                var playedLastSevenDays = TimeSpan.FromSeconds(user?.items?.Sum(x => x.TimeInSeconds) ?? 0);
                                d[item.Item1.Name] = Tuple.Create(item.Item1, item.Item2, item.Item3, item.Item4, playedLastSevenDays, item.Item1.TribeId.HasValue ? context.Tribes?.FirstOrDefault(x => x.Id == item.Item1.TribeId.Value) : null);
                            }
                        }

                        //var playerslist = players.Select(x => {
                        //    var extra = d.ContainsKey(x.Name) ? d[x.Name] : null;
                        //    return new
                        //    {
                        //        Steam = x.Name,
                        //        Name = extra?.Item1?.Name,
                        //        Tribe = extra?.Item1?.TribeName,
                        //        Discord = extra != null && extra.Item3 != null ? $"{extra.Item3.Name}#{extra.Item3.Discriminator}" : null,
                        //        TimeOnline = x.Time.ToStringCustom(),
                        //        PlayedLastSevenDays = extra != null && extra.Item5.TotalMinutes > 1 ? extra?.Item5.ToStringCustom() : null
                        //    };
                        //}).ToArray();

                        foreach (var player in players)
                        {
                            var extra = d?.ContainsKey(player.Name) == true ? d[player.Name] : null;
                            sr.OnlinePlayers.Add(new OnlinePlayerViewModel
                            {
                                SteamName         = player.Name,
                                CharacterName     = extra?.Item1?.Name,
                                TribeName         = extra?.Item6?.Name,
                                DiscordName       = extra != null && extra.Item3 != null ? $"{extra.Item3.Name}#{extra.Item3.Discriminator}" : null,
                                TimeOnline        = player.Time.ToStringCustom(),
                                TimeOnlineSeconds = (int)Math.Round(player.Time.TotalSeconds)
                            });
                        }
                    }

                    result.Servers.Add(sr);
                }
            }

            foreach (var context in _contextManager.Clusters)
            {
                var cc = new ClusterStatusViewModel
                {
                    Key        = context.Config.Key,
                    ServerKeys = _contextManager.Servers
                                 .Where(x => x.Config.Cluster.Equals(context.Config.Key, StringComparison.OrdinalIgnoreCase))
                                 .Select(x => x.Config.Key).ToArray()
                };
                result.Clusters.Add(cc);
            }

            return(result);
        }
Example #19
0
        public async Task <ServerStatusAllViewModel> Get()
        {
            var demoMode = IsDemoMode() ? new DemoMode() : null;

            var anonymize = _config.AnonymizeWebApiData;
            var user      = WebApiHelper.GetUser(HttpContext, _config);

            if (anonymize)
            {
                var serverContext = _contextManager?.Servers?.FirstOrDefault();
                var player        = serverContext?.Players?.Where(x =>
                                                                  x.Tribe != null && x.Tribe.Creatures != null && x.Tribe.Structures != null &&
                                                                  x.Tribe.Creatures.Any(y => y.IsBaby) &&
                                                                  x.Tribe.Structures.OfType <ArkStructureCropPlot>().Any() &&
                                                                  x.Tribe.Structures.OfType <ArkStructureElectricGenerator>().Any()
                                                                  ).OrderByDescending(x => x.Creatures.Length).FirstOrDefault();

                if (player == null)
                {
                    user = null;
                }
                else
                {
                    user.Name    = player.Name;
                    user.SteamId = player.SteamId;
                    user.Roles   = _config?.WebApp?.AccessControl?.SelectMany(x => x.Value.Values)
                                   .SelectMany(x => x)
                                   .Distinct(StringComparer.OrdinalIgnoreCase)
                                   .OrderBy(x => x)
                                   .ToArray();
                }
            }

            var result = new ServerStatusAllViewModel {
                User = user, AccessControl = BuildViewModelForAccessControl(_config)
            };

            if (_contextManager == null)
            {
                return(result);
            }

            if (_contextManager.Servers != null)
            {
                foreach (var context in _contextManager.Servers)
                {
                    var serverContext = _contextManager.GetServer(context.Config.Key);

                    var tamedDinosCount    = context.TamedCreatures?.Count();
                    var uploadedDinosCount = context.CloudCreatures?.Count();
                    var wildDinosCount     = context.WildCreatures?.Count();
                    var structuresCount    = context.Structures?.Count();
                    var totalPlayers       = context.Players?.Count();
                    var totalTribes        = context.Tribes?.Count();
                    var serverStarted      = _serverService.GetServerStartTime(context.Config.Key);

                    var nextUpdate       = context.ApproxTimeUntilNextUpdate;
                    var nextUpdateTmp    = nextUpdate?.ToStringCustom();
                    var nextUpdateString = nextUpdate.HasValue ? !string.IsNullOrWhiteSpace(nextUpdateTmp) ? $"~{nextUpdateTmp}" : "waiting for new update ..." : null;
                    var lastUpdate       = context.LastUpdate;
                    var lastUpdateString = lastUpdate.ToStringWithRelativeDay();

                    var anonymizedServer      = anonymize ? _anonymizeData.GetServer(context.Config.Key) : null;
                    var serverStatusViewModel = new ServerStatusViewModel
                    {
                        Key                = anonymizedServer?.Key ?? context.Config.Key,
                        Name               = anonymizedServer?.Name ?? context.Data.ServerInfo?.ServerName,
                        Address            = anonymizedServer?.Address ?? context.Config.DisplayAddress ?? context.Data.ServerInfo?.Address,
                        Version            = context.Data.ServerInfo != null ? $"{context.Data.ServerInfo.MajorVersion}.{context.Data.ServerInfo.MinorVersion}" : null,
                        OnlinePlayerMax    = context.Data.ServerInfo?.MaxPlayers ?? 0,
                        MapName            = context.Data.ServerInfo?.MapName,
                        InGameTime         = context.Data.ServerInfo?.DayNumber.ToString(),
                        TamedCreatureCount = tamedDinosCount ?? 0,
                        CloudCreatureCount = uploadedDinosCount ?? 0,
                        WildCreatureCount  = wildDinosCount ?? 0,
                        StructureCount     = structuresCount ?? 0,
                        TribeCount         = totalTribes ?? 0,
                        LastUpdate         = lastUpdateString,
                        NextUpdate         = nextUpdateString,
                        ServerStarted      = serverStarted
                    };

                    result.Servers.Add(serverStatusViewModel);
                }
            }


            if (_contextManager.Clusters != null)
            {
                foreach (var context in _contextManager.Clusters)
                {
                    var cc = new ClusterStatusViewModel
                    {
                        Key        = context?.Config?.Key,
                        ServerKeys = _contextManager.Servers
                                     .Where(x => x.Config != null && x.Config.ClusterKey != null && x.Config.ClusterKey.Equals(context.Config.Key, StringComparison.OrdinalIgnoreCase))
                                     .Select(x => x.Config.Key).ToArray()
                    };
                    result.Clusters.Add(cc);
                }
            }

            return(result);
        }
Example #20
0
        public async Task <bool> SaveWorld(string serverKey, Func <string, Task <IUserMessage> > sendMessageDirected, int timeoutSeconds = _saveWorldDefaultTimeoutSeconds, bool noUpdateForThisCall = false)
        {
            //todo: it would be much better is SaveWorld considered if the save request ends up in a queue or not.

            if (timeoutSeconds <= 0)
            {
                timeoutSeconds = _saveWorldDefaultTimeoutSeconds;
            }

            var serverContext = _contextManager.GetServer(serverKey);

            if (serverContext == null)
            {
                if (sendMessageDirected != null)
                {
                    await sendMessageDirected($"could not find server instance {serverKey}");
                }
                return(false);
            }

            if (sendMessageDirected != null)
            {
                await sendMessageDirected($"saving world (may take a while)...");
            }
            try
            {
                //if (noUpdateForThisCall) _context.DisableContextUpdates();
                if (await serverContext.Steam.SendRconCommand("saveworld") == null)
                {
                    //failed to connect/exception/etc.
                    if (sendMessageDirected != null)
                    {
                        await sendMessageDirected($"failed to save world.");
                    }
                    return(false);
                }

                //wait for a save file change event
                Tuple <ArkServerContext, bool, SavegameBackupResult> state = null;
                var now = DateTime.Now;
                while (true)
                {
                    var timeout = TimeSpan.FromSeconds(timeoutSeconds) - (DateTime.Now - now);
                    if (timeout.TotalSeconds <= 0 || !_signaller.Wait(timeout, out state))
                    {
                        if (sendMessageDirected != null)
                        {
                            await sendMessageDirected($"timeout while waiting for savegame write (save status unknown).");
                        }
                        return(false);
                    }
                    if (state?.Item1.Config.Key.Equals(serverKey, StringComparison.OrdinalIgnoreCase) != true)
                    {
                        continue;
                    }
                    if (_config.Backups.Enabled && !(state?.Item3?.ArchivePaths?.Length >= 1))
                    {
                        if (sendMessageDirected != null)
                        {
                            await sendMessageDirected($"savegame backup failed...");
                        }
                        return(false);
                    }

                    break;
                }
            }
            finally
            {
                //if (noUpdateForThisCall) _context.EnableContextUpdates();
            }

            if (sendMessageDirected != null)
            {
                await sendMessageDirected($"world saved!");
            }
            return(true);
        }
Example #21
0
        public ServerViewModel Get(string id) //, int? limit)
        {
            var context = _contextManager.GetServer(id);

            if (context == null)
            {
                return(null);
            }

            var demoMode = IsDemoMode() ? new DemoMode() : null;
            var result   = new AdminServerViewModel
            {
            };

            var creatureCounts  = context.NoRafts?.GroupBy(x => x.TargetingTeam).ToDictionary(x => x.Key, x => x.Count());
            var structureCounts = context.Structures?.Where(x => x.TargetingTeam.HasValue).GroupBy(x => x.TargetingTeam.Value).ToDictionary(x => x.Key, x => x.Count());

            if (HasFeatureAccess("admin-server", "players") && context.Players != null)
            {
                result.Players.AddRange(context.Players.Select(x =>
                {
                    int cc1 = 0, cc2 = 0, sc1 = 0, sc2 = 0;
                    creatureCounts?.TryGetValue(x.Id, out cc1);
                    structureCounts?.TryGetValue(x.Id, out sc1);
                    if (x.TribeId.HasValue)
                    {
                        creatureCounts?.TryGetValue(x.TribeId.Value, out cc2);
                        structureCounts?.TryGetValue(x.TribeId.Value, out sc2);
                    }

                    var tribe = x.TribeId != null ? context.Tribes?.FirstOrDefault(y => y.Id == x.TribeId) : null;
                    return(new AdminPlayerReferenceViewModel
                    {
                        Id = x.Id,
                        SteamId = x.SteamId,
                        FakeSteamId = demoMode?.GetSteamId(x.SteamId),
                        CharacterName = demoMode?.GetPlayerName(x.Id) ?? x.CharacterName,
                        SteamName = null,
                        TribeName = tribe != null ? demoMode?.GetTribeName(tribe.Id) ?? tribe.Name : null,
                        TribeId = x.TribeId,
                        CreatureCount = cc1 + cc2,
                        StructureCount = sc1 + sc2,
                        LastActiveTime = x.LastActiveTime
                    });
                }).OrderByDescending(x => x.LastActiveTime));
            }

            if (HasFeatureAccess("admin-server", "tribes") && context.Tribes != null)
            {
                result.Tribes.AddRange(context.Tribes.Select(x =>
                {
                    int cc1 = 0, sc1 = 0;
                    creatureCounts?.TryGetValue(x.Id, out cc1);
                    structureCounts?.TryGetValue(x.Id, out sc1);
                    foreach (var m in x.MemberIds)
                    {
                        int cc2 = 0, sc2 = 0;
                        creatureCounts?.TryGetValue(m, out cc2);
                        structureCounts?.TryGetValue(m, out sc2);
                        cc1 += cc2;
                        sc1 += sc2;
                    }

                    var members = context.Players?.Where(y => x.MemberIds.Contains(y.Id)).ToList() ?? new List <ArkPlayer>();
                    return(new AdminTribeReferenceViewModel
                    {
                        Id = x.Id,
                        Name = demoMode?.GetTribeName(x.Id) ?? x.Name,
                        MemberSteamIds = members.Select(y => y.SteamId).ToList(),
                        CreatureCount = cc1,
                        StructureCount = sc1,
                        LastActiveTime = x.LastActiveTime
                    });
                }).OrderByDescending(x => x.LastActiveTime));
            }

            return(result);
        }
Example #22
0
        public async Task Run(CommandEventArgs e)
        {
            if (_savedstate.VotingDisabled)
            {
                await e.Channel.SendMessageDirectedAt(e.User.Id, $"the voting system is currently disabled.");

                return;
            }

            //!vote ban24h <player name> reason <text>
            //!votes
            //!vote alpha yes
            //!vote alpha no
            var args = CommandHelper.ParseArgs(e, new { ServerKey = "", Ban = "", Ban24h = "", Unban = "", SetTimeOfDay = "", DestroyWildDinos = false, UpdateServer = false, RestartServer = false, Reason = "", Yes = false, No = false, Veto = false, History = false,
                                                        Alfa      = false, Bravo = false, Charlie = false, Delta = false, Echo = false, Foxtrot = false, Golf = false, Hotel = false, India = false,
                                                        Juliett   = false, Kilo = false, Lima = false, Mike = false, November = false, Oscar = false, Papa = false, Quebec = false, Romeo = false,
                                                        Sierra    = false, Tango = false, Uniform = false, Victor = false, Whiskey = false, Xray = false, Yankee = false, Zulu = false }, x =>
                                               x.For(y => y.ServerKey, noPrefix: true)
                                               .For(y => y.Ban, untilNextToken: true)
                                               .For(y => y.Unban, untilNextToken: true)
                                               .For(y => y.Ban24h, untilNextToken: true)
                                               .For(y => y.Reason, untilNextToken: true)
                                               .For(y => y.DestroyWildDinos, flag: true)
                                               .For(y => y.UpdateServer, flag: true)
                                               .For(y => y.RestartServer, flag: true)
                                               .For(y => y.Yes, flag: true)
                                               .For(y => y.No, flag: true)
                                               .For(y => y.Veto, flag: true)
                                               .For(y => y.History, flag: true)
                                               .For(y => y.Alfa, flag: true)
                                               .For(y => y.Bravo, flag: true)
                                               .For(y => y.Charlie, flag: true)
                                               .For(y => y.Delta, flag: true)
                                               .For(y => y.Echo, flag: true)
                                               .For(y => y.Foxtrot, flag: true)
                                               .For(y => y.Golf, flag: true)
                                               .For(y => y.Hotel, flag: true)
                                               .For(y => y.India, flag: true)
                                               .For(y => y.Juliett, flag: true)
                                               .For(y => y.Kilo, flag: true)
                                               .For(y => y.Lima, flag: true)
                                               .For(y => y.Mike, flag: true)
                                               .For(y => y.November, flag: true)
                                               .For(y => y.Oscar, flag: true)
                                               .For(y => y.Papa, flag: true)
                                               .For(y => y.Quebec, flag: true)
                                               .For(y => y.Romeo, flag: true)
                                               .For(y => y.Sierra, flag: true)
                                               .For(y => y.Tango, flag: true)
                                               .For(y => y.Uniform, flag: true)
                                               .For(y => y.Victor, flag: true)
                                               .For(y => y.Whiskey, flag: true)
                                               .For(y => y.Xray, flag: true)
                                               .For(y => y.Yankee, flag: true)
                                               .For(y => y.Zulu, flag: true));

            var identifiers = args.Alfa || args.Bravo || args.Charlie || args.Delta || args.Echo || args.Foxtrot || args.Golf || args.Hotel || args.India ||
                              args.Juliett || args.Kilo || args.Lima || args.Mike || args.November || args.Oscar || args.Papa || args.Quebec || args.Romeo ||
                              args.Sierra || args.Tango || args.Uniform || args.Victor || args.Whiskey || args.Xray || args.Yankee || args.Zulu;

            var identifierStrings = TypeDescriptor.GetProperties(args.GetType()).OfType <PropertyDescriptor>().Where(x => _identifierStrings.Contains(x.Name, StringComparer.OrdinalIgnoreCase) && x.PropertyType == typeof(bool) && (bool)x.GetValue(args)).Select(x => x.Name).ToArray();
            var voteStrings       = TypeDescriptor.GetProperties(args.GetType()).OfType <PropertyDescriptor>().Where(x => _voteStrings.Contains(x.Name, StringComparer.OrdinalIgnoreCase) && x.PropertyType == typeof(bool) && (bool)x.GetValue(args)).Select(x => x.Name).ToArray();

            var isAdminOrDev = _discord.Servers.Any(x => x.Roles.Any(y => y != null && new[] { _config.AdminRoleName, _config.DeveloperRoleName }.Contains(y.Name, StringComparer.OrdinalIgnoreCase) == true && y.Members.Any(z => z.Id == e.User.Id)));

            if (args == null || (identifiers && (voteStrings.Length == 0 || voteStrings.Length > 1 || identifierStrings.Length == 0 || identifierStrings.Length > 1))  //votes require an identifier and a Yes/No/Veto
                )
            {
                await e.Channel.SendMessage(string.Join(Environment.NewLine, new string[] {
                    $"**My logic circuits cannot process this command! I am just a bot after all... :(**",
                    !string.IsNullOrWhiteSpace(SyntaxHelp) ? $"Help me by following this syntax: **!{Name}** {SyntaxHelp}" : null
                }.Where(x => x != null)));

                return;
            }

            var now = DateTime.Now;
            var sb  = new StringBuilder();

            //this should match any type of vote
            if (!string.IsNullOrWhiteSpace(args.Ban) || !string.IsNullOrWhiteSpace(args.Ban24h) || !string.IsNullOrWhiteSpace(args.Unban) || !string.IsNullOrWhiteSpace(args.SetTimeOfDay) || args.DestroyWildDinos || args.UpdateServer || args.RestartServer)
            {
                var serverContext = args?.ServerKey != null?_contextManager.GetServer(args.ServerKey) : null;

                if (serverContext == null)
                {
                    await e.Channel.SendMessageDirectedAt(e.User.Id, $"**Votes need to be prefixed with a server instance key.**");

                    return;
                }
                if (!serverContext.IsInitialized)
                {
                    await e.Channel.SendMessage($"The server data is loading but is not ready yet...");

                    return;
                }

                if (string.IsNullOrWhiteSpace(args.Reason))
                {
                    await e.Channel.SendMessageDirectedAt(e.User.Id, $"specifying a reason is mandatory when starting a vote.");

                    return;
                }

                //is the user allowed to start a vote?
                //level >= 50 && days registered >= 7

                //is the username valid?

                //is there already an ongoing vote for the same thing?
                using (var db = _databaseContextFactory.Create())
                {
                    var user = db.Users.FirstOrDefault(x => x.DiscordId == (long)e.User.Id && !x.Unlinked);
                    if (user == null)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"this command can only be used after you link your Discord user with your Steam account using **!linksteam**.");

                        return;
                    }

                    if (user.DisallowVoting)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"you are not allowed to vote.");

                        return;
                    }

                    if (!isAdminOrDev)
                    {
                        var player = serverContext.Players.FirstOrDefault(x => x.SteamId != null && x.SteamId.Equals(user.SteamId.ToString()));
                        if (player == null)
                        {
                            await e.Channel.SendMessageDirectedAt(e.User.Id, $"we have no record of you playing in the last month which is a requirement for using this command.");

                            return;
                        }

                        if (player.CharacterLevel < 50)
                        {
                            await e.Channel.SendMessageDirectedAt(e.User.Id, $"you have to reach level 50 in order to initiate votes.");

                            return;
                        }

                        var firstPlayed = user.Played?.Count > 0 ? user.Played?.Min(x => x.Date) : null;
                        if (!firstPlayed.HasValue || (now - user.Played.Min(x => x.Date)).TotalDays < 7d)
                        {
                            await e.Channel.SendMessageDirectedAt(e.User.Id, $"you have to have played for atleast seven days in order to initiate votes.");

                            return;
                        }
                    }

                    var availableIdentifiers = _identifierStrings.Except(db.Votes.Where(x => x.Result == VoteResult.Undecided).Select(x => x.Identifier).ToArray(), StringComparer.OrdinalIgnoreCase).ToArray();
                    var identifier           = availableIdentifiers.Length > 0 ? availableIdentifiers.ElementAt(_rnd.Next(availableIdentifiers.Length)) : null;
                    if (identifier == null)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"there are too many active votes at the moment. Please try again later.");

                        return;
                    }

                    InitiateVoteResult result = null;

                    //handling of specific types
                    if (!string.IsNullOrWhiteSpace(args.Ban))
                    {
                        result = await BanVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason, args.Ban, 365 * 24 * 50);
                    }
                    else if (!string.IsNullOrWhiteSpace(args.Ban24h))
                    {
                        result = await BanVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason, args.Ban24h, 24);
                    }
                    else if (!string.IsNullOrWhiteSpace(args.Unban))
                    {
                        result = await UnbanVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason, args.Unban);
                    }
                    else if (!string.IsNullOrWhiteSpace(args.SetTimeOfDay))
                    {
                        result = await SetTimeOfDayVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason, args.SetTimeOfDay);
                    }
                    else if (args.DestroyWildDinos)
                    {
                        result = await DestroyWildDinosVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason);
                    }
                    else if (args.UpdateServer)
                    {
                        result = await UpdateServerVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason);
                    }
                    else if (args.RestartServer)
                    {
                        result = await RestartServerVoteHandler.Initiate(e.Channel, serverContext, _config, db, e.User.Id, identifier, now, args.Reason);
                    }
                    else
                    {
                        //this should never happen
                        throw new ApplicationException("The vote type is not handled in code...");
                    }

                    if (result == null || result.Vote == null)
                    {
                        return;
                    }

                    result.Vote.Votes.Add(new UserVote
                    {
                        InitiatedVote = true,
                        Reason        = args.Reason,
                        VotedFor      = true,
                        User          = user,
                        UserId        = user.Id,
                        VoteType      = isAdminOrDev ? UserVoteType.Admin : UserVoteType.Trusted,
                        When          = now
                    });

                    db.Votes.Add(result.Vote);
                    db.SaveChanges();

                    if (!string.IsNullOrWhiteSpace(result.MessageInitiator))
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, result.MessageInitiator);
                    }

                    try
                    {
                        if (!string.IsNullOrWhiteSpace(result.MessageRcon))
                        {
                            await serverContext.Steam.SendRconCommand($"serverchat {result.MessageRcon.ReplaceRconSpecialChars()}");
                        }

                        if (!string.IsNullOrWhiteSpace(result.MessageAnnouncement) && !string.IsNullOrWhiteSpace(_config.AnnouncementChannel))
                        {
                            var channels = _discord.Servers.Select(x => x.TextChannels.FirstOrDefault(y => _config.AnnouncementChannel.Equals(y.Name, StringComparison.OrdinalIgnoreCase))).Where(x => x != null);
                            foreach (var channel in channels)
                            {
                                await channel.SendMessage(result.MessageAnnouncement);
                            }
                        }
                    }
                    catch { /*ignore all exceptions */ }

                    serverContext.OnVoteInitiated(result.Vote);

                    return;
                }
            }
            else if (identifiers && (args.Yes || args.No || args.Veto))
            {
                if (!_context.IsInitialized)
                {
                    await e.Channel.SendMessage($"The server data is loading but is not ready yet...");

                    return;
                }

                //does the identifier match an ongoing vote?

                //have the user already voted?
                using (var db = _databaseContextFactory.Create())
                {
                    var identifier = identifierStrings.First();
                    var allvotes   = db.Votes.ToArray();
                    var votes      = db.Votes.Where(x => x.Result == VoteResult.Undecided && x.Finished > now && x.Identifier.Equals(identifier, StringComparison.OrdinalIgnoreCase)).ToArray();
                    if (votes.Length == 0)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"there is no active vote with the given identifier.");

                        return;
                    }
                    if (votes.Length > 1)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"there are multiple active votes with this identifier. This is a bug and the vote cannot be cast.");

                        return;
                    }
                    var vote = votes.First();

                    if (args.Veto && !isAdminOrDev)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"you do not have this permission.");

                        return;
                    }

                    var user = db.Users.FirstOrDefault(x => x.DiscordId == (long)e.User.Id && !x.Unlinked);
                    if (user == null)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"this command can only be used after you link your Discord user with your Steam account using **!linksteam**.");

                        return;
                    }

                    if (user.DisallowVoting)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"you are not allowed to vote.");

                        return;
                    }

                    //todo: players are only considered for one server
                    var player = _context.Players.FirstOrDefault(x => x.SteamId != null && x.SteamId.Equals(user.SteamId.ToString()));
                    if (player == null)
                    {
                        await e.Channel.SendMessageDirectedAt(e.User.Id, $"we have no record of you playing in the last month which is a requirement for using this command.");

                        return;
                    }

                    string   message  = null;
                    UserVote uservote = null;
                    if ((uservote = vote.Votes.FirstOrDefault(x => x.UserId == user.Id)) != null)
                    {
                        //await e.Channel.SendMessageDirectedAt(e.User.Id, $"you have already voted.");
                        //return;

                        uservote.Reason   = args.Reason;
                        uservote.VotedFor = args.Veto ? false : args.Yes;
                        uservote.Vetoed   = args.Veto;
                        uservote.When     = now;

                        message = $"your vote has been changed!";
                    }
                    else
                    {
                        var firstPlayed = user.Played?.Count > 0 ? user.Played.Min(x => x.Date) : (DateTime?)null;

                        vote.Votes.Add(new UserVote
                        {
                            InitiatedVote = false,
                            Reason        = args.Reason,
                            VotedFor      = args.Veto ? false : args.Yes,
                            Vetoed        = args.Veto,
                            User          = user,
                            UserId        = user.Id,
                            VoteType      = isAdminOrDev ? UserVoteType.Admin : !firstPlayed.HasValue || (now - user.Played.Min(x => x.Date)).TotalDays < 7d ? UserVoteType.NewMember : player.Level < 50 ? UserVoteType.Member : UserVoteType.Trusted,
                            When          = now
                        });

                        message = $"your vote has been recorded!";
                    }
                    db.SaveChanges();

                    if (args.Veto)
                    {
                        var serverContext = _contextManager.GetServer(vote.ServerKey);
                        if (serverContext != null)
                        {
                            serverContext.OnVoteResultForced(vote, VoteResult.Vetoed);
                            message = $"you have vetoed this vote.";
                        }
                        else
                        {
                            message = $"could not veto vote because there was no server key.";
                        }
                    }

                    await e.Channel.SendMessageDirectedAt(e.User.Id, message);
                }
            }
            else
            {
                using (var db = _databaseContextFactory.Create())
                {
                    if (args.History)
                    {
                        var votes = db.Votes.OrderByDescending(x => x.Started).Where(x => x.Result != VoteResult.Undecided && System.Data.Entity.DbFunctions.DiffDays(now, x.Started) <= 7).ToArray();
                        if (votes.Length == 0)
                        {
                            await e.Channel.SendMessageDirectedAt(e.User.Id, $"there appear to be no history of votes from the last seven days.");

                            return;
                        }

                        sb.AppendLine("**Previous votes**");
                        sb.AppendLine("--------------------");
                        foreach (var vote in votes)
                        {
                            sb.AppendLine($"***{vote.Started:yyyy-MM-dd HH:mm}***");
                            sb.AppendLine("**" + vote.ToString() + "**");
                            sb.AppendLine(vote.Result == VoteResult.Passed ? ":white_check_mark: The vote passed" : vote.Result == VoteResult.Failed ? ":x: The vote failed" : vote.Result == VoteResult.Vetoed ? ":x: The vote was vetoed" : "Result is unknown").AppendLine();
                        }
                    }
                    else
                    {
                        var votes = db.Votes.OrderByDescending(x => x.Started).Where(x => x.Result == VoteResult.Undecided).ToArray();
                        if (votes.Length == 0)
                        {
                            await e.Channel.SendMessageDirectedAt(e.User.Id, $"there are no active votes at this time.");

                            return;
                        }

                        sb.AppendLine("**Active Votes**");
                        sb.AppendLine("--------------------");
                        foreach (var vote in votes)
                        {
                            sb.AppendLine("**" + vote.ToString() + "**");
                            sb.AppendLine($"To vote use the command: **!vote {vote.Identifier} yes**/**no**").AppendLine();
                        }
                    }
                }
            }

            var msg = sb.ToString();

            if (!string.IsNullOrWhiteSpace(msg))
            {
                await CommandHelper.SendPartitioned(e.Channel, sb.ToString());
            }
        }
Example #23
0
        public async Task <ServerStatusAllViewModel> Get()
        {
            var demoMode = IsDemoMode() ? new DemoMode() : null;

            var anonymize = _config.AnonymizeWebApiData;
            var user      = WebApiHelper.GetUser(Request, _config);

            if (anonymize)
            {
                var serverContext = _contextManager.Servers.FirstOrDefault();
                var player        = serverContext?.Players.Where(x =>
                                                                 x.Tribe != null &&
                                                                 x.Tribe.Creatures.Any(y => y.IsBaby) &&
                                                                 x.Tribe.Structures.OfType <ArkStructureCropPlot>().Any() &&
                                                                 x.Tribe.Structures.OfType <ArkStructureElectricGenerator>().Any()
                                                                 ).OrderByDescending(x => x.Creatures.Length).FirstOrDefault();

                if (player == null)
                {
                    user = null;
                }
                else
                {
                    user.Name    = player.Name;
                    user.SteamId = player.SteamId;
                    user.Roles   = _config.AccessControl.SelectMany(x => x.Value.Values)
                                   .SelectMany(x => x)
                                   .Distinct(StringComparer.OrdinalIgnoreCase)
                                   .OrderBy(x => x)
                                   .ToArray();
                }
            }

            var result = new ServerStatusAllViewModel {
                User = user, AccessControl = BuildViewModelForAccessControl(_config)
            };

            foreach (var context in _contextManager.Servers)
            {
                var serverContext = _contextManager.GetServer(context.Config.Key);
                var status        = serverContext.Steam.GetServerStatusCached();
                //if (status == null || status.Item1 == null || status.Item2 == null)
                //{
                //    //Server status is currently unavailable
                //}
                //else
                //{
                var info        = status?.Item1;
                var rules       = status?.Item2;
                var playerinfos = status?.Item3;

                var m                  = info != null ? new Regex(@"^(?<name>.+?)\s+-\s+\(v(?<version>\d+\.\d+)\)?$", RegexOptions.IgnoreCase | RegexOptions.Singleline).Match(info.Name) : null;
                var name               = m?.Success == true ? m.Groups["name"].Value : (info?.Name ?? context.Config.Key);
                var version            = m?.Success == true ? m.Groups["version"] : null;
                var currentTime        = rules?.FirstOrDefault(x => x.Name == "DayTime_s")?.Value;
                var tamedDinosCount    = context.TamedCreatures?.Count();
                var uploadedDinosCount = context.CloudCreatures?.Count();
                var wildDinosCount     = context.WildCreatures?.Count();
                //var tamedDinosMax = 6000; //todo: remove hardcoded value
                var structuresCount = context.Structures?.Count();
                var totalPlayers    = context.Players?.Count();
                var totalTribes     = context.Tribes?.Count();
                var serverStarted   = _serverService.GetServerStartTime(context.Config.Key);

                var nextUpdate       = context.ApproxTimeUntilNextUpdate;
                var nextUpdateTmp    = nextUpdate?.ToStringCustom();
                var nextUpdateString = (nextUpdate.HasValue ? (!string.IsNullOrWhiteSpace(nextUpdateTmp) ? $"~{nextUpdateTmp}" : "waiting for new update ...") : null);
                var lastUpdate       = context.LastUpdate;
                var lastUpdateString = lastUpdate.ToStringWithRelativeDay();

                var anonymizedServer = anonymize ? _anonymizeData.GetServer(context.Config.Key) : null;
                var sr = new ServerStatusViewModel
                {
                    Key                = anonymizedServer?.Key ?? context.Config.Key,
                    Name               = anonymizedServer?.Name ?? name,
                    Address            = anonymizedServer?.Address ?? context.Config.DisplayAddress ?? info?.Address,
                    Version            = version?.ToString(),
                    OnlinePlayerCount  = info?.Players ?? 0,
                    OnlinePlayerMax    = info?.MaxPlayers ?? 0,
                    MapName            = info?.Map,
                    InGameTime         = currentTime,
                    TamedCreatureCount = tamedDinosCount ?? 0,
                    CloudCreatureCount = uploadedDinosCount ?? 0,
                    WildCreatureCount  = wildDinosCount ?? 0,
                    StructureCount     = structuresCount ?? 0,
                    PlayerCount        = totalPlayers ?? 0,
                    TribeCount         = totalTribes ?? 0,
                    LastUpdate         = lastUpdateString,
                    NextUpdate         = nextUpdateString,
                    ServerStarted      = serverStarted
                };

                if (HasFeatureAccess("home", "online"))
                {
                    var onlineplayers = playerinfos?.Where(x => !string.IsNullOrEmpty(x.Name)).ToArray() ?? new PlayerInfo[] { };
                    if (anonymize)
                    {
                        int n = 0;
                        foreach (var player in context.Players.OrderByDescending(x => x.LastActiveTime).Take(onlineplayers.Length))
                        {
                            sr.OnlinePlayers.Add(new OnlinePlayerViewModel
                            {
                                SteamName         = player.Name,
                                CharacterName     = player.CharacterName,
                                TribeName         = player.Tribe?.Name,
                                DiscordName       = null,
                                TimeOnline        = onlineplayers[n].Time.ToStringCustom(),
                                TimeOnlineSeconds = (int)Math.Round(onlineplayers[n].Time.TotalSeconds)
                            });

                            n++;
                        }
                    }
                    else
                    {
                        using (var db = _databaseContextFactory.Create())
                        {
                            // Names of online players (steam does not provide ids)
                            var onlineplayerNames = onlineplayers.Select(x => x.Name).ToArray();

                            // Get the player data for each name (null when no matching name or when multiple players share the same name)
                            var onlineplayerData = context.Players != null ? (from k in onlineplayerNames join p in context.Players on k equals p.Name into grp select grp.Count() == 1 ? grp.ElementAt(0) : null).ToArray() : new ArkPlayer[] { };

                            // Parse all steam ids
                            var parsedSteamIds = onlineplayerData.Select(x => { long steamId; return(x?.SteamId != null ? long.TryParse(x.SteamId, out steamId) ? steamId : (long?)null : null); }).ToArray();

                            // Get the player data for each name
                            var databaseUsers = (from k in parsedSteamIds join u in db.Users on k equals u?.SteamId into grp select grp.FirstOrDefault()).ToArray();

                            // Get the discord users
                            var discordUsers = databaseUsers.Select(x => x != null ? _discordManager.GetDiscordUserNameById((ulong)x.DiscordId) : null).ToArray();

                            int n = 0;
                            foreach (var player in onlineplayers)
                            {
                                var extra          = onlineplayerData.Length > n ? new { player = onlineplayerData[n], user = databaseUsers[n], discordName = discordUsers[n] } : null;
                                var demoPlayerName = demoMode?.GetPlayerName();

                                sr.OnlinePlayers.Add(new OnlinePlayerViewModel
                                {
                                    SteamName         = demoPlayerName ?? player.Name,
                                    CharacterName     = demoPlayerName ?? extra?.player?.CharacterName,
                                    TribeName         = demoMode?.GetTribeName() ?? extra?.player?.Tribe?.Name,
                                    DiscordName       = demoMode != null ? null : extra?.discordName,
                                    TimeOnline        = player.Time.ToStringCustom(),
                                    TimeOnlineSeconds = (int)Math.Round(player.Time.TotalSeconds)
                                });

                                n++;
                            }
                        }
                    }
                }
                else
                {
                    sr.OnlinePlayers = null;
                }

                result.Servers.Add(sr);
                //}
            }

            foreach (var context in _contextManager.Clusters)
            {
                var cc = new ClusterStatusViewModel
                {
                    Key        = context.Config.Key,
                    ServerKeys = _contextManager.Servers
                                 .Where(x => x.Config.ClusterKey.Equals(context.Config.Key, StringComparison.OrdinalIgnoreCase))
                                 .Select(x => x.Config.Key).ToArray()
                };
                result.Clusters.Add(cc);
            }

            return(result);
        }
Example #24
0
        public async Task Run(CommandEventArgs e)
        {
            var args = CommandHelper.ParseArgs(e, new { ServerKey = "" }, x =>
                                               x.For(y => y.ServerKey, noPrefix: true, isRequired: false));

            var serverContext = _contextManager.GetServer(args.ServerKey ?? _config.ServerKey);

            if (serverContext == null)
            {
                await e.Channel.SendMessage($"**Specified server instance key is not valid.**");

                return;
            }

            if (!serverContext.IsInitialized)
            {
                await e.Channel.SendMessage($"**The data is loading but is not ready yet...**");

                return;
            }

            var player = await CommandHelper.GetCurrentPlayerOrSendErrorMessage(e, _databaseContextFactory, serverContext);

            if (player == null)
            {
                return;
            }


            var playercreatures = serverContext.NoRafts.Where(x => (ulong)x.TargetingTeam == player.Id || (x.OwningPlayerId.HasValue && (ulong)x.OwningPlayerId == player.Id)).ToArray();
            var tribecreatures  = player.TribeId.HasValue ? serverContext.NoRafts.Where(x => x.TargetingTeam == player.TribeId.Value && !playercreatures.Any(y => y.Id == x.Id)).ToArray() : new ArkTamedCreature[] { };

            var mydinos = playercreatures.Select(x => new { c = x, o = "player" }).Concat(tribecreatures.Select(x => new { c = x, o = "tribe" })).Select(item =>
            {
                var currentFood = item.c.CurrentStatusValues?.Length > 4 ? item.c.CurrentStatusValues[4] : null;
                var maxFood     = item.c.BaseStats?.Length > 4 && item.c.TamedStats?.Length > 4 ?
                                  ArkContext.CalculateMaxStat(
                    ArkSpeciesStatsData.Stat.Food,
                    item.c.ClassName,
                    item.c.BaseStats[4],
                    item.c.TamedStats[4],
                    (decimal)(item.c.DinoImprintingQuality ?? 0f),
                    (decimal)(item.c.TamedIneffectivenessModifier ?? 0f)) : null;

                //baby food formula: max * 0.1 + (max - (max * 0.1)) * age
                if (maxFood.HasValue && item.c.BabyAge.HasValue)
                {
                    maxFood = maxFood.Value * 0.1 + (maxFood.Value - (maxFood.Value * 0.1)) * item.c.BabyAge.Value;
                }

                var fs = currentFood.HasValue && maxFood.HasValue ? currentFood.Value / (float)maxFood.Value : (float?)null;
                if (fs.HasValue && fs > 1f)
                {
                    fs = 1f;
                }

                var aliases = ArkSpeciesAliases.Instance.GetAliases(item.c.ClassName);
                return(new { c = item.c, o = item.o, food = fs });
            }).ToArray();

            //var mydinos = serverContext.NoRafts
            //    .Where(x => ((x.OwningPlayerId.HasValue && x.OwningPlayerId.Value == player.Id) || (x.Team.Value == player.TribeId)) && !x.IsBaby)
            //    .Select(x =>
            //    {
            //        //!_context.ArkSpeciesStatsData.SpeciesStats.Any(y => y.Name.Equals(x.SpeciesName, StringComparison.OrdinalIgnoreCase)) ? _context.ArkSpeciesStatsData.SpeciesStats.Select(y => new { name = y.Name, similarity = StatisticsHelper.CompareToCharacterSequence(x.Name, x.SpeciesName.ToCharArray()) }).OrderByDescending(y => y.similarity).FirstOrDefault()?.name : null;
            //        return new
            //        {
            //            creature = x,
            //            maxFood = ArkContext.CalculateMaxStat(Data.ArkSpeciesStatsData.Stat.Food, x.SpeciesClass ?? x.SpeciesName, x.WildLevels?.Food, x.TamedLevels?.Food, x.ImprintingQuality, x.TamedIneffectivenessModifier)
            //        };
            //    })
            //    .ToArray();
            //var foodStatus = mydinos?.Where(x => x.creature.CurrentFood.HasValue && x.maxFood.HasValue).Select(x => (double)x.creature.CurrentFood.Value / x.maxFood.Value)
            //    .Where(x => x <= 1d).OrderBy(x => x).ToArray();
            //var starving = mydinos?.Where(x => x.creature.CurrentFood.HasValue && x.maxFood.HasValue).Select(x => new { creature = x.creature, p = (double)x.creature.CurrentFood.Value / x.maxFood.Value })
            //    .Where(x => x.p <= (1 / 2d)).OrderBy(x => x.p).ToArray(); //any dino below 1/2 food is considered to be starving
            var foodStatus = mydinos.Where(x => x.food.HasValue).Select(x => x.food.Value).OrderBy(x => x).ToArray();
            var starving   = mydinos.Where(x => !x.food.HasValue || x.food <= (1 / 2d)).OrderBy(x => x.food).ToArray(); //any dino below 1/2 food is considered to be starving

            if (foodStatus.Length <= 0)
            {
                await e.Channel.SendMessage($"<@{e.User.Id}>, we could not get the food status of your dinos! :(");

                return;
            }

            var min = foodStatus.Min();
            var avg = foodStatus.Average();
            var max = foodStatus.Max();

            var stateFun = min <= 0.25 ? "starving... :(" : min <= 0.5 ? "hungry... :|" : min <= 0.75 ? "feeling satisfied :)" : "feeling happy! :D";

            var sb = new StringBuilder();

            sb.AppendLine($"**Your dinos are {stateFun}**");
            sb.AppendLine($"{min:P0} ≤ {avg:P0} ≤ {max:P0}");
            if (starving.Length > 0)
            {
                var tmp = starving.Select(x =>
                {
                    var aliases = ArkSpeciesAliases.Instance.GetAliases(x.c.ClassName);
                    return($"{x.c.Name ?? aliases.FirstOrDefault() ?? x.c.ClassName}, lvl {x.c.Level}" + $" ({(x.food.HasValue ? x.food.Value.ToString("P0") : "Unknown")})");
                }).ToArray().Join((n, l) => n == l ? " and " : ", ");
                sb.AppendLine(tmp);
            }

            await CommandHelper.SendPartitioned(e.Channel, sb.ToString());

            var filepath = Path.Combine(_config.TempFileOutputDirPath, "chart.jpg");

            if (CommandHelper.AreaPlotSaveAs(foodStatus.Select((x, i) => new DataPoint(i, x)).ToArray(), filepath))
            {
                await e.Channel.SendFile(filepath);
            }
            if (File.Exists(filepath))
            {
                File.Delete(filepath);
            }
        }