Example #1
0
        public async Task LinkSteam()
        {
            using (var context = _databaseContextFactory.Create())
            {
                if (context.Users.FirstOrDefault(x =>
                                                 x != null && x.DiscordId == (long)Context.User.Id && !x.Unlinked) != null)
                {
                    await Context.Channel.SendMessageAsync(
                        $"<@{Context.User.Id}>, your user is already linked with Steam. If you wish to remove this link use the command **!unlinksteam**.");

                    return;
                }
            }

            var state = await _openId.LinkWithSteamTaskAsync(Context.User.Id);

            if (state == null)
            {
                await Context.Channel.SendMessageAsync(
                    $"<@{Context.User.Id}>, something went wrong... :( Please try sending the **!linksteam** command to me in a private conversation instead!");

                return;
            }

            EmbedBuilder builder = new EmbedBuilder()
            {
                Title       = "Steam Account Link",
                Description = $"Proceed to link your Discord user with your Steam account by [Logging into Steam]({state.StartUrl})",
                Url         = state.StartUrl,
                Color       = Color.Green
            };

            var channel = await Context.User.GetOrCreateDMChannelAsync();

            var msg = await channel.SendMessageAsync("", false, builder.Build());

            if (Context.IsPrivate)
            {
                return;
            }

            await Context.Channel.SendMessageAsync(
                $"<@{Context.User.Id}>, I have sent you a private message with instructions on how to proceed with linking your Discord user with Steam! If you do not receive this message, please try sending the **!linksteam** command to me in a private conversation!");

            //todo: how to get state in 1.0?
            //if (msg.State == MessageState.Normal || msg.State == MessageState.Queued)
            //    await Context.Channel.SendMessageAsync(
            //        $"<@{Context.User.Id}>, I have sent you a private message with instructions on how to proceed with linking your Discord user with Steam! If you do not receive this message, please try sending the **!linksteam** command to me in a private conversation!");
            //else
            //    await Context.Channel.SendMessageAsync(
            //        $"<@{Context.User.Id}>, it seems that I am unable to start a private conversation with you! :( Please try sending the **!linksteam** command to me in a private conversation instead!");
        }
Example #2
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 #3
0
        public async Task LinkSteam()
        {
            using (var context = _databaseContextFactory.Create())
            {
                if (context.Users.FirstOrDefault(x =>
                                                 x != null && x.DiscordId == (long)Context.User.Id && !x.Unlinked) != null)
                {
                    await Context.Channel.SendMessageAsync(
                        $"<@{Context.User.Id}>, your user is already linked with Steam. If you wish to remove this link use the command **!unlinksteam**.");

                    return;
                }
            }

            var state = await _openId.LinkWithSteamTaskAsync(Context.User.Id);

            if (state == null)
            {
                await Context.Channel.SendMessageAsync(
                    $"<@{Context.User.Id}>, something went wrong... :( Please try sending the **!linksteam** command to me in a private conversation instead!");

                return;
            }

            var sb = new StringBuilder();

            sb.AppendLine($"**Proceed to link your Discord user with your Steam account by following this link:**");
            sb.AppendLine($"{(await _urlShortenerService?.ShortenUrl(state.StartUrl)) ?? state.StartUrl}");

            var channel = await Context.User.GetOrCreateDMChannelAsync();

            var msg = await channel.SendMessageAsync(sb.ToString().Trim('\r', '\n'));

            if (Context.IsPrivate)
            {
                return;
            }

            await Context.Channel.SendMessageAsync(
                $"<@{Context.User.Id}>, I have sent you a private message with instructions on how to proceed with linking your Discord user with Steam! If you do not receive this message, please try sending the **!linksteam** command to me in a private conversation!");

            //todo: how to get state in 1.0?
            //if (msg.State == MessageState.Normal || msg.State == MessageState.Queued)
            //    await Context.Channel.SendMessageAsync(
            //        $"<@{Context.User.Id}>, I have sent you a private message with instructions on how to proceed with linking your Discord user with Steam! If you do not receive this message, please try sending the **!linksteam** command to me in a private conversation!");
            //else
            //    await Context.Channel.SendMessageAsync(
            //        $"<@{Context.User.Id}>, it seems that I am unable to start a private conversation with you! :( Please try sending the **!linksteam** command to me in a private conversation instead!");
        }
