diff --git a/Common/Discord/DiscordFormatUtility.cs b/Common/Discord/DiscordFormatUtility.cs new file mode 100644 index 0000000..2e17ce5 --- /dev/null +++ b/Common/Discord/DiscordFormatUtility.cs @@ -0,0 +1,48 @@ +using System.Text; +using Discord; + +namespace Approvers.King.Common; + +public static class DiscordFormatUtility +{ + public static string Smile => MasterManager.SettingMaster.CommonSmileFormat; + public static string Missing => MasterManager.SettingMaster.CommonMissingMessage; + + public static string Repeat(this string value, int count, string separator = "") + { + return string.Join(separator, EnumerableUtility.Repeat(value, count)); + } + + public static string Custom(this string value, string formatter) + { + var isBold = formatter.Contains("b"); + var isItalic = formatter.Contains("i"); + var isUnderline = formatter.Contains("u"); + var isStrike = formatter.Contains("s"); + var isCode = formatter.Contains("c"); + var isSpoiler = formatter.Contains("p"); + + var result = value; + if (isBold) result = Format.Bold(result); + if (isItalic) result = Format.Italics(result); + if (isUnderline) result = Format.Underline(result); + if (isStrike) result = Format.Strikethrough(result); + if (isCode) result = Format.Code(result); + if (isSpoiler) result = Format.Spoiler(result); + + return result; + } + + public static string Table(IEnumerable<(string key, string value)> records) + { + var recordList = records.ToList(); + var maxLength = recordList.Max(r => r.key.Length); + var sb = new StringBuilder(); + foreach (var (key, value) in recordList) + { + sb.AppendLine($"| {value.PadLeft(maxLength)} | {Format.Sanitize(key)}"); + } + + return Format.Code(sb.ToString()); + } +} diff --git a/Common/Discord/DiscordMessageUtility.cs b/Common/Discord/DiscordMessageUtility.cs deleted file mode 100644 index 485e7eb..0000000 --- a/Common/Discord/DiscordMessageUtility.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Text; -using Discord; - -namespace Approvers.King.Common; - -public static class DiscordMessageUtility -{ - public static string Table(IEnumerable<(string key, string value)> records) - { - var recordList = records.ToList(); - var maxLength = recordList.Max(r => r.key.Length); - var sb = new StringBuilder(); - foreach (var (key, value) in recordList) - { - sb.AppendLine($"| {value.PadLeft(maxLength)} | {Format.Sanitize(key)}"); - } - - return Format.Code(sb.ToString()); - } -} diff --git a/Common/Master/SettingMaster.cs b/Common/Master/SettingMaster.cs index 6a22337..4bb6b38 100644 --- a/Common/Master/SettingMaster.cs +++ b/Common/Master/SettingMaster.cs @@ -139,6 +139,16 @@ private int GetInt(string key) public int SlotRepeatPermillageUpperBound => GetInt(nameof(SlotRepeatPermillageUpperBound)); public Multiplier SlotRepeatUpperBound => Multiplier.FromPermillage(SlotRepeatPermillageUpperBound); + + /// + /// 汎用的な笑顔の絵文字フォーマット + /// + public string CommonSmileFormat => GetString(nameof(CommonSmileFormat)); + + /// + /// 汎用的な存在しないメッセージ + /// + public string CommonMissingMessage => GetString(nameof(CommonMissingMessage)); } [SuppressMessage("ReSharper", "UnassignedGetOnlyAutoProperty")] diff --git a/Common/Time/TimeManager.cs b/Common/Time/TimeManager.cs index 952aacb..958b43a 100644 --- a/Common/Time/TimeManager.cs +++ b/Common/Time/TimeManager.cs @@ -4,7 +4,6 @@ public class TimeManager : Singleton { public static TimeSpan DailyResetTime => TimeSpan.FromMilliseconds(MasterManager.SettingMaster.DailyResetTime); public static int MonthlyResetDay => MasterManager.SettingMaster.MonthlyResetDay; - public static DateTime Birthday => new(1, MasterManager.SettingMaster.BirthdayMonth, MasterManager.SettingMaster.BirthdayDay); private DateTime? _debugBaseTime; private TimeSpan _debugTimeOffset; @@ -28,12 +27,4 @@ public static DateTime GetNow() { return DateTime.Now.ToLocalTime() + Instance._debugTimeOffset; } - - /// - /// 時間を過ぎていればtrue - /// - public static bool IsExpired(DateTime time) - { - return GetNow() > time; - } } diff --git a/Common/Utility/EnumerableUtility.cs b/Common/Utility/EnumerableUtility.cs index a608e3b..438bee7 100644 --- a/Common/Utility/EnumerableUtility.cs +++ b/Common/Utility/EnumerableUtility.cs @@ -6,9 +6,4 @@ public static IEnumerable Repeat(T value, int count) { for (var i = 0; i < count; i++) yield return value; } - - public static IEnumerable Repeat(Func value, int count) - { - for (var i = 0; i < count; i++) yield return value(); - } } diff --git a/Events/Admin/AdminMasterReloadPresenter.cs b/Events/Admin/AdminMasterReloadPresenter.cs index 5120b94..f8648a5 100644 --- a/Events/Admin/AdminMasterReloadPresenter.cs +++ b/Events/Admin/AdminMasterReloadPresenter.cs @@ -10,8 +10,7 @@ public class AdminMasterReloadPresenter : DiscordMessagePresenterBase { protected override async Task MainAsync() { - await Message.ReplyAsync("マスターをリロードするぞ"); await MasterManager.FetchAsync(); - await Message.ReplyAsync("マスターをリロードしたぞ"); + await Message.ReplyAsync("done(ドゥーン)"); } } diff --git a/Events/DailyReset/DailyResetBirthPresenter.cs b/Events/DailyReset/DailyResetBirthPresenter.cs deleted file mode 100644 index 50b2b6b..0000000 --- a/Events/DailyReset/DailyResetBirthPresenter.cs +++ /dev/null @@ -1,23 +0,0 @@ -using Approvers.King.Common; - -namespace Approvers.King.Events; - -/// -/// 誕生日に発火するイベント -/// -public class DailyResetBirthPresenter : SchedulerJobPresenterBase -{ - private static readonly string Message = $""" - {string.Join("", EnumerableUtility.Repeat(IssoUtility.SmileStamp, 16))} - {IssoUtility.SmileStamp}                    {IssoUtility.SmileStamp} - {IssoUtility.SmileStamp} ***† 誕 生 日 だ 祝 え カ ス †*** {IssoUtility.SmileStamp} - {IssoUtility.SmileStamp}                    {IssoUtility.SmileStamp} - {string.Join("", EnumerableUtility.Repeat(IssoUtility.SmileStamp, 16))} - """; - - protected override async Task MainAsync() - { - var guild = DiscordManager.Client.GetGuild(EnvironmentManager.DiscordTargetGuildId); - await guild.GetTextChannel(EnvironmentManager.DiscordMainChannelId).SendMessageAsync(Message); - } -} diff --git a/Events/DailyReset/DailyResetPresenter.cs b/Events/DailyReset/DailyResetPresenter.cs index 806c972..7ccbd74 100644 --- a/Events/DailyReset/DailyResetPresenter.cs +++ b/Events/DailyReset/DailyResetPresenter.cs @@ -5,6 +5,8 @@ namespace Approvers.King.Events; +using F = DiscordFormatUtility; + /// /// 毎日のリセットを行うイベント /// @@ -12,6 +14,8 @@ public class DailyResetPresenter : SchedulerJobPresenterBase { protected override async Task MainAsync() { + var now = TimeManager.GetNow(); + await using var app = AppService.CreateSession(); var slotMaxUsers = await app.Users @@ -33,6 +37,13 @@ protected override async Task MainAsync() // 排出率を投稿する await DiscordManager.GetMainChannel().SendMessageAsync(embed: GachaUtility.GetInfoEmbedBuilder(gacha).Build()); + // 誕生日なら祝わせる + var isBirthday = now.Month == MasterManager.SettingMaster.BirthdayMonth && now.Day == MasterManager.SettingMaster.BirthdayDay; + if (isBirthday) + { + await SendBirthdayMessageAsync(); + } + // スロットの実行回数が最大になったユーザーを通知する await NotifySlotMaxUsers(slotMaxUsers); } @@ -45,7 +56,7 @@ private async Task NotifySlotMaxUsers(IReadOnlyList users) } var sb = new StringBuilder(); - sb.AppendLine("**\u2b07\ufe0e\u2b07\ufe0e\u2b07\ufe0e 昨日のスロカス一覧がこちらw \u2b07\ufe0e\u2b07\ufe0e\u2b07\ufe0e**"); + sb.AppendLine("\u2b07\ufe0e\u2b07\ufe0e\u2b07\ufe0e 昨日のスロカス一覧がこちらw \u2b07\ufe0e\u2b07\ufe0e\u2b07\ufe0e".Custom("b")); sb.AppendLine(); foreach (var user in users) { @@ -54,4 +65,18 @@ private async Task NotifySlotMaxUsers(IReadOnlyList users) await DiscordManager.GetMainChannel().SendMessageAsync(sb.ToString()); } + + private async Task SendBirthdayMessageAsync() + { + var message = $""" + {F.Smile.Repeat(16)} + {F.Smile}                    {F.Smile} + {F.Smile} ***† 誕 生 日 だ 祝 え カ ス †*** {F.Smile} + {F.Smile}                    {F.Smile} + {F.Smile.Repeat(16)} + """; + + // 誕生日を祝わせる + await DiscordManager.GetMainChannel().SendMessageAsync(message); + } } diff --git a/Events/Gacha/GachaCommandPresenter.cs b/Events/Gacha/GachaCommandPresenter.cs index 9f9daf6..4e06305 100644 --- a/Events/Gacha/GachaCommandPresenter.cs +++ b/Events/Gacha/GachaCommandPresenter.cs @@ -4,6 +4,8 @@ namespace Approvers.King.Events; +using F = DiscordFormatUtility; + /// /// 10連ガチャを回すイベント /// @@ -28,9 +30,8 @@ private async Task SendReplyAsync(User user, IReadOnlyList results) foreach (var result in results) { builder.AppendLine(result != null - ? Format.Bold( - $"・{result.RandomMessage?.Content ?? MessageConst.MissingMessage} ({result.Probability.Rate:P0})") - : Format.Code("x")); + ? $"・{result.RandomMessage?.Content ?? F.Missing} ({result.Probability.Rate:P0})".Custom("b") + : "x".Custom("c")); } // 爆死してたら煽る @@ -39,7 +40,7 @@ private async Task SendReplyAsync(User user, IReadOnlyList results) builder.AppendLine(); var messages = MasterManager.RandomMessageMaster.GetAll(x => x.Type == RandomMessageType.GachaFailed); var failedMessage = RandomManager.PickRandom(messages).Content; - builder.AppendLine(Format.Bold(Format.Italics(failedMessage))); + builder.AppendLine(failedMessage.Custom("bi")); } builder.AppendLine(); diff --git a/Events/Gacha/GachaInteractReplyPresenter.cs b/Events/Gacha/GachaInteractReplyPresenter.cs index 2db828c..5754581 100644 --- a/Events/Gacha/GachaInteractReplyPresenter.cs +++ b/Events/Gacha/GachaInteractReplyPresenter.cs @@ -3,6 +3,8 @@ namespace Approvers.King.Events; +using F = DiscordFormatUtility; + /// /// 確定ガチャを回すイベント /// @@ -15,7 +17,7 @@ protected override async Task MainAsync() var gacha = await app.GetDefaultGachaAsync(); var message = user.RollGachaOnceCertain(gacha); - await SendReplyAsync(message.RandomMessage?.Content ?? MessageConst.MissingMessage); + await SendReplyAsync(message.RandomMessage?.Content ?? F.Missing); await app.SaveChangesAsync(); } diff --git a/Events/Gacha/GachaRareReplyPresenter.cs b/Events/Gacha/GachaRareReplyPresenter.cs index fe44977..4ebb80d 100644 --- a/Events/Gacha/GachaRareReplyPresenter.cs +++ b/Events/Gacha/GachaRareReplyPresenter.cs @@ -3,6 +3,8 @@ namespace Approvers.King.Events; +using F = DiscordFormatUtility; + /// /// 単発ガチャを回すイベント /// @@ -22,7 +24,7 @@ protected override async Task MainAsync() var message = user.RollGachaOnce(gacha); if (message != null) { - await SendReplyAsync(message.RandomMessage?.Content ?? MessageConst.MissingMessage); + await SendReplyAsync(message.RandomMessage?.Content ?? F.Missing); } await app.SaveChangesAsync(); diff --git a/Events/Gacha/GachaUtility.cs b/Events/Gacha/GachaUtility.cs index ba9ce85..e100d00 100644 --- a/Events/Gacha/GachaUtility.cs +++ b/Events/Gacha/GachaUtility.cs @@ -4,6 +4,8 @@ namespace Approvers.King.Events; +using F = DiscordFormatUtility; + public static class GachaUtility { public static EmbedBuilder GetInfoEmbedBuilder(Gacha gacha) @@ -12,13 +14,12 @@ public static EmbedBuilder GetInfoEmbedBuilder(Gacha gacha) var records = gacha.GachaItems .OrderByDescending(x => x.Probability) .Where(x => x.Probability > minProbability) - .Select(x => (x.RandomMessage?.Content ?? MessageConst.MissingMessage, x.Probability.Rate.ToString("P0"))); + .Select(x => (x.RandomMessage?.Content ?? F.Missing, x.Probability.Rate.ToString("P0"))); return new EmbedBuilder() - .WithTitle( - $"{IssoUtility.SmileStamp}{IssoUtility.SmileStamp}{IssoUtility.SmileStamp} 本日のいっそう {IssoUtility.SmileStamp}{IssoUtility.SmileStamp}{IssoUtility.SmileStamp}") + .WithTitle($"{F.Smile.Repeat(3)} 本日のいっそう {F.Smile.Repeat(3)}") .WithColor(new Color(0xf1, 0xc4, 0x0f)) - .WithDescription($"本日は {Format.Bold($"{gacha.HitProbability.Rate:P0}")} の確率で反応します") - .AddField("排出確率", DiscordMessageUtility.Table(records)); + .WithDescription($"本日は {$"{gacha.HitProbability.Rate:P0}".Custom("b")} の確率で反応します") + .AddField("排出確率", F.Table(records)); } public static string CreateRankingView(IReadOnlyList rankingUsers) @@ -29,9 +30,7 @@ public static string CreateRankingView(IReadOnlyList rankingUsers) { var scoreText = Math.Min(999_999_999, user.MonthlyGachaPurchasePrice).ToString("N0"); var whiteSpace = Math.Max(0, 11 - scoreText.Length); - var line = - Format.Code($"#{order:D2} - {"".PadLeft(whiteSpace, ' ')}{scoreText}†カス†(税込)") + " " + - MentionUtils.MentionUser(user.DiscordId); + var line = $"#{order:D2} - {"".PadLeft(whiteSpace, ' ')}{scoreText}†カス†(税込)".Custom("c") + " " + MentionUtils.MentionUser(user.DiscordId); embedBuilder.AppendLine(line); order++; } diff --git a/Events/IssoUtility.cs b/Events/IssoUtility.cs deleted file mode 100644 index 80f34fd..0000000 --- a/Events/IssoUtility.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Approvers.King.Events; - -public static class IssoUtility -{ - public const string SmileStamp = "<:isso_smile:1081501060369236069>"; -} diff --git a/Events/Marugame/MarugamePresenter.cs b/Events/Marugame/MarugamePresenter.cs index e5b5407..a630677 100644 --- a/Events/Marugame/MarugamePresenter.cs +++ b/Events/Marugame/MarugamePresenter.cs @@ -18,7 +18,7 @@ protected override async Task MainAsync() return; } - var message = Format.Code(ConvertMessageToVertical(Content)); + var message = ConvertMessageToVertical(Content).Custom("c"); await Message.ReplyAsync(message); } diff --git a/Events/MessageConst.cs b/Events/MessageConst.cs deleted file mode 100644 index c4b7a11..0000000 --- a/Events/MessageConst.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Approvers.King.Events; - -public static class MessageConst -{ - public const string MissingMessage = "[不明なメッセージ]"; -} diff --git a/Events/MonthlyReset/MonthlyResetPresenter.cs b/Events/MonthlyReset/MonthlyResetPresenter.cs index dfb08fd..dfb79aa 100644 --- a/Events/MonthlyReset/MonthlyResetPresenter.cs +++ b/Events/MonthlyReset/MonthlyResetPresenter.cs @@ -4,6 +4,8 @@ namespace Approvers.King.Events; +using F = DiscordFormatUtility; + /// /// 毎月のリセットを行うイベント /// @@ -34,7 +36,7 @@ private async Task SendSummaryAsync(IReadOnlyList purchaseRankingUsers, IR { var embed = new EmbedBuilder() .WithColor(Color.LightOrange) - .WithTitle(Format.Bold($"{IssoUtility.SmileStamp} †今月も貢げカス† {IssoUtility.SmileStamp}")) + .WithTitle($"{F.Smile} †今月も貢げカス† {F.Smile}".Custom("b")) .WithDescription("月が変わったから課金額をリセットした") .AddField("先月の課金額ランキング", GachaUtility.CreateRankingView(purchaseRankingUsers)) .AddField("先月の利益ランキング", SlotUtility.CreateRankingView(slotRewardRankingUsers)) diff --git a/Events/Slot/SlotExecutePresenter.cs b/Events/Slot/SlotExecutePresenter.cs index 2c62c5d..dfc75f3 100644 --- a/Events/Slot/SlotExecutePresenter.cs +++ b/Events/Slot/SlotExecutePresenter.cs @@ -72,11 +72,11 @@ private static string CreatePurchaseMessage(SlotExecuteResult result, User user, { if (result.IsWin) { - sb.AppendLine(Format.Bold($"Y O U W I N ! ! x{result.ResultRate.Rate:F1}")); + sb.AppendLine($"Y O U W I N ! ! x{result.ResultRate.Rate:F1}".Custom("b")); } else { - sb.AppendLine(Format.Bold($"Y O U L O S E")); + sb.AppendLine($"Y O U L O S E".Custom("b")); } } diff --git a/Events/Slot/SlotUtility.cs b/Events/Slot/SlotUtility.cs index e384ebf..33c40c9 100644 --- a/Events/Slot/SlotUtility.cs +++ b/Events/Slot/SlotUtility.cs @@ -14,9 +14,7 @@ public static string CreateRankingView(IReadOnlyList rankingUsers) { var scoreText = Math.Min(999_999_999, user.MonthlySlotProfitPrice).ToString("N0"); var whiteSpace = Math.Max(0, 11 - scoreText.Length); - var line = - Format.Code($"#{order:D2} - {"".PadLeft(whiteSpace, ' ')}{scoreText}†カス†(税込)") + " " + - MentionUtils.MentionUser(user.DiscordId); + var line = $"#{order:D2} - {"".PadLeft(whiteSpace, ' ')}{scoreText}†カス†(税込)".Custom("c") + " " + MentionUtils.MentionUser(user.DiscordId); embedBuilder.AppendLine(line); order++; } diff --git a/Makefile b/Makefile index 6228e0c..585fe32 100644 --- a/Makefile +++ b/Makefile @@ -7,10 +7,7 @@ migrate: run: dotnet run -.PHONY: docker-build -docker-build: +.PHONY: push +push: docker build . -t $(app_name) - -.PHONY: docker-push -docker-push: docker push $(app_name) diff --git a/Program.cs b/Program.cs index 99ad03b..8e8e778 100644 --- a/Program.cs +++ b/Program.cs @@ -65,7 +65,6 @@ private static void RegisterEvents() }; SchedulerManager.RegisterDaily(TimeManager.DailyResetTime); - SchedulerManager.RegisterYearly(TimeManager.Birthday + TimeManager.DailyResetTime + TimeSpan.FromSeconds(1)); SchedulerManager.RegisterMonthly(TimeManager.MonthlyResetDay, TimeManager.DailyResetTime); SchedulerManager.RegisterOn(x => x.Minute is 0); }