private async Task VoteFinished(ArkServerContext serverContext, IEfDatabaseContext db, Database.Model.Vote vote, bool noAnnouncement = false, VoteResult?forcedResult = null) { var handler = GetVoteHandler(vote); if (handler == null) { return; } var votesFor = vote.Votes.Count(x => x.VotedFor); var votesAgainst = vote.Votes.Count(x => !x.VotedFor); #if DEBUG vote.Result = forcedResult ?? (vote.Votes.Count >= 1 && votesFor > votesAgainst ? VoteResult.Passed : VoteResult.Failed); #else vote.Result = forcedResult ?? (vote.Votes.Count >= 3 && votesFor > votesAgainst ? VoteResult.Passed : VoteResult.Failed); #endif VoteStateChangeResult result = null; try { result = await handler.VoteFinished(serverContext, _config, _constants, db); try { if (!noAnnouncement && result != null) { if (result.MessageRcon != null) { await serverContext.Steam.SendRconCommand($"serverchat {result.MessageRcon.ReplaceRconSpecialChars()}"); } if (result.MessageAnnouncement != null && !string.IsNullOrWhiteSpace(_config.Discord.AnnouncementChannel)) { await _discordManager.SendTextMessageToChannelNameOnAllServers(_config.Discord.AnnouncementChannel, result.MessageAnnouncement); } } } catch { /* ignore all exceptions */ } if (result != null && result.React != null) { if (result.ReactDelayInMinutes <= 0) { await result.React(); } else { await _scheduledTasksManager.StartCountdown(serverContext, result.ReactDelayFor, result.ReactDelayInMinutes, result.React); } } } catch (Exception ex) { //todo: better exception handling structure Logging.LogException(ex.Message, ex, GetType(), LogLevel.ERROR, ExceptionLevel.Unhandled); } db.SaveChanges(); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } if (_vote.Result == VoteResult.Passed) { _vote.BannedUntil = _vote.Started.AddHours(_vote.DurationInHours); await serverContext.Steam.SendRconCommand($"banplayer {_vote.SteamId}"); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to ban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to ban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}." }); }
public static async Task <InitiateVoteResult> Initiate(Channel channel, ArkServerContext context, IConfig config, IEfDatabaseContext db, ulong userId, string identifier, DateTime when, string reason, string targetRaw, int durationInHours) { var _rId = new Regex(@"^\s*(id|(steam\s*id))\s*\:\s*(?<id>\d+)\s*$", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.ExplicitCapture); var m = _rId.Match(targetRaw); var targets = m.Success ? context.Players.Where(x => x.Id.ToString().Equals(m.Groups["id"].Value) || x.SteamId.Equals(m.Groups["id"].Value)).ToArray() : context.Players.Where(x => (x.Name != null && x.Name.Equals(targetRaw, StringComparison.OrdinalIgnoreCase)) || (x.Name != null && x.Name.Equals(targetRaw, StringComparison.OrdinalIgnoreCase))).ToArray(); if (targets.Length == 0) { await channel.SendMessageDirectedAt(userId, $"could not find a player with that name (maybe they have not been saved yet?). Try using their steam id instead."); return(null); } if (targets.Length > 1) { await channel.SendMessageDirectedAt(userId, $"there are more than one player with that name. Try using their steam id instead."); return(null); } var target = targets.First(); var steamId = long.Parse(target.SteamId); var votes = db.Votes.OfType <BanVote>().Where(x => x.SteamId == steamId).ToArray(); if (votes.Any(x => x.BannedUntil.HasValue && x.BannedUntil.Value > when)) { await channel.SendMessageDirectedAt(userId, $"this player is already banned."); return(null); } var unvotes = db.Votes.OfType <UnbanVote>().Where(x => x.SteamId == steamId).ToArray(); if (votes.Any(x => x.Result == VoteResult.Undecided) || unvotes.Any(x => x.Result == VoteResult.Undecided)) { await channel.SendMessageDirectedAt(userId, $"there is already an active vote to ban/unban this player."); return(null); } //proceed to initiate vote var vote = new BanVote { SteamId = steamId, PlayerName = target.Name, CharacterName = target.Name, TribeName = target.TribeId.HasValue ? context.Tribes?.FirstOrDefault(x => x.Id == target.TribeId)?.Name : null, //target.TribeName, Reason = reason, Started = when, #if DEBUG Finished = when.AddSeconds(10), #else Finished = when.AddMinutes(5), #endif DurationInHours = durationInHours, Result = VoteResult.Undecided, ServerKey = context.Config.Key, Identifier = identifier }; return(new InitiateVoteResult { MessageInitiator = $"the vote to ban this player have been initiated. Announcement will be made.", MessageAnnouncement = $@"**A vote to ban {vote.FullName}{(vote.DurationInHours <= (24 * 90) ? $" for {vote.DurationInHours}h" : "")} due to ""{reason}"" have been started. Please cast your vote in the next five minutes!**{Environment.NewLine}To vote use the command: **!vote {identifier} yes**/**no**", MessageRcon = $@"A vote to ban {vote.FullName}{(vote.DurationInHours <= (24 * 90) ? $" for {vote.DurationInHours}h" : "")} due to ""{reason}"" have been started. Please cast your vote on Discord using !vote {identifier} yes/no in the next five minutes!", Vote = vote }); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to update the server ({_vote.ServerKey}) have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to update the server have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}.", ReactDelayInMinutes = 5, ReactDelayFor = "Server update", React = _vote.Result == VoteResult.Passed ? new Func <Task>(async() => { string message = null; if (!await _arkServerService.UpdateServer(_vote.ServerKey, (s) => { message = s; return Task.FromResult((IUserMessage)null); }, (s) => s.FirstCharToUpper(), 300)) { Logging.Log($@"Vote to update server ({_vote.ServerKey}) execution failed (""{message ?? ""}"")", GetType(), LogLevel.DEBUG); } }) : null }); }
public static async Task <InitiateVoteResult> Initiate(IMessageChannel channel, ArkServerContext context, IConfig config, IEfDatabaseContext db, ulong userId, string identifier, DateTime when, string reason) { if (db.Votes.OfType <RestartServerVote>().Where(x => x.Result == VoteResult.Undecided).Any() || db.Votes.OfType <UpdateServerVote>().Where(x => x.Result == VoteResult.Undecided).Any()) { await channel.SendMessageDirectedAt(userId, $"there is already an active vote to manage the server."); return(null); } //proceed to initiate vote var vote = new UpdateServerVote { Reason = reason, Started = when, #if DEBUG Finished = when.AddSeconds(10), #else Finished = when.AddMinutes(5), #endif Result = VoteResult.Undecided, ServerKey = context.Config.Key, Identifier = identifier }; return(new InitiateVoteResult { MessageInitiator = $"the vote to update the server have been initiated. Announcement will be made.", MessageAnnouncement = $@"@everyone **A vote to update the server ({context.Config.Key}) due to ""{reason}"" have been started. Please cast your vote in the next five minutes!**{Environment.NewLine}To vote use the command: **!vote {identifier} yes**/**no**", MessageRcon = $@"A vote to update the server due to ""{reason}"" have been started. Please cast your vote on Discord using !vote {identifier} yes/no in the next five minutes!", Vote = vote }); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } if (serverContext == null) { return(null); } if (_vote.Result == VoteResult.Passed) { await serverContext.Steam.SendRconCommand($"destroywilddinos"); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to wipe wild dinos on server ({_vote.ServerKey}) have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to wipe wild dinos have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}." }); }
public async Task <VoteStateChangeResult> VoteFinished(ArkServerContext serverContext, IConfig config, IConstants constants, IEfDatabaseContext db) { if (_vote == null) { return(null); } if (_vote.Result == VoteResult.Passed) { var bans = db.Votes.OfType <BanVote>().Where(x => x.SteamId == _vote.SteamId && x.Result == VoteResult.Passed && x.BannedUntil.HasValue && x.BannedUntil.Value > DateTime.Now); foreach (var ban in bans) { ban.BannedUntil = null; } await serverContext.Steam.SendRconCommand($"unbanplayer {_vote.SteamId}"); } return(new VoteStateChangeResult { MessageAnnouncement = $@"{(_vote.Result == VoteResult.Passed ? ":white_check_mark:" : ":x:")} **Vote to unban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}**", MessageRcon = $@"Vote to unban {_vote.FullName} have {(_vote.Result == VoteResult.Vetoed ? "been vetoed" : _vote.Result == VoteResult.Passed ? "passed" : "failed")}." }); }
public static async Task <InitiateVoteResult> Initiate(Channel channel, ArkServerContext context, IConfig config, IEfDatabaseContext db, ulong userId, string identifier, DateTime when, string reason, string timeOfDayRaw) { var _rTimeOfDay = new Regex(@"^\s*\d{2,2}\:\d{2,2}(\:\d{2,2})?\s*$", RegexOptions.Singleline | RegexOptions.IgnoreCase); if (!_rTimeOfDay.IsMatch(timeOfDayRaw)) { await channel.SendMessageDirectedAt(userId, $"time of day format is invalid."); return(null); } var votes = db.Votes.OfType <SetTimeOfDayVote>().Where(x => x.Result == VoteResult.Undecided).ToArray(); if (votes.Length > 0) { await channel.SendMessageDirectedAt(userId, $"there is already an active vote to set the time of day."); return(null); } //proceed to initiate vote var vote = new SetTimeOfDayVote { TimeOfDay = timeOfDayRaw.Trim(), Reason = reason, Started = when, #if DEBUG Finished = when.AddSeconds(10), #else Finished = when.AddMinutes(2), #endif Result = VoteResult.Undecided, ServerKey = context.Config.Key, Identifier = identifier }; return(new InitiateVoteResult { MessageInitiator = $"the vote to set time of day to {vote.TimeOfDay} have been initiated. Announcement will be made.", MessageAnnouncement = $@"**A vote to set time of day on server ({context.Config.Key}) to {vote.TimeOfDay} due to ""{reason}"" have been started. Please cast your vote in the next two minutes!**{Environment.NewLine}To vote use the command: **!vote {identifier} yes**/**no**", MessageRcon = $@"A vote to set time of day to {vote.TimeOfDay} due to ""{reason}"" have been started. Please cast your vote on Discord using !vote {identifier} yes/no in the next two minutes!", Vote = vote }); }