Example #4
0
        public async Task UnlinkSteam()
        {
            using (var context = _databaseContextFactory.Create())
            {
                var user = context.Users.FirstOrDefault(x => x.DiscordId == (long)Context.User.Id && !x.Unlinked);
                if (user == null)
                {
                    await Context.Channel.SendMessageAsync($"<@{Context.User.Id}>, your user is not linked with Steam.");
                }
                else
                {
                    user.Unlinked = true;
                    var result = context.SaveChanges();

                    //remove ark role from users when they unlink
                    if (Context.Client?.Guilds != null)
                    {
                        foreach (var server in Context.Client.Guilds)
                        {
                            try
                            {
                                var duser = server.GetUser(Context.User.Id);
                                var role  = server.Roles.FirstOrDefault(x => x.Name.Equals(_config.Discord.MemberRoleName));
                                if (duser != null && role == null)
                                {
                                    continue;
                                }

                                if (duser?.Roles.Any(x => x.Id == role.Id) == true)
                                {
                                    await duser.RemoveRoleAsync(role);
                                }
                            }
                            catch (HttpException)
                            {
                                //could be due to the order of roles on the server. bot role with "manage roles" permission must be higher up than the role it is trying to set
                            }
                        }
                    }

                    await Context.Channel.SendMessageAsync($"<@{Context.User.Id}>, your user is no longer linked with Steam.");
                }
            }
        }
Example #5
0
        public async Task Run(CommandEventArgs e)
        {
            using (var context = _databaseContextFactory.Create())
            {
                var user = context.Users.FirstOrDefault(x => x.DiscordId == (long)e.User.Id && !x.Unlinked);
                if (user == null)
                {
                    await e.Channel.SendMessage($"<@{e.User.Id}>, your user is not linked with Steam.");
                }
                else
                {
                    user.Unlinked = true;
                    var result = context.SaveChanges();

                    //remove ark role from users when they unlink
                    if (_discord?.Servers != null)
                    {
                        foreach (var server in _discord.Servers)
                        {
                            try
                            {
                                var duser = server.GetUser(e.User.Id);
                                var role  = server.FindRoles(_config.MemberRoleName, true).FirstOrDefault();
                                if (duser != null && role == null)
                                {
                                    continue;
                                }

                                if (duser.HasRole(role))
                                {
                                    await duser.RemoveRoles(role);
                                }
                            }
                            catch (HttpException)
                            {
                                //could be due to the order of roles on the server. bot role with "manage roles" permission must be higher up than the role it is trying to set
                            }
                        }
                    }

                    await e.Channel.SendMessage($"<@{e.User.Id}>, your user is no longer linked with Steam.");
                }
            }
        }
Example #6
0
        public async Task Run(CommandEventArgs e)
        {
            using (var context = _databaseContextFactory.Create())
            {
                var user = context.Users.FirstOrDefault(x => x.DiscordId == (long)e.User.Id && !x.Unlinked);
                if (user == null)
                {
                    await e.Channel.SendMessage($"<@{e.User.Id}>, your existence is a mystery to us! :(");
                }
                else
                {
                    if (!e.Channel.IsPrivate)
                    {
                        await e.Channel.SendMessage($"<@{e.User.Id}>, I will send you a private message with everything we know about you!");
                    }

                    var sb = new StringBuilder();
                    sb.AppendLine($"**This is what we know about you:**");
                    sb.AppendLine($"● **Discord ID:** {user.DiscordId}");
                    sb.AppendLine($"● **Steam ID:** {user.SteamId}");
                    if (user.SteamDisplayName != null)
                    {
                        sb.AppendLine($"● **Steam nick:** {user.SteamDisplayName}");
                    }
                    if (user.RealName != null)
                    {
                        sb.AppendLine($"● **Real name:** {user.RealName}");
                    }

                    if (e.User.PrivateChannel == null)
                    {
                        await e.User.CreatePMChannel();
                    }
                    foreach (var msg in sb.ToString().Partition(2000))
                    {
                        await e.User.PrivateChannel.SendMessage(msg.Trim('\r', '\n'));
                    }
                }
            }
        }
