diff --git a/CHANGELOG.md b/CHANGELOG.md index 82d9e1a..2dd6640 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ *a,c,f,r,o* +## [6.0.9] - 19.03.2025 + +### Changed + + - `.cinfo` now also has a member list + +### Fixed + + - `.antispamignore` will now properly persist through restarts + - livechannels and scheduled commands will now be inside utility module as they should + ## [6.0.8] - 19.03.2025 ### Added @@ -14,6 +25,7 @@ - `.lchd <channel or channelId>` removed a live channel ### Fixed + - `.antispamignore` fixed ## [6.0.7] - 19.03.2025 diff --git a/src/EllieBot.GrpcApiBase/EllieBot.GrpcApiBase.csproj b/src/EllieBot.GrpcApiBase/EllieBot.GrpcApiBase.csproj index 16fcb89..abdc85d 100644 --- a/src/EllieBot.GrpcApiBase/EllieBot.GrpcApiBase.csproj +++ b/src/EllieBot.GrpcApiBase/EllieBot.GrpcApiBase.csproj @@ -9,7 +9,7 @@ <ItemGroup> <PackageReference Include="Google.Protobuf" Version="3.29.3" /> <PackageReference Include="Grpc" Version="2.46.6" /> - <PackageReference Include="Grpc.Tools" Version="2.69.0" PrivateAssets="All" /> + <PackageReference Include="Grpc.Tools" Version="2.68.1" PrivateAssets="All" /> </ItemGroup> <ItemGroup> diff --git a/src/EllieBot/EllieBot.csproj b/src/EllieBot/EllieBot.csproj index 5ba587d..3cf7abb 100644 --- a/src/EllieBot/EllieBot.csproj +++ b/src/EllieBot/EllieBot.csproj @@ -4,7 +4,7 @@ <Nullable>enable</Nullable> <ImplicitUsings>true</ImplicitUsings> <SatelliteResourceLanguages>en</SatelliteResourceLanguages> - <Version>6.0.8</Version> + <Version>6.0.9</Version> <!-- Output/build --> <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory> @@ -34,7 +34,7 @@ <PackageReference Include="Google.Protobuf" Version="3.29.3" /> <PackageReference Include="Grpc" Version="2.46.6" /> <PackageReference Include="Grpc.Net.Client" Version="2.67.0" /> - <PackageReference Include="Grpc.Tools" Version="2.69.0" PrivateAssets="All" /> + <PackageReference Include="Grpc.Tools" Version="2.68.1" PrivateAssets="All" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.8.0" /> diff --git a/src/EllieBot/Modules/Administration/Protection/ProtectionService.cs b/src/EllieBot/Modules/Administration/Protection/ProtectionService.cs index a6716e8..d97442d 100644 --- a/src/EllieBot/Modules/Administration/Protection/ProtectionService.cs +++ b/src/EllieBot/Modules/Administration/Protection/ProtectionService.cs @@ -407,6 +407,7 @@ public class ProtectionService : IReadyExecutor, IEService if (_antiSpamGuilds.TryGetValue(guildId, out var temp)) temp.AntiSpamSettings.IgnoredChannels.Add(obj); // add to local cache + spam.IgnoredChannels.Add(obj); added = true; } else diff --git a/src/EllieBot/Modules/Help/CommandListGenerator.cs b/src/EllieBot/Modules/Help/CommandListGenerator.cs new file mode 100644 index 0000000..212c9b3 --- /dev/null +++ b/src/EllieBot/Modules/Help/CommandListGenerator.cs @@ -0,0 +1,62 @@ +#nullable disable +using System.Globalization; +using System.Text; +using Ellie.Common.Marmalade; +using EllieBot.Common.ModuleBehaviors; +using Newtonsoft.Json; + +namespace EllieBot.Modules.Help; + +public sealed partial class CommandListGenerator( + CommandService cmds, + IMarmaladeLoaderService marmalades, + IBotStrings strings +) : IEService, IReadyExecutor +{ + public async Task OnReadyAsync() + { + await Task.Delay(10_000); + +#if DEBUG + await GenerateCommandListAsync(".", CultureInfo.InvariantCulture); +#endif + } + + public async Task<Stream> GenerateCommandListAsync(string prefix, CultureInfo culture) + { + // order commands by top level name + // and make a dictionary of <ModuleName, Array<JsonCommandData>> + var cmdData = cmds.Commands.GroupBy(x => x.Module.GetTopLevelModule().Name) + .OrderBy(x => x.Key) + .ToDictionary(x => x.Key, + x => x.DistinctBy(c => c.Aliases.First()) + .Select(com => + { + List<string> optHelpStr = null; + + var opt = CommandsUtilityService.GetEllieOptionType(com.Attributes); + if (opt is not null) + optHelpStr = CommandsUtilityService.GetCommandOptionHelpList(opt); + + return new CommandJsonObject + { + Aliases = com.Aliases.Select(alias => prefix + alias).ToArray(), + Description = com.RealSummary(strings, marmalades, culture, prefix), + Usage = com.RealRemarksArr(strings, marmalades, culture, prefix), + Submodule = com.Module.Name, + Module = com.Module.GetTopLevelModule().Name, + Options = optHelpStr, + Requirements = CommandsUtilityService.GetCommandRequirements(com) + }; + }) + .ToList()); + + var readableData = JsonConvert.SerializeObject(cmdData, Formatting.Indented); + + // send the indented file to chat + var rDataStream = new MemoryStream(Encoding.ASCII.GetBytes(readableData)); + await File.WriteAllTextAsync("data/commandlist.json", readableData); + + return rDataStream; + } +} \ No newline at end of file diff --git a/src/EllieBot/Modules/Help/Help.cs b/src/EllieBot/Modules/Help/Help.cs index 095394b..b2503ee 100644 --- a/src/EllieBot/Modules/Help/Help.cs +++ b/src/EllieBot/Modules/Help/Help.cs @@ -1,8 +1,6 @@ #nullable disable using EllieBot.Modules.Help.Common; using EllieBot.Modules.Help.Services; -using Newtonsoft.Json; -using System.Text; using Ellie.Common.Marmalade; namespace EllieBot.Modules.Help; @@ -22,6 +20,7 @@ public sealed partial class Help : EllieModule<HelpService> private readonly AsyncLazy<ulong> _lazyClientId; private readonly IMarmaladeLoaderService _marmalades; + private readonly CommandListGenerator _cmdListGen; public Help( ICommandsUtilityService _cus, @@ -31,7 +30,8 @@ public sealed partial class Help : EllieModule<HelpService> IServiceProvider services, DiscordSocketClient client, IBotStrings strings, - IMarmaladeLoaderService marmalades) + IMarmaladeLoaderService marmalades, + CommandListGenerator cmdListGen) { this._cus = _cus; _cmds = cmds; @@ -41,6 +41,7 @@ public sealed partial class Help : EllieModule<HelpService> _client = client; _strings = strings; _marmalades = marmalades; + _cmdListGen = cmdListGen; _lazyClientId = new(async () => (await _client.GetApplicationInfoAsync()).Id); } @@ -488,38 +489,7 @@ public sealed partial class Help : EllieModule<HelpService> { _ = ctx.Channel.TriggerTypingAsync(); - // order commands by top level module name - // and make a dictionary of <ModuleName, Array<JsonCommandData>> - var cmdData = _cmds.Commands.GroupBy(x => x.Module.GetTopLevelModule().Name) - .OrderBy(x => x.Key) - .ToDictionary(x => x.Key, - x => x.DistinctBy(c => c.Aliases.First()) - .Select(com => - { - List<string> optHelpStr = null; - - var opt = CommandsUtilityService.GetEllieOptionType(com.Attributes); - if (opt is not null) - optHelpStr = CommandsUtilityService.GetCommandOptionHelpList(opt); - - return new CommandJsonObject - { - Aliases = com.Aliases.Select(alias => prefix + alias).ToArray(), - Description = com.RealSummary(_strings, _marmalades, Culture, prefix), - Usage = com.RealRemarksArr(_strings, _marmalades, Culture, prefix), - Submodule = com.Module.Name, - Module = com.Module.GetTopLevelModule().Name, - Options = optHelpStr, - Requirements = CommandsUtilityService.GetCommandRequirements(com) - }; - }) - .ToList()); - - var readableData = JsonConvert.SerializeObject(cmdData, Formatting.Indented); - - // send the indented file to chat - await using var rDataStream = new MemoryStream(Encoding.ASCII.GetBytes(readableData)); - await File.WriteAllTextAsync("data/commandlist.json", readableData); + await using var rDataStream = await _cmdListGen.GenerateCommandListAsync(prefix, Culture); await ctx.Channel.SendFileAsync(rDataStream, "cmds.json", GetText(strs.commandlist_regen)); } diff --git a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs index 88232a9..0bd8414 100644 --- a/src/EllieBot/Modules/Utility/Info/InfoCommands.cs +++ b/src/EllieBot/Modules/Utility/Info/InfoCommands.cs @@ -84,14 +84,29 @@ public partial class Utility return; var createdAt = new DateTime(2015, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(ch.Id >> 22); var usercount = (await ch.GetUsersAsync().FlattenAsync()).Count(); - var embed = CreateEmbed() - .WithTitle(ch.Name) - .WithDescription(ch.Topic?.SanitizeMentions(true)) - .AddField(GetText(strs.id), ch.Id.ToString(), true) - .AddField(GetText(strs.created_at), $"{createdAt:dd.MM.yyyy HH:mm}", true) - .AddField(GetText(strs.users), usercount.ToString(), true) - .WithOkColor(); - await Response().Embed(embed).SendAsync(); + + var users = await ch.GetUsersAsync(CacheMode.CacheOnly).FlattenAsync().Fmap(x => x.ToList()); + + await Response() + .Paginated() + .Items(users) + .PageSize(20) + .Page((items, _) => + { + var embed = CreateEmbed() + .WithTitle(ch.Name) + .WithDescription(ch.Topic?.SanitizeMentions(true)) + .AddField(GetText(strs.id), ch.Id.ToString(), true) + .AddField(GetText(strs.created_at), + TimestampTag.FromDateTime(createdAt, TimestampTagStyles.ShortDate), + true) + .AddField(GetText(strs.users), usercount.ToString(), true) + .AddField(GetText(strs.members), string.Join(" . ", items.Select(x => x.DisplayName))) + .WithOkColor(); + + return embed; + }) + .SendAsync(); } [Cmd] diff --git a/src/EllieBot/Modules/Utility/LiveChannel/LiveChannelCommands.cs b/src/EllieBot/Modules/Utility/LiveChannel/LiveChannelCommands.cs index 3c3b7b5..b3093f6 100644 --- a/src/EllieBot/Modules/Utility/LiveChannel/LiveChannelCommands.cs +++ b/src/EllieBot/Modules/Utility/LiveChannel/LiveChannelCommands.cs @@ -1,4 +1,6 @@ -namespace EllieBot.Modules.Utility.LiveChannel; +using EllieBot.Modules.Utility.LiveChannel; + +namespace EllieBot.Modules.Utility; public partial class Utility { diff --git a/src/EllieBot/Modules/Utility/Scheduled/ScheduledCommands.cs b/src/EllieBot/Modules/Utility/Scheduled/ScheduledCommands.cs index 4bb6f92..0972ad5 100644 --- a/src/EllieBot/Modules/Utility/Scheduled/ScheduledCommands.cs +++ b/src/EllieBot/Modules/Utility/Scheduled/ScheduledCommands.cs @@ -1,6 +1,7 @@ using EllieBot.Common.TypeReaders.Models; +using EllieBot.Modules.Utility.Scheduled; -namespace EllieBot.Modules.Utility.Scheduled; +namespace EllieBot.Modules.Utility; public partial class Utility { diff --git a/src/EllieBot/data/commandlist.json b/src/EllieBot/data/commandlist.json index 01eada3..6eb75ae 100644 --- a/src/EllieBot/data/commandlist.json +++ b/src/EllieBot/data/commandlist.json @@ -4528,61 +4528,6 @@ ] } ], - "LiveChannelCommands": [ - { - "Aliases": [ - ".livechadd", - ".lcha", - ".lchadd" - ], - "Description": "Adds a channel as a live channel with the specified template.\nYou can see a full list of placeholders with `.phs` command.", - "Usage": [ - ".livechadd #general Time: %server.time%", - ".livechadd #general -- %server.members% --" - ], - "Submodule": "LiveChannelCommands", - "Module": "LiveChannelCommands", - "Options": null, - "Requirements": [ - "ManageChannels Server Permission" - ] - }, - { - "Aliases": [ - ".livechlist", - ".lchl", - ".lchli", - ".lchlist" - ], - "Description": "Lists all live channels in the server.", - "Usage": [ - ".livechlist" - ], - "Submodule": "LiveChannelCommands", - "Module": "LiveChannelCommands", - "Options": null, - "Requirements": [ - "ManageChannels Server Permission" - ] - }, - { - "Aliases": [ - ".livechremove", - ".lchd", - ".lchrm" - ], - "Description": "Removes a live channel.", - "Usage": [ - ".livechremove #general" - ], - "Submodule": "LiveChannelCommands", - "Module": "LiveChannelCommands", - "Options": null, - "Requirements": [ - "ManageChannels Server Permission" - ] - } - ], "Marmalade": [ { "Aliases": [ @@ -5836,54 +5781,6 @@ ] } ], - "ScheduledCommands": [ - { - "Aliases": [ - ".schedulelist", - ".schl", - ".schli" - ], - "Description": "Lists your scheduled commands in the current server.", - "Usage": [ - ".schedulelist" - ], - "Submodule": "ScheduledCommands", - "Module": "ScheduledCommands", - "Options": null, - "Requirements": [] - }, - { - "Aliases": [ - ".scheduledelete", - ".schd", - ".schdel" - ], - "Description": "Deletes one of your scheduled commands by its ID.", - "Usage": [ - ".scheduledelete 5" - ], - "Submodule": "ScheduledCommands", - "Module": "ScheduledCommands", - "Options": null, - "Requirements": [] - }, - { - "Aliases": [ - ".scheduleadd", - ".scha", - ".schadd" - ], - "Description": "Schedules a command to be executed after the specified amount of time.\nYou can schedule up to 5 commands at a time.", - "Usage": [ - ".scheduleadd 1h5m .say Hello after 1 hour and 5 minutes", - ".scheduleadd 3h .br all" - ], - "Submodule": "ScheduledCommands", - "Module": "ScheduledCommands", - "Options": null, - "Requirements": [] - } - ], "Searches": [ { "Aliases": [ @@ -7487,6 +7384,59 @@ "ManageChannels Channel Permission" ] }, + { + "Aliases": [ + ".livechadd", + ".lcha", + ".lchadd" + ], + "Description": "Adds a channel as a live channel with the specified template.\nYou can see a full list of placeholders with `.phs` command.", + "Usage": [ + ".livechadd #general Time: %server.time%", + ".livechadd #general -- %server.members% --" + ], + "Submodule": "LiveChannelCommands", + "Module": "Utility", + "Options": null, + "Requirements": [ + "ManageChannels Server Permission" + ] + }, + { + "Aliases": [ + ".livechlist", + ".lchl", + ".lchli", + ".lchlist" + ], + "Description": "Lists all live channels in the server.", + "Usage": [ + ".livechlist" + ], + "Submodule": "LiveChannelCommands", + "Module": "Utility", + "Options": null, + "Requirements": [ + "ManageChannels Server Permission" + ] + }, + { + "Aliases": [ + ".livechremove", + ".lchd", + ".lchrm" + ], + "Description": "Removes a live channel.", + "Usage": [ + ".livechremove #general" + ], + "Submodule": "LiveChannelCommands", + "Module": "Utility", + "Options": null, + "Requirements": [ + "ManageChannels Server Permission" + ] + }, { "Aliases": [ ".quotelist", @@ -7837,6 +7787,52 @@ "ManageMessages Server Permission" ] }, + { + "Aliases": [ + ".schedulelist", + ".schl", + ".schli" + ], + "Description": "Lists your scheduled commands in the current server.", + "Usage": [ + ".schedulelist" + ], + "Submodule": "ScheduledCommands", + "Module": "Utility", + "Options": null, + "Requirements": [] + }, + { + "Aliases": [ + ".scheduledelete", + ".schd", + ".schdel" + ], + "Description": "Deletes one of your scheduled commands by its ID.", + "Usage": [ + ".scheduledelete 5" + ], + "Submodule": "ScheduledCommands", + "Module": "Utility", + "Options": null, + "Requirements": [] + }, + { + "Aliases": [ + ".scheduleadd", + ".scha", + ".schadd" + ], + "Description": "Schedules a command to be executed after the specified amount of time.\nYou can schedule up to 5 commands at a time.", + "Usage": [ + ".scheduleadd 1h5m .say Hello after 1 hour and 5 minutes", + ".scheduleadd 3h .br all" + ], + "Submodule": "ScheduledCommands", + "Module": "Utility", + "Options": null, + "Requirements": [] + }, { "Aliases": [ ".streamrole"