From ad489a77fa5111381680942b291fcb2cd9ad10a3 Mon Sep 17 00:00:00 2001 From: sbz <70881002+sbzappa@users.noreply.github.com> Date: Thu, 15 Aug 2024 21:24:03 -0400 Subject: [PATCH] Version 1.38 (#83) * Updated version to 1.38 and added support for auto-reset weeklies. * Changed reset time to UTC 18 0 0 * Removed xvfb hack * Removed xvfb hack (for realz). * Cleanup --- MaraBot/Core/CommandUtils.cs | 85 +++++---------------------------- MaraBot/Core/WeeklyUtils.cs | 8 ++-- MaraBot/Messages/Display.cs | 2 +- MaraBot/Program.cs | 14 ++++++ MaraBot/Tasks/ResetChallenge.cs | 5 ++ MaraBot/Tasks/ResetWeekly.cs | 65 ++++++++++++++++++++++++- config/mystery.json | 2 +- 7 files changed, 100 insertions(+), 81 deletions(-) diff --git a/MaraBot/Core/CommandUtils.cs b/MaraBot/Core/CommandUtils.cs index 356d3ab..e649979 100644 --- a/MaraBot/Core/CommandUtils.cs +++ b/MaraBot/Core/CommandUtils.cs @@ -665,9 +665,16 @@ public int Compare(KeyValuePair x, KeyValuePair GenerateMysteryRaceAsync( - CommandContext ctx, + /// + /// Generate a race a randomized weekly settings + /// + /// Author of the race. "Mara" if null or empty. + /// Name of the race. + /// Description of the race + /// List of weekly settings + /// Randomizer options + /// Tuple of preset and seed string. + public static async Task<(Preset Preset, string Seed, string ValidationHash)> GenerateMysteryRaceAsync( string author, string name, string description, @@ -742,7 +749,7 @@ await Task.Run(() => case AttachmentFileType.LogFile: return await LoadLogAttachmentAsync(ctx, author, name, description, options); case AttachmentFileType.None: - return await GenerateMysteryRaceAsync(ctx, author, name, description, mysterySettings, options); + return await GenerateMysteryRaceAsync(author, name, description, mysterySettings, options); default: throw new InvalidOperationException(errorMessage); @@ -778,68 +785,6 @@ await Task.Run(() => if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX) { - Process xvfbProcess = null; - var framebufferFile = "/tmp/Xvfb_screen0"; - - var displayEnv = Environment.GetEnvironmentVariable("DISPLAY"); - if (String.IsNullOrEmpty(displayEnv)) - { - var displayNumber = 1; - - xvfbProcess = new Process - { - StartInfo = new ProcessStartInfo - { - FileName = "Xvfb", - ArgumentList = - { - $":{displayNumber}", - "-fbdir", - "/tmp/" - } - } - }; - - try - { - xvfbProcess.Start(); - } - catch(Exception exception) - { - xvfbProcess.Dispose(); - throw new InvalidOperationException( - "This feature requires Xvfb to setup a virtual display.\n" + - $"Exception: {exception.Message}" - ); - } - - var timeout = TimeSpan.FromMilliseconds(5000); - DateTimeOffset timeoutAt = DateTimeOffset.UtcNow + timeout; - var fileExists = false; - while (true) - { - if (File.Exists(framebufferFile)) - { - fileExists = true; - break; - } - if (DateTimeOffset.UtcNow >= timeoutAt) break; - await Task.Delay(10); - } - - if (fileExists) - displayEnv = $":{displayNumber}"; - else - { - xvfbProcess?.Kill(); - xvfbProcess?.Dispose(); - - throw new InvalidOperationException( - $"Could not find Xvfb framebuffer file {framebufferFile}." - ); - } - } - var tcs = new TaskCompletionSource(); var randomizerProcess = new Process { @@ -859,8 +804,6 @@ await Task.Run(() => EnableRaisingEvents = true }; - randomizerProcess.StartInfo.EnvironmentVariables["DISPLAY"] = displayEnv; - randomizerProcess.Exited += (sender, args) => { tcs.SetResult(randomizerProcess.ExitCode); @@ -873,7 +816,6 @@ await Task.Run(() => } catch (Exception exception) { - xvfbProcess?.Dispose(); throw new InvalidOperationException( "This feature requires mono to run the randomizer executable.\n" + $"Exception: {exception.Message}" @@ -881,11 +823,6 @@ await Task.Run(() => } await tcs.Task; - - File.Delete(framebufferFile); - - xvfbProcess?.Kill(); - xvfbProcess?.Dispose(); } else { diff --git a/MaraBot/Core/WeeklyUtils.cs b/MaraBot/Core/WeeklyUtils.cs index 60adb07..a1e6076 100644 --- a/MaraBot/Core/WeeklyUtils.cs +++ b/MaraBot/Core/WeeklyUtils.cs @@ -10,8 +10,9 @@ namespace MaraBot.Core public static class WeeklyUtils { static Random s_TimeBasedRandom = new Random(DateTime.Now.GetHashCode()); - static DateTime s_FirstWeek = new DateTime(2021, 08, 13, 0, 0, 0); + static DateTime s_FirstWeek = new DateTime(2021, 08, 13, 18, 0, 0, DateTimeKind.Utc); static readonly TimeSpan s_WeeklyDuration = TimeSpan.FromDays(7.0); + //static readonly TimeSpan s_WeeklyDuration = TimeSpan.FromMinutes(1.0); enum ChallengeDuration { @@ -22,7 +23,6 @@ enum ChallengeDuration static readonly ChallengeDuration s_ChallengeDuration = ChallengeDuration.EveryMonth; - /// /// Retrieves the duration until next weekly reset. /// @@ -120,9 +120,9 @@ public static string GetRandomSeed() public static int GetWeekNumber() { var elapsed = DateTime.UtcNow.Subtract(s_FirstWeek); - var elapsedWeeks = elapsed.Days / 7; + var divide = elapsed.Divide(s_WeeklyDuration); - return elapsedWeeks; + return (int)Math.Truncate(divide); } /// diff --git a/MaraBot/Messages/Display.cs b/MaraBot/Messages/Display.cs index 59a9011..4311906 100644 --- a/MaraBot/Messages/Display.cs +++ b/MaraBot/Messages/Display.cs @@ -266,7 +266,7 @@ public static async Task LeaderboardEmbedAsync(DiscordGuild IEnumerable> leaderboard = weekly.Leaderboard; // To avoid giving away any ranking, avoid sorting the leaderboard when preventing spoilers. - if (!preventSpoilers) + if (leaderboard != null && !preventSpoilers) { leaderboard = leaderboard .OrderBy(kvp => kvp.Value); diff --git a/MaraBot/Program.cs b/MaraBot/Program.cs index 5fcca81..a25e924 100644 --- a/MaraBot/Program.cs +++ b/MaraBot/Program.cs @@ -102,12 +102,26 @@ static async Task MainAsync() }; var resetChallengeTask = resetChallenge.StartAsync(); + var resetWeekly = new ResetWeekly + { + Discord = discord, + Weekly = weekly, + Options = options, + Config = config, + MutexRegistry = mutexRegistry, + MysterySettings = mysterySettings + }; + var resetWeeklyTask = resetWeekly.StartAsync(); + await discord.StartAsync(); await Task.Delay(-1); resetChallenge.StopAsync(); await resetChallengeTask; + + resetWeekly.StopAsync(); + await resetWeeklyTask; } } } diff --git a/MaraBot/Tasks/ResetChallenge.cs b/MaraBot/Tasks/ResetChallenge.cs index c3a880c..e8caf71 100644 --- a/MaraBot/Tasks/ResetChallenge.cs +++ b/MaraBot/Tasks/ResetChallenge.cs @@ -51,6 +51,11 @@ public async Task StartAsync() } var duration = WeeklyUtils.GetRemainingChallengeDuration(timeStamp); + + // At most check remaining duration every day. + if (duration > TimeSpan.FromDays(1)) + duration = TimeSpan.FromDays(1); + if (duration > TimeSpan.Zero) await Task.Delay(duration, _cts.Token); } diff --git a/MaraBot/Tasks/ResetWeekly.cs b/MaraBot/Tasks/ResetWeekly.cs index a23ed11..864f080 100644 --- a/MaraBot/Tasks/ResetWeekly.cs +++ b/MaraBot/Tasks/ResetWeekly.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -6,6 +7,7 @@ using MaraBot.Core; using MaraBot.IO; using MaraBot.Messages; +using Microsoft.Extensions.Logging; namespace MaraBot.Tasks { @@ -14,8 +16,27 @@ public class ResetWeekly private readonly CancellationTokenSource _cts = new CancellationTokenSource(); public DiscordShardedClient Discord { get; set; } + + /// + /// Weekly settings. + /// public Weekly Weekly { get; set; } - public Config Config { get; set; } + /// + /// Randomizer Options. + /// + public IReadOnlyDictionary Options { private get; set; } + /// + /// Mystery Settings. + /// + public IReadOnlyDictionary MysterySettings { private get; set; } + /// + /// Bot configuration. + /// + public Config Config { private get; set; } + /// + /// Mutex registry. + /// + public MutexRegistry MutexRegistry { private get; set; } public async Task StartAsync() { @@ -73,6 +94,48 @@ await CommandUtils.SendToChannelAsync( // Set weekly to blank with a fresh leaderboard. Weekly.Load(Weekly.NotSet); await WeeklyIO.StoreWeeklyAsync(Weekly); + + // Generate a new race. + var name = $"Weekly {currentWeek}"; + + Weekly.Preset = default; + Weekly.PresetName = String.Empty; + + try + { + (Weekly.Preset, Weekly.Seed, _) = await CommandUtils.GenerateMysteryRaceAsync(default, name, default, MysterySettings, Options); + } + catch (InvalidOperationException e) + { + Discord.Logger.LogWarning( + "Could not generate weekly race.\n" + + e.Message); + return; + } + + try + { + var (newPreset, newSeed, newValidationHash) = await CommandUtils.GenerateValidationHash(Weekly.Preset, Weekly.Seed, Config, Options, MutexRegistry); + if (newPreset.Equals(Weekly.Preset) && newSeed.Equals(Weekly.Seed)) + { + Weekly.ValidationHash = newValidationHash; + } + } + catch (Exception exception) + { + Discord.Logger.LogWarning( + "Could not create a validation hash.\n" + + exception.Message); + } + + await WeeklyIO.StoreWeeklyAsync(Weekly); + + var raceEmbed = Display.RaceEmbed(Weekly.Preset, Weekly.Seed, Weekly.ValidationHash); + + foreach (var guild in guilds) + { + await CommandUtils.SendToChannelAsync(guild, Config.WeeklyChannel, raceEmbed); + } } public void StopAsync() diff --git a/config/mystery.json b/config/mystery.json index 3d6008a..9251b37 100644 --- a/config/mystery.json +++ b/config/mystery.json @@ -1,7 +1,7 @@ { "version": { "values": { - "1.36": 100 + "1.38": 100 } },