diff --git a/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs b/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs new file mode 100644 index 0000000..422aae6 --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/AiAssistantService.cs @@ -0,0 +1,314 @@ +using EllieBot.Common.ModuleBehaviors; +using EllieBot.Modules.Administration; +using EllieBot.Modules.Games.Services; +using System.Net; +using System.Net.Http.Json; +using System.Text; +using System.Text.Json; +using JsonSerializer = System.Text.Json.JsonSerializer; + +namespace EllieBot.Modules.Utility; + +public enum GetCommandErrorResult +{ + RateLimitHit, + NotAuthorized, + Disregard, + Unknown +} + +public sealed class AiAssistantService + : IAiAssistantService, IReadyExecutor, + IExecOnMessage, + IEService +{ + private IReadOnlyCollection _commands = []; + + private readonly IBotStrings _strings; + private readonly IHttpClientFactory _httpFactory; + private readonly CommandService _cmds; + private readonly IBotCredsProvider _credsProvider; + private readonly DiscordSocketClient _client; + private readonly ICommandHandler _cmdHandler; + private readonly BotConfigService _bcs; + private readonly IMessageSenderService _sender; + + private readonly JsonSerializerOptions _serializerOptions = new(); + private readonly IPermissionChecker _permChecker; + private readonly IBotCache _botCache; + private readonly ChatterBotService _cbs; + + public AiAssistantService( + DiscordSocketClient client, + IBotStrings strings, + IHttpClientFactory httpFactory, + CommandService cmds, + IBotCredsProvider credsProvider, + ICommandHandler cmdHandler, + BotConfigService bcs, + IPermissionChecker permChecker, + IBotCache botCache, + ChatterBotService cbs, + IMessageSenderService sender) + { + _client = client; + _strings = strings; + _httpFactory = httpFactory; + _cmds = cmds; + _credsProvider = credsProvider; + _cmdHandler = cmdHandler; + _bcs = bcs; + _sender = sender; + _permChecker = permChecker; + _botCache = botCache; + _cbs = cbs; + } + + public async Task> TryGetCommandAsync( + ulong userId, + string prompt, + IReadOnlyCollection commands, + string prefix) + { + using var content = new StringContent( + JsonSerializer.Serialize(new + { + query = prompt, + commands = commands.ToDictionary(x => x.Name, + x => new AiCommandModel() + { + Desc = string.Format(x.Desc ?? "", prefix), + Params = x.Params, + Name = x.Name + }), + }), + Encoding.UTF8, + "application/json" + ); + + using var request = new HttpRequestMessage(); + request.Method = HttpMethod.Post; + // request.RequestUri = new("https://nai.nadeko.bot/get-command"); + request.RequestUri = new("https://nai.nadeko.bot/get-command"); + request.Content = content; + + var creds = _credsProvider.GetCreds(); + + request.Headers.TryAddWithoutValidation("x-auth-token", creds.EllieAiToken); + request.Headers.TryAddWithoutValidation("x-auth-userid", userId.ToString()); + + + using var client = _httpFactory.CreateClient(); + + // todo customize according to the bot's config + // - CurrencyName + // - + + using var response = await client.SendAsync(request); + + if (response.StatusCode == HttpStatusCode.TooManyRequests) + { + return GetCommandErrorResult.RateLimitHit; + } + else if (response.StatusCode == HttpStatusCode.Unauthorized) + { + return GetCommandErrorResult.NotAuthorized; + } + + var funcModel = await response.Content.ReadFromJsonAsync(); + + + if (funcModel?.Name == "disregard") + { + Log.Warning("Disregarding the prompt: {Prompt}", prompt); + return GetCommandErrorResult.Disregard; + } + + if (funcModel is null) + return GetCommandErrorResult.Unknown; + + var comModel = new EllieCommandCallModel() + { + Name = funcModel.Name, + Arguments = funcModel.Arguments + .OrderBy(param => _commands.FirstOrDefault(x => x.Name == funcModel.Name) + ?.Params + .Select((x, i) => (x, i)) + .Where(x => x.x.Name == param.Key) + .Select(x => x.i) + .FirstOrDefault()) + .Select(x => x.Value) + .Where(x => !string.IsNullOrWhiteSpace(x)) + .ToArray(), + Remaining = funcModel.Remaining + }; + + return comModel; + } + + public IReadOnlyCollection GetCommands() + => _commands; + + public Task OnReadyAsync() + { + var cmds = _cmds.Commands + .Select(x => (MethodName: x.Summary, CommandName: x.Aliases[0])) + .Where(x => !x.MethodName.Contains("///")) + .Distinct() + .ToList(); + + var funcs = new List(); + foreach (var (method, cmd) in cmds) + { + var commandStrings = _strings.GetCommandStrings(method); + + if (commandStrings is null) + continue; + + funcs.Add(new() + { + Name = cmd, + Desc = commandStrings?.Desc?.Replace("currency", "flowers") ?? string.Empty, + Params = commandStrings?.Params.FirstOrDefault() + ?.Select(x => new AiCommandParamModel() + { + Desc = x.Value.Desc, + Name = x.Key, + }) + .ToArray() + ?? [] + }); + } + + _commands = funcs; + + return Task.CompletedTask; + } + + public int Priority + => 2; + + public async Task ExecOnMessageAsync(IGuild guild, IUserMessage msg) + { + if (string.IsNullOrWhiteSpace(_credsProvider.GetCreds().EllieAiToken)) + return false; + + if (guild is not SocketGuild sg) + return false; + + var nadekoId = _client.CurrentUser.Id; + + var channel = msg.Channel as ITextChannel; + if (channel is null) + return false; + + var normalMention = $"<@{nadekoId}> "; + var nickMention = $"<@!{nadekoId}> "; + string query; + if (msg.Content.StartsWith(normalMention, StringComparison.InvariantCulture)) + query = msg.Content[normalMention.Length..].Trim(); + else if (msg.Content.StartsWith(nickMention, StringComparison.InvariantCulture)) + query = msg.Content[nickMention.Length..].Trim(); + else + return false; + + var success = await TryExecuteAiCommand(guild, msg, channel, query); + + return success; + } + + public async Task TryExecuteAiCommand( + IGuild guild, + IUserMessage msg, + ITextChannel channel, + string query) + { + // check permissions + var pcResult = await _permChecker.CheckPermsAsync( + guild, + msg.Channel, + msg.Author, + "Utility", + "prompt" + ); + + if (!pcResult.IsAllowed) + return false; + + using var _ = channel.EnterTypingState(); + + var result = await TryGetCommandAsync(msg.Author.Id, query, _commands, _cmdHandler.GetPrefix(guild.Id)); + + if (result.TryPickT0(out var model, out var error)) + { + if (model.Name == ".ai_chat") + { + if (guild is not SocketGuild sg) + return false; + + var sess = _cbs.GetOrCreateSession(guild.Id); + if (sess is null) + return false; + + await _cbs.RunChatterBot(sg, msg, channel, sess, query); + return false; + } + + var commandString = GetCommandString(model); + + var msgTask = _sender.Response(channel) + .Embed(_sender.CreateEmbed() + .WithOkColor() + .WithAuthor(msg.Author.GlobalName, + msg.Author.RealAvatarUrl().ToString()) + .WithDescription(commandString)) + .SendAsync(); + + + await _cmdHandler.TryRunCommand( + (SocketGuild)guild, + (ISocketMessageChannel)channel, + new DoAsUserMessage((SocketUserMessage)msg, msg.Author, commandString)); + + var cmdMsg = await msgTask; + + cmdMsg.DeleteAfter(5); + + return true; + } + + if (error == GetCommandErrorResult.Disregard) + { + // await msg.ErrorAsync(); + return false; + } + + var key = new TypedKey($"sub_error:{msg.Author.Id}:{error}"); + + if (!await _botCache.AddAsync(key, true, TimeSpan.FromDays(1), overwrite: false)) + return false; + + var errorMsg = error switch + { + GetCommandErrorResult.RateLimitHit + => "You've spent your daily requests quota.", + GetCommandErrorResult.NotAuthorized + => "In order to use this command you have to have a 5$ or higher subscription at ", + GetCommandErrorResult.Unknown + => "The service is temporarily unavailable.", + _ => throw new ArgumentOutOfRangeException() + }; + + await _sender.Response(channel) + .Error(errorMsg) + .SendAsync(); + + return true; + } + + private string GetCommandString(EllieCommandCallModel res) + => $"{_bcs.Data.Prefix}{res.Name} {res.Arguments.Select((x, i) => GetParamString(x, i + 1 == res.Arguments.Count)).Join(" ")}"; + + private static string GetParamString(string val, bool isLast) + => isLast ? val : "\"" + val + "\""; +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs b/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs new file mode 100644 index 0000000..eeaf38b --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/AiCommandModel.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace EllieBot.Modules.Utility; + +public sealed class AiCommandModel +{ + [JsonPropertyName("name")] + public required string Name { get; set; } + + [JsonPropertyName("desc")] + public required string Desc { get; set; } + + [JsonPropertyName("params")] + public required IReadOnlyList Params { get; set; } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Ai/AiCommandParamModel.cs b/src/EllieBot/Modules/Utility/Ai/AiCommandParamModel.cs new file mode 100644 index 0000000..594d581 --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/AiCommandParamModel.cs @@ -0,0 +1,12 @@ +using System.Text.Json.Serialization; + +namespace EllieBot.Modules.Utility; + +public sealed class AiCommandParamModel +{ + [JsonPropertyName("name")] + public required string Name { get; set; } + + [JsonPropertyName("desc")] + public required string Desc { get; set; } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Ai/CommandPromptResultModel.cs b/src/EllieBot/Modules/Utility/Ai/CommandPromptResultModel.cs new file mode 100644 index 0000000..78d6179 --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/CommandPromptResultModel.cs @@ -0,0 +1,16 @@ +using System.Text.Json.Serialization; + +namespace EllieBot.Modules.Utility; + +public sealed class CommandPromptResultModel +{ + [JsonPropertyName("name")] + public required string Name { get; set; } + + [JsonPropertyName("arguments")] + public required Dictionary Arguments { get; set; } + + [JsonPropertyName("remaining")] + [JsonConverter(typeof(NumberToStringConverter))] + public required string Remaining { get; set; } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Ai/EllieCommandCallModel.cs b/src/EllieBot/Modules/Utility/Ai/EllieCommandCallModel.cs new file mode 100644 index 0000000..4de388e --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/EllieCommandCallModel.cs @@ -0,0 +1,8 @@ +namespace EllieBot.Modules.Utility; + +public sealed class EllieCommandCallModel +{ + public required string Name { get; set; } + public required IReadOnlyList Arguments { get; set; } + public required string Remaining { get; set; } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Ai/IAiAssistantService.cs b/src/EllieBot/Modules/Utility/Ai/IAiAssistantService.cs new file mode 100644 index 0000000..0fc17e2 --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/IAiAssistantService.cs @@ -0,0 +1,20 @@ +using OneOf; + +namespace EllieBot.Modules.Utility; + +public interface IAiAssistantService +{ + Task> TryGetCommandAsync( + ulong userId, + string prompt, + IReadOnlyCollection commands, + string prefix); + + IReadOnlyCollection GetCommands(); + + Task TryExecuteAiCommand( + IGuild guild, + IUserMessage msg, + ITextChannel channel, + string query); +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Ai/UtilityCommands.cs b/src/EllieBot/Modules/Utility/Ai/UtilityCommands.cs new file mode 100644 index 0000000..52fe4d5 --- /dev/null +++ b/src/EllieBot/Modules/Utility/Ai/UtilityCommands.cs @@ -0,0 +1,23 @@ +using EllieBot.Modules.Administration; + +namespace EllieBot.Modules.Utility; + +public partial class UtilityCommands +{ + public class PromptCommands : EllieModule + { + [Cmd] + [RequireContext(ContextType.Guild)] + public async Task Prompt([Leftover] string query) + { + await ctx.Channel.TriggerTypingAsync(); + var res = await _service.TryExecuteAiCommand(ctx.Guild, ctx.Message, (ITextChannel)ctx.Channel, query); + } + + private string GetCommandString(EllieCommandCallModel res) + => $"{_bcs.Data.Prefix}{res.Name} {res.Arguments.Select((x, i) => GetParamString(x, i + 1 == res.Arguments.Count)).Join(" ")}"; + + private static string GetParamString(string val, bool isLast) + => isLast ? val : "\"" + val + "\""; + } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Calc/CalcCommand.cs b/src/EllieBot/Modules/Utility/Calc/CalcCommands.cs similarity index 100% rename from src/EllieBot/Modules/Utility/Calc/CalcCommand.cs rename to src/EllieBot/Modules/Utility/Calc/CalcCommands.cs diff --git a/src/EllieBot/Modules/Utility/ConfigCommands.cs b/src/EllieBot/Modules/Utility/ConfigCommands.cs index 28f9772..57b8f4c 100644 --- a/src/EllieBot/Modules/Utility/ConfigCommands.cs +++ b/src/EllieBot/Modules/Utility/ConfigCommands.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Modules.Utility; public partial class Utility @@ -138,12 +138,12 @@ public partial class Utility private string GetPropsAndValuesString(IConfigService config, IReadOnlyCollection names) { var propValues = names.Select(pr => - { - var val = config.GetSetting(pr); - if (pr != "currency.sign") - val = val?.TrimTo(28); - return val?.Replace("\n", "") ?? "-"; - }) + { + var val = config.GetSetting(pr); + if (pr != "currency.sign") + val = val?.TrimTo(28); + return val?.Replace("\n", "") ?? "-"; + }) .ToList(); var strings = names.Zip(propValues, (name, value) => $"{name,-25} = {value}\n"); diff --git a/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs b/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs index a2ebf58..2109eef 100644 --- a/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs +++ b/src/EllieBot/Modules/Utility/Giveaway/GiveawayCommands.cs @@ -48,30 +48,30 @@ public partial class Utility [UserPerm(GuildPerm.ManageMessages)] public async Task GiveawayEnd(kwum id) { - var success = await _service.EndGiveawayAsync(ctx.Guild.Id, id); + var success = await _service.EndGiveawayAsync(ctx.Guild.Id, id); - if (!success) - { - await Response().Error(strs.giveaway_not_found).SendAsync(); - return; - } + if(!success) + { + await Response().Error(strs.giveaway_not_found).SendAsync(); + return; + } - await ctx.OkAsync(); + await ctx.OkAsync(); _ = ctx.Message.DeleteAfter(5); } [Cmd] [UserPerm(GuildPerm.ManageMessages)] public async Task GiveawayReroll(kwum id) - { + { var success = await _service.RerollGiveawayAsync(ctx.Guild.Id, id); if (!success) { await Response().Error(strs.giveaway_not_found).SendAsync(); return; } - - + + await ctx.OkAsync(); _ = ctx.Message.DeleteAfter(5); } diff --git a/src/EllieBot/Modules/Utility/GuildColors.cs b/src/EllieBot/Modules/Utility/GuildColors.cs index bf50902..7f787e6 100644 --- a/src/EllieBot/Modules/Utility/GuildColors.cs +++ b/src/EllieBot/Modules/Utility/GuildColors.cs @@ -4,7 +4,7 @@ namespace EllieBot.Modules.Utility; public interface IGuildColorsService { - + } public sealed class GuildColorsService : IGuildColorsService, IEService @@ -34,6 +34,6 @@ public partial class Utility { public class GuildColorsCommands : EllieModule { - + } } \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs index 87b8aa1..e2533e0 100644 --- a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs +++ b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System.Text; using EllieBot.Modules.Patronage; @@ -34,7 +34,7 @@ public partial class Utility { var guild = (IGuild)_client.GetGuild(guildId) ?? await _client.Rest.GetGuildAsync(guildId); - + if (guild is null) return; @@ -144,9 +144,9 @@ public partial class Utility true) .WithOkColor(); - var patron = await _ps.GetPatronAsync(user.Id); + var mPatron = await _ps.GetPatronAsync(user.Id); - if (patron.Tier != PatronTier.None) + if (mPatron is {} patron && patron.Tier != PatronTier.None) { embed.WithFooter(patron.Tier switch { diff --git a/src/EllieBot/Modules/Utility/Invite/InviteService.cs b/src/EllieBot/Modules/Utility/Invite/InviteService.cs index aa6946b..d89ec28 100644 --- a/src/EllieBot/Modules/Utility/Invite/InviteService.cs +++ b/src/EllieBot/Modules/Utility/Invite/InviteService.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using CommandLine; namespace EllieBot.Modules.Utility.Services; @@ -45,4 +45,4 @@ public class InviteService : IEService Expire = 0; } } -} +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Quote/IQuoteService.cs b/src/EllieBot/Modules/Utility/Quote/IQuoteService.cs index 55dc96b..ccf360e 100644 --- a/src/EllieBot/Modules/Utility/Quote/IQuoteService.cs +++ b/src/EllieBot/Modules/Utility/Quote/IQuoteService.cs @@ -3,4 +3,4 @@ public interface IQuoteService { Task DeleteAllAuthorQuotesAsync(ulong guildId, ulong userId); -} +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs b/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs index cea5914..913781b 100644 --- a/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs +++ b/src/EllieBot/Modules/Utility/Quote/QuoteCommands.cs @@ -1,4 +1,4 @@ -#nullable disable warnings +#nullable disable warnings using LinqToDB; using LinqToDB.EntityFrameworkCore; using EllieBot.Common.Yml; @@ -157,8 +157,8 @@ public partial class Utility async (sm) => { var msg = sm.Data.Components.FirstOrDefault()?.Value; - - if (!string.IsNullOrWhiteSpace(msg)) + + if(!string.IsNullOrWhiteSpace(msg)) await QuoteEdit(id, msg); } ); @@ -307,7 +307,7 @@ public partial class Utility .UpdateWithOutputAsync((del, ins) => ins); q = result.FirstOrDefault(); - + await uow.SaveChangesAsync(); } diff --git a/src/EllieBot/Modules/Utility/Quote/QuoteService.cs b/src/EllieBot/Modules/Utility/Quote/QuoteService.cs index bebed66..db49648 100644 --- a/src/EllieBot/Modules/Utility/Quote/QuoteService.cs +++ b/src/EllieBot/Modules/Utility/Quote/QuoteService.cs @@ -1,4 +1,4 @@ -#nullable disable warnings +#nullable disable warnings using LinqToDB; using LinqToDB.EntityFrameworkCore; using EllieBot.Db.Models; @@ -13,7 +13,7 @@ public sealed class QuoteService : IQuoteService, IEService { _db = db; } - + /// /// Delete all quotes created by the author in a guild /// diff --git a/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs b/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs index 8a414dc..67b87af 100644 --- a/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs +++ b/src/EllieBot/Modules/Utility/Remind/RemindCommands.cs @@ -113,10 +113,9 @@ public partial class Utility foreach (var rem in rems) { var when = rem.When; - var diff = when - DateTime.UtcNow; embed.AddField( $"#{++i + (page * 10)} {rem.When:HH:mm yyyy-MM-dd} UTC " - + $"(in {diff.ToPrettyStringHm()})", + + $"{TimestampTag.FromDateTime(when)}", $@"`Target:` {(rem.IsPrivate ? "DM" : "Channel")} `TargetId:` {rem.ChannelId} `Message:` {rem.Message?.TrimTo(50)}"); @@ -203,16 +202,15 @@ public partial class Utility await uow.SaveChangesAsync(); } - var gTime = ctx.Guild is null ? time : TimeZoneInfo.ConvertTime(time, _tz.GetTimeZoneOrUtc(ctx.Guild.Id)); + // var gTime = ctx.Guild is null ? time : TimeZoneInfo.ConvertTime(time, _tz.GetTimeZoneOrUtc(ctx.Guild.Id)); try { await Response() - .Confirm($"\u23f0 {GetText(strs.remind( + .Confirm($"\u23f0 {GetText(strs.remind2( Format.Bold(!isPrivate ? $"<#{targetId}>" : ctx.User.Username), Format.Bold(message), - ts.ToPrettyStringHm(), - gTime, - gTime))}") + TimestampTag.FromDateTime(DateTime.UtcNow.Add(ts), TimestampTagStyles.Relative), + TimestampTag.FormatFromDateTime(time, TimestampTagStyles.ShortDateTime)))}") .SendAsync(); } catch diff --git a/src/EllieBot/Modules/Utility/Repeater/RepeaterService.cs b/src/EllieBot/Modules/Utility/Repeater/RepeaterService.cs index 6adb2c0..07d05cc 100644 --- a/src/EllieBot/Modules/Utility/Repeater/RepeaterService.cs +++ b/src/EllieBot/Modules/Utility/Repeater/RepeaterService.cs @@ -273,7 +273,7 @@ public sealed class RepeaterService : IReadyExecutor, IEService .Text(text) .Sanitize(false) .SendAsync(); - + _ = newMsg.AddReactionAsync(new Emoji("🔄")); if (_noRedundant.Contains(repeater.Id)) diff --git a/src/EllieBot/Modules/Utility/Repeater/RunningRepeater.cs b/src/EllieBot/Modules/Utility/Repeater/RunningRepeater.cs index 52f4072..509347f 100644 --- a/src/EllieBot/Modules/Utility/Repeater/RunningRepeater.cs +++ b/src/EllieBot/Modules/Utility/Repeater/RunningRepeater.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using EllieBot.Db.Models; namespace EllieBot.Modules.Utility.Services; diff --git a/src/EllieBot/Modules/Utility/StreamRole/StreamRoleService.cs b/src/EllieBot/Modules/Utility/StreamRole/StreamRoleService.cs index 1b5796a..4ded9d0 100644 --- a/src/EllieBot/Modules/Utility/StreamRole/StreamRoleService.cs +++ b/src/EllieBot/Modules/Utility/StreamRole/StreamRoleService.cs @@ -30,7 +30,7 @@ public class StreamRoleService : IReadyExecutor, IEService private Task OnPresenceUpdate(SocketUser user, SocketPresence? oldPresence, SocketPresence? newPresence) { - + _ = Task.Run(async () => { if (oldPresence?.Activities?.Count != newPresence?.Activities?.Count) diff --git a/src/EllieBot/Modules/Utility/Todo/TodoService.cs b/src/EllieBot/Modules/Utility/Todo/TodoService.cs index 72a7d13..38ea848 100644 --- a/src/EllieBot/Modules/Utility/Todo/TodoService.cs +++ b/src/EllieBot/Modules/Utility/Todo/TodoService.cs @@ -140,7 +140,7 @@ public sealed class TodoService : IEService return ArchiveTodoResult.NoTodos; } - + await tr.CommitAsync(); return ArchiveTodoResult.Success; @@ -183,7 +183,7 @@ public sealed class TodoService : IEService public async Task GetTodoAsync(ulong userId, int todoId) { await using var ctx = _db.GetDbContext(); - + return await ctx .GetTable() .Where(x => x.UserId == userId && x.Id == todoId) diff --git a/src/EllieBot/Modules/Utility/UnitConversion/ConverterService.cs b/src/EllieBot/Modules/Utility/UnitConversion/ConverterService.cs index 85c299d..12d9f8e 100644 --- a/src/EllieBot/Modules/Utility/UnitConversion/ConverterService.cs +++ b/src/EllieBot/Modules/Utility/UnitConversion/ConverterService.cs @@ -63,20 +63,20 @@ public class ConverterService : IEService, IReadyExecutor UnitType = unitTypeString }; var units = currencyRates.ConversionRates.Select(u => new ConvertUnit - { - Triggers = [u.Key], - Modifier = u.Value, - UnitType = unitTypeString - }) + { + Triggers = [u.Key], + Modifier = u.Value, + UnitType = unitTypeString + }) .ToList(); - var stream = File.OpenRead("data/units.json"); + var stream = File.OpenRead("data/units.json"); var defaultUnits = await JsonSerializer.DeserializeAsync(stream); - if (defaultUnits is not null) + if(defaultUnits is not null) units.AddRange(defaultUnits); - + units.Add(baseType); - + await _cache.AddAsync(_convertKey, units); } @@ -90,7 +90,7 @@ public class Rates { [JsonPropertyName("base")] public string Base { get; set; } - + [JsonPropertyName("date")] public DateTime Date { get; set; } diff --git a/src/EllieBot/Modules/Utility/Utility.cs b/src/EllieBot/Modules/Utility/Utility.cs index 1c53f8c..7382403 100644 --- a/src/EllieBot/Modules/Utility/Utility.cs +++ b/src/EllieBot/Modules/Utility/Utility.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using EllieBot.Modules.Utility.Services; using Newtonsoft.Json; using System.Diagnostics; diff --git a/src/EllieBot/Modules/Utility/VerboseErrorsService.cs b/src/EllieBot/Modules/Utility/VerboseErrorsService.cs index e80f889..c5cf886 100644 --- a/src/EllieBot/Modules/Utility/VerboseErrorsService.cs +++ b/src/EllieBot/Modules/Utility/VerboseErrorsService.cs @@ -58,7 +58,7 @@ public class VerboseErrorsService : IEService if (maybeEnabled is bool isEnabled) // set it gc.VerboseErrors = isEnabled; else // toggle it - isEnabled = gc.VerboseErrors = !gc.VerboseErrors; + isEnabled = gc.VerboseErrors = !gc.VerboseErrors; uow.SaveChanges(); diff --git a/src/EllieBot/Modules/Utility/_common/ConvertUnit.cs b/src/EllieBot/Modules/Utility/_common/ConvertUnit.cs index e38cbe4..b65fdea 100644 --- a/src/EllieBot/Modules/Utility/_common/ConvertUnit.cs +++ b/src/EllieBot/Modules/Utility/_common/ConvertUnit.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable using System.Diagnostics; namespace EllieBot.Modules.Utility.Common; diff --git a/src/EllieBot/Modules/Utility/_common/EvalGlobals.cs b/src/EllieBot/Modules/Utility/_common/EvalGlobals.cs index ffe3ecd..a31c056 100644 --- a/src/EllieBot/Modules/Utility/_common/EvalGlobals.cs +++ b/src/EllieBot/Modules/Utility/_common/EvalGlobals.cs @@ -1,4 +1,4 @@ -// ReSharper disable InconsistentNaming +// ReSharper disable InconsistentNaming #nullable disable namespace EllieBot.Modules.Utility; diff --git a/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRoleNotFoundException.cs b/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRoleNotFoundException.cs index 45e007e..d1880b2 100644 --- a/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRoleNotFoundException.cs +++ b/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRoleNotFoundException.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Modules.Utility.Common.Exceptions; public class StreamRoleNotFoundException : Exception @@ -8,13 +8,13 @@ public class StreamRoleNotFoundException : Exception { } - public StreamRoleNotFoundException(string message) + public StreamRoleNotFoundException(string message) : base(message) { } - public StreamRoleNotFoundException(string message, Exception innerException) + public StreamRoleNotFoundException(string message, Exception innerException) : base(message, innerException) { } -} +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRolePermissionException.cs b/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRolePermissionException.cs index 97fd187..d75c53c 100644 --- a/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRolePermissionException.cs +++ b/src/EllieBot/Modules/Utility/_common/Exceptions/StreamRolePermissionException.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Modules.Utility.Common.Exceptions; public class StreamRolePermissionException : Exception diff --git a/src/EllieBot/Modules/Utility/_common/StreamRoleListType.cs b/src/EllieBot/Modules/Utility/_common/StreamRoleListType.cs index 775b346..aca487b 100644 --- a/src/EllieBot/Modules/Utility/_common/StreamRoleListType.cs +++ b/src/EllieBot/Modules/Utility/_common/StreamRoleListType.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable namespace EllieBot.Modules.Utility.Common; public enum StreamRoleListType