Example #7
0
        //todo: this method does not really belong here and should be moved elsewhere
        public static async Task <ArkSavegameToolkitNet.Domain.ArkPlayer> GetCurrentPlayerOrSendErrorMessage(CommandEventArgs e, EfDatabaseContextFactory databaseContextFactory, ArkServerContext serverContext)
        {
            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.SendMessage($"<@{e.User.Id}>, this command can only be used after you link your Discord user with your Steam account using **!linksteam**.");

                    return(null);
                }

                var player = serverContext.Players.FirstOrDefault(x => x.SteamId != null && x.SteamId.Equals(user.SteamId.ToString()));
                if (player == null)
                {
                    await e.Channel.SendMessage($"<@{e.User.Id}>, we have no record of you playing in the last month.");

                    return(null);
                }

                return(player);
            }
        }
Example #8
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 #9
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 #10
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 #11
0
        private async void _openId_SteamOpenIdCallback(object sender, SteamOpenIdCallbackEventArgs e)
        {
            if (e.Successful)
            {
                var player = new
                {
                    RealName    = (string)null,
                    PersonaName = (string)null
                };
                try
                {
                    using (var wc = new WebClient())
                    {
                        var data = await wc.DownloadStringTaskAsync($@"http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?key={_config.SteamApiKey}&steamids={e.SteamId}");

                        var response = JsonConvert.DeserializeAnonymousType(data, new { response = new { players = new[] { player } } });
                        player = response?.response?.players?.FirstOrDefault();
                    }
                }
                catch { /* ignore exceptions */ }

                //QueryMaster.Steam.GetPlayerSummariesResponsePlayer player = null;
                //await Task.Factory.StartNew(() =>
                //{
                //    try
                //    {
                //        //this results in an exception (but it is easy enough to query by ourselves)
                //        var query = new QueryMaster.Steam.SteamQuery(_config.SteamApiKey);
                //        var result = query?.ISteamUser.GetPlayerSummaries(new[] { e.SteamId });
                //        if (result == null || !result.IsSuccess) return;

                //        player = result.ParsedResponse.Players.FirstOrDefault();
                //    }
                //    catch { /* ignore exceptions */}
                //});

                //set ark role on users when they link
                //foreach(var server in _discord.Servers)
                //{
                //    var user = server.GetUser(e.DiscordUserId);
                //    var role = server.FindRoles(_config.MemberRoleName, true).FirstOrDefault();
                //    if (user == null || role == null) continue;

                //    //try
                //    //{
                //    //    if (!user.HasRole(role)) await user.AddRoles(role);

                //    //    var p = _context.Players?.FirstOrDefault(x => { ulong steamId = 0; return ulong.TryParse(x.SteamId, out steamId) ? steamId == e.SteamId : false; });
                //    //    if (p != null && !string.IsNullOrWhiteSpace(p.Name))
                //    //    {

                //    //        //must be less or equal to 32 characters
                //    //        await user.Edit(nickname: p.Name.Length > 32 ? p.Name.Substring(0, 32) : p.Name);

                //    //    }
                //    //}
                //    //catch (HttpException)
                //    //{
                //    //    //could be due to the order of roles on the server. bot role with "manage roles"/"change nickname" permission must be higher up than the role it is trying to set
                //    //}
                //}

                using (var context = _databaseContextFactory.Create())
                {
                    var user = context.Users.FirstOrDefault(x => x.DiscordId == (long)e.DiscordUserId);
                    if (user != null)
                    {
                        user.RealName         = player?.RealName;
                        user.SteamDisplayName = player?.PersonaName;
                        user.SteamId          = (long)e.SteamId;
                        user.Unlinked         = false;
                    }
                    else
                    {
                        user = new Database.Model.User {
                            DiscordId = (long)e.DiscordUserId, SteamId = (long)e.SteamId, RealName = player?.RealName, SteamDisplayName = player?.PersonaName
                        };
                        context.Users.Add(user);
                    }

                    foreach (var associatePlayed in context.Played.Where(x => x.SteamId == (long)e.SteamId))
                    {
                        associatePlayed.SteamId = null;
                        user.Played.Add(associatePlayed);
                    }

                    context.SaveChanges();
                }

                var ch = await _discord.GetUser(e.DiscordUserId).GetOrCreateDMChannelAsync();

                if (ch != null)
                {
                    await ch.SendMessageAsync($"Your Discord user is now linked with your Steam account! :)");
                }
            }
            else
            {
                var ch = await _discord.GetUser(e.DiscordUserId).GetOrCreateDMChannelAsync();

                if (ch != null)
                {
                    await ch.SendMessageAsync($"Something went wrong during the linking process. Please try again later!");
                }
            }
        }
Example #12
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 #13
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 #14
0
        private async Task UpdateNicknamesAndRoles(Server _server = null)
        {
            try
            {
                //change nicknames, add/remove from ark-role
                Database.Model.User[] linkedusers = null;
                using (var db = _databaseContextFactory.Create())
                {
                    linkedusers = db.Users.Where(x => !x.Unlinked).ToArray();
                }

                foreach (var server in _discord.Servers)
                {
                    if (_server != null && server.Id != _server.Id)
                    {
                        continue;
                    }

                    var role = server.FindRoles(_config.MemberRoleName, true).FirstOrDefault();
                    if (role == null)
                    {
                        continue;
                    }

                    foreach (var user in server.Users)
                    {
                        try
                        {
                            var dbuser = linkedusers.FirstOrDefault(x => (ulong)x.DiscordId == user.Id);
                            if (dbuser == null)
                            {
                                if (user.HasRole(role))
                                {
                                    Logging.Log($@"Removing role ({role.Name}) from user ({user.Name}#{user.Discriminator})", GetType(), LogLevel.DEBUG);
                                    await user.RemoveRoles(role);
                                }
                                continue;
                            }

                            if (!user.HasRole(role))
                            {
                                Logging.Log($@"Adding role ({role.Name}) from user ({user.Name}#{user.Discriminator})", GetType(), LogLevel.DEBUG);
                                await user.AddRoles(role);
                            }

                            var player     = _context.Players?.FirstOrDefault(x => { long steamId = 0; return(long.TryParse(x.SteamId, out steamId) ? steamId == dbuser.SteamId : false); });
                            var playerName = player?.Name?.Length > 32 ? player?.Name?.Substring(0, 32) : player?.Name;
                            if (!string.IsNullOrWhiteSpace(playerName) &&
                                !user.ServerPermissions.Administrator &&
                                !playerName.Equals(user.Name, StringComparison.Ordinal) &&
                                (user.Nickname == null || !playerName.Equals(user.Nickname, StringComparison.Ordinal)))
                            {
                                //must be less or equal to 32 characters
                                Logging.Log($@"Changing nickname (from: ""{user.Nickname ?? "null"}"", to: ""{playerName}"") for user ({user.Name}#{user.Discriminator})", GetType(), LogLevel.DEBUG);
                                await user.Edit(nickname : playerName);
                            }
                        }
                        catch (HttpException ex)
                        {
                            //could be due to the order of roles on the server. bot role with "manage roles"/"change nickname" permission must be higher up than the role it is trying to set
                            Logging.LogException("HttpException while trying to update nicknames/roles (could be due to permissions)", ex, GetType(), LogLevel.DEBUG, ExceptionLevel.Ignored);
                        }
                    }
                }
            }
            catch (WebException ex)
            {
                Logging.LogException("Exception while trying to update nicknames/roles", ex, GetType(), LogLevel.DEBUG, ExceptionLevel.Ignored);
            }
        }