From 2cc32c9002029de8bfb36b83912f503f8786db37 Mon Sep 17 00:00:00 2001 From: Xieon Date: Tue, 3 Oct 2023 21:00:02 -0400 Subject: [PATCH 1/4] Push WIP to WIP branch Working on embed , various discord commands have been adjusted. --- .../Commands/General/HelloModule.cs | 42 +++++++++++- .../Commands/Management/OwnerModule.cs | 65 +++++++++++++++++-- .../Helpers/DiscordTradeNotifier.cs | 35 ++-------- 3 files changed, 104 insertions(+), 38 deletions(-) diff --git a/SysBot.Pokemon.Discord/Commands/General/HelloModule.cs b/SysBot.Pokemon.Discord/Commands/General/HelloModule.cs index bd6dbd9..31e485b 100644 --- a/SysBot.Pokemon.Discord/Commands/General/HelloModule.cs +++ b/SysBot.Pokemon.Discord/Commands/General/HelloModule.cs @@ -1,5 +1,8 @@ -using Discord.Commands; +using Discord; +using Discord.Commands; +using System.Linq; // Include the System.Linq namespace. using System.Threading.Tasks; +using System.IO; //Weed need System.IO to r/w local system files such as "rules.txt" namespace SysBot.Pokemon.Discord { @@ -14,5 +17,40 @@ public async Task PingAsync() var msg = string.Format(str, Context.User.Mention); await ReplyAsync(msg).ConfigureAwait(false); } - } + + + + [Command("rules")] + [Summary("Get the server rules.")] + public async Task RulesAsync() + { + string folderPath = "variables"; + string rulesFilePath = Path.Combine(folderPath, "rules.txt"); + + // Ensure the folder exists, create it if it doesn't. + if (!Directory.Exists(folderPath)) + { + Directory.CreateDirectory(folderPath); + } + + if (!File.Exists(rulesFilePath)) + { + // If the file doesn't exist, create it with the specified content. + File.WriteAllText(rulesFilePath, "Rules File not Updated Yet"); + } + + string rulesContent = File.ReadAllText(rulesFilePath); + + var embed = new EmbedBuilder + { + Title = "Server Rules", + Description = rulesContent, + Color = new Color(0, 255, 0), // Green success commmand embed - + }; + + await ReplyAsync(embed: embed.Build()); + } + + + } } \ No newline at end of file diff --git a/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs b/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs index c0f31e3..8c8dac8 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs @@ -4,13 +4,20 @@ using System.Threading.Tasks; using Discord; +//I'm going to be using a lot of libraries and subliraries that we not initially used in the original project source code - +//These will be required to use parts of my code +using Discord.WebSocket; // We need this subclass to be able to attach deleted Pk9 files and restore them. +using Discord.Net; // This is to handle deleted message exceptions +using System.Net; // We need this to catch exceptions for deleted messages + + namespace SysBot.Pokemon.Discord { public class OwnerModule : SudoModule { [Command("addSudo")] [Summary("Adds mentioned user to global sudo")] - [RequireOwner] + [RequireSudo] // ReSharper disable once UnusedParameter.Global public async Task SudoUsers([Remainder] string _) { @@ -22,19 +29,23 @@ public async Task SudoUsers([Remainder] string _) [Command("removeSudo")] [Summary("Removes mentioned user from global sudo")] - [RequireOwner] + [RequireSudo] // ReSharper disable once UnusedParameter.Global public async Task RemoveSudoUsers([Remainder] string _) { + /* + // We commented this out to prevent the wrong user getting sudo, and removing other sudo users before someone can execute the kill command var users = Context.Message.MentionedUsers; var objects = users.Select(GetReference); SysCordSettings.Settings.GlobalSudoList.RemoveAll(z => objects.Any(o => o.ID == z.ID)); await ReplyAsync("Done.").ConfigureAwait(false); + */ + await ReplyAsync("Sudo must be removed in person from console currently").ConfigureAwait(false); } [Command("addChannel")] [Summary("Adds a channel to the list of channels that are accepting commands.")] - [RequireOwner] + [RequireSudo] // Changed this to require sudo perms instead of owner // ReSharper disable once UnusedParameter.Global public async Task AddChannel() { @@ -43,9 +54,53 @@ public async Task AddChannel() await ReplyAsync("Done.").ConfigureAwait(false); } + /* + This ccommand isn't complete yet - + */ + [Command("undelete")] + [Summary("Undeletes a specific message by ID.")] + [RequireSudo] + public async Task UndeleteMessageAsync(ulong messageId) + { + // Attempt to get the message by its ID using the Channel. + var channel = Context.Channel as ITextChannel; + + if (channel != null) + { + var message = await channel.GetMessageAsync(messageId).ConfigureAwait(false); + + if (message != null) + { + // Assuming you want to post the undeleted message with author and attachments as files if they exist. + var undeleteMessage = $"{Context.User.Mention} Restoring Deleted message by {message.Author} : {message.Content}"; + + if (message.Attachments.Any()) + { + var attachments = message.Attachments.Select(a => a.Url); + undeleteMessage += $"\nAttachments:\n{string.Join("\n", attachments)}"; + } + + await channel.SendMessageAsync(undeleteMessage).ConfigureAwait(false); + } + + else + { + await ReplyAsync("The specified message does not exist or is not accessible.").ConfigureAwait(false); + } + } + + else + { + await ReplyAsync("This command can only be used in a text channel.").ConfigureAwait(false); + } +} + + + + [Command("removeChannel")] [Summary("Removes a channel from the list of channels that are accepting commands.")] - [RequireOwner] + [RequireSudo] // Changed to allow sudo to execut // ReSharper disable once UnusedParameter.Global public async Task RemoveChannel() { @@ -105,7 +160,7 @@ public async Task LeaveAll() [Command("sudoku")] [Alias("kill", "shutdown")] [Summary("Causes the entire process to end itself!")] - [RequireOwner] + [RequireSudo] // ReSharper disable once UnusedParameter.Global public async Task ExitProgram() { diff --git a/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs b/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs index 529f1be..31e4f62 100644 --- a/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs +++ b/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs @@ -134,39 +134,12 @@ public async void TradeFinished(PokeRoutineExecutor routine, PokeTradeDetail< // Define a dictionary to map integer values to emote strings // not used currently string? ballEmote = null; // Declare ballEmote outside of the if statement - string? ballEmbed = null; - string? noball = null; + // string? ballEmbed = null; + // string? noball = null; /* Dictionary ballEmotes = new() - { - { 1, ":ball_Master:" }, - { 2, ":ball_Ultra:" }, - { 3, ":ball_Great:" }, - { 4, ":ball_Poke:" }, - { 5, ":ball_safari:" }, - { 6, ":ball_net:" }, - { 7, ":ball_dive:" }, - { 8, ":ball_nest:" }, - { 9, ":ball_repeat:" }, - { 10, ":ball_timer:" }, - { 11, ":ball_luxury:" }, - { 12, ":ball_pre:" }, - { 13, ":ball_dusk:" }, - { 14, ":ball_heal:" }, - { 15, ":ball_quick:" }, - { 16, ":ball_cherish:" }, - { 17, ":ball_fast:" }, - { 18, ":ball_level:" }, - { 19, ":ball_lure:" }, - { 20, ":ball_heavy:" }, - { 21, ":ball_love:" }, - { 22, ":ball_friend:" }, - { 23, ":ball_love:" }, - { 24, ":ball_sport:" }, - { 25, ":ball_dream:" }, - { 27, ":ball_strange:" }, - }; + @@ -234,7 +207,7 @@ public async void TradeFinished(PokeRoutineExecutor routine, PokeTradeDetail< embed.AddField("Trainer IG Info", $"OT: {ot} / TID: {tid}",true); embed.AddField("IV Spread", $"{stats}", true); embed.AddField("MOVES #'s", $"{m1}\n{m2}\n{m3}\n{m4}",true); - embed.AddField("Move List" , moveList); // New line Added to the Embed + embed.AddField("Move List" , moveList, true); // New line Added to the Embed embed.AddField("Breloom?", $"Breloom override is off, if it was on would you have gotten Breloom instead?{breloom}"); // var mblink = $"data:image/jpeg;base64,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"; From 2ab699963cfa02b3d85ef7043d5cb16b796f12ba Mon Sep 17 00:00:00 2001 From: Xieon Date: Wed, 4 Oct 2023 16:00:11 -0400 Subject: [PATCH 2/4] Add the pokemon picture database than you to Lilly, Rich, and Kosh for helping compile --- .gitignore | 6 ++++ .../Commands/Management/SudoModule.cs | 36 ++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dfcfd56..bb85eda 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,10 @@ bld/ [Ll]og/ [Ll]ogs/ +# Since this version of the bot does not creat a stable single .exe compiled build we must include the pkmnpics database +!/[Bb]in/x64/Debug/net7.0-windows/pkmnpics/ + + # Visual Studio 2015/2017 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot @@ -56,6 +60,8 @@ dlldata.c # Benchmark Results BenchmarkDotNet.Artifacts/ + + # .NET Core project.lock.json project.fragment.lock.json diff --git a/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs b/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs index c77e83c..6a0af7a 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs @@ -1,9 +1,14 @@ -using Discord.Commands; +// System Libraries being used using System; +using System.IO; // added systtem.io for file manipulation using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; + +//Discord Libraries using Discord; +using Discord.Commands; +// using Discord.Net; //commented out until we use it, which eventually we weill. namespace SysBot.Pokemon.Discord { @@ -72,6 +77,35 @@ public async Task UnBlackListIDs([Summary("Comma Separated Discord IDs")][Remain await ReplyAsync("Done.").ConfigureAwait(false); } + +[Command("owner")] +[RequireSudo] // Use RequireSudo attribute +public async Task YourCommandAsync() +{ + ulong userId = Context.User.Id; + + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + + if (ownerIds.Contains(userId.ToString())) + { + // You can execute the command logic here for owners + await ReplyAsync("You are the owner. You can execute this command."); + } + else + { + // Provide a message for sudo users who are not owners + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); + } +} + + + + + [Command("blacklistSummary")] [Alias("printBlacklist", "blacklistPrint")] [Summary("Prints the list of blacklisted users.")] From 99bfb21d3d03c47af3f70a62e2f776b48ba3a22c Mon Sep 17 00:00:00 2001 From: Xieon Date: Wed, 4 Oct 2023 19:40:38 -0400 Subject: [PATCH 3/4] Push WIP updates to owner and sudo classses --- .../Commands/Management/OwnerModule.cs | 100 ++++++++++++++---- .../Commands/Management/SudoModule.cs | 4 +- 2 files changed, 82 insertions(+), 22 deletions(-) diff --git a/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs b/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs index 8c8dac8..288e125 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs @@ -1,15 +1,16 @@ -using Discord.Commands; +//Organized into System Libraries and sub Libraries, and Discord using System; using System.Linq; +using System.IO; //we need this for local file manipulation using System.Threading.Tasks; -using Discord; //I'm going to be using a lot of libraries and subliraries that we not initially used in the original project source code - //These will be required to use parts of my code using Discord.WebSocket; // We need this subclass to be able to attach deleted Pk9 files and restore them. using Discord.Net; // This is to handle deleted message exceptions using System.Net; // We need this to catch exceptions for deleted messages - +using Discord.Commands; +using Discord; namespace SysBot.Pokemon.Discord { @@ -21,6 +22,7 @@ public class OwnerModule : SudoModule // ReSharper disable once UnusedParameter.Global public async Task SudoUsers([Remainder] string _) { + var users = Context.Message.MentionedUsers; var objects = users.Select(GetReference); SysCordSettings.Settings.GlobalSudoList.AddIfNew(objects); @@ -54,9 +56,7 @@ public async Task AddChannel() await ReplyAsync("Done.").ConfigureAwait(false); } - /* - This ccommand isn't complete yet - - */ + //This ccommand isn't complete yet - [Command("undelete")] [Summary("Undeletes a specific message by ID.")] [RequireSudo] @@ -95,9 +95,6 @@ public async Task UndeleteMessageAsync(ulong messageId) } } - - - [Command("removeChannel")] [Summary("Removes a channel from the list of channels that are accepting commands.")] [RequireSudo] // Changed to allow sudo to execut @@ -109,24 +106,47 @@ public async Task RemoveChannel() await ReplyAsync("Done.").ConfigureAwait(false); } + + //Command edited to include double verification check - if user has sudo, and is in owner list [Command("leave")] [Alias("bye")] [Summary("Leaves the current server.")] - [RequireOwner] + [RequireSudo] // ReSharper disable once UnusedParameter.Global public async Task Leave() { - await ReplyAsync("Goodbye.").ConfigureAwait(false); - await Context.Guild.LeaveAsync().ConfigureAwait(false); + ulong userId = Context.User.Id; + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + if (ownerIds.Contains(userId.ToString())) + { + await ReplyAsync($"Goodbye - Exiting the Guild <@{userId}>").ConfigureAwait(false); + await Context.Guild.LeaveAsync().ConfigureAwait(false); + } + else + { + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); + } } - [Command("leaveguild")] + // Changed to Sudo from Owner, and require Sudo and id match in parameter.tct to execute. + [Command("leaveguild")] [Alias("lg")] [Summary("Leaves guild based on supplied ID.")] - [RequireOwner] + [RequireSudo] //changed to require sudo and match id in parameters/owner // ReSharper disable once UnusedParameter.Global public async Task LeaveGuild(string userInput) { + + ulong userId = Context.User.Id; + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + if (ownerIds.Contains(userId.ToString())) + { if (!ulong.TryParse(userInput, out ulong id)) { await ReplyAsync("Please provide a valid Guild ID.").ConfigureAwait(false); @@ -142,21 +162,48 @@ public async Task LeaveGuild(string userInput) await ReplyAsync($"Leaving {guild}.").ConfigureAwait(false); await guild.LeaveAsync().ConfigureAwait(false); + } + else + { + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); + } + + + + } + // Changed to invlude double verification method [Command("leaveall")] [Summary("Leaves all servers the bot is currently in.")] - [RequireOwner] + [RequireSudo] // ReSharper disable once UnusedParameter.Global public async Task LeaveAll() { - await ReplyAsync("Leaving all servers.").ConfigureAwait(false); - foreach (var guild in Context.Client.Guilds) + + ulong userId = Context.User.Id; + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + if (ownerIds.Contains(userId.ToString())) + { + await ReplyAsync("You are the owner. You can execute this command."); + await ReplyAsync("Leaving all servers.").ConfigureAwait(false); + foreach (var guild in Context.Client.Guilds) + { + await guild.LeaveAsync().ConfigureAwait(false); + } + } + else { - await guild.LeaveAsync().ConfigureAwait(false); + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); } + + } + // Changed to Sudo + List verification method [Command("sudoku")] [Alias("kill", "shutdown")] [Summary("Causes the entire process to end itself!")] @@ -164,8 +211,21 @@ public async Task LeaveAll() // ReSharper disable once UnusedParameter.Global public async Task ExitProgram() { - await Context.Channel.EchoAndReply("Shutting down... goodbye! **Bot services are going offline.**").ConfigureAwait(false); - Environment.Exit(0); + ulong userId = Context.User.Id; + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + if (ownerIds.Contains(userId.ToString())) + { + await ReplyAsync("You are the owner. You can execute this command."); + await Context.Channel.EchoAndReply("Shutting down... goodbye! **Bot services are going offline.**").ConfigureAwait(false); + Environment.Exit(0); + } + else + { + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); + } } private RemoteControlAccess GetReference(IUser channel) => new() diff --git a/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs b/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs index 6a0af7a..3f4d7c7 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs @@ -78,9 +78,9 @@ public async Task UnBlackListIDs([Summary("Comma Separated Discord IDs")][Remain } -[Command("owner")] +[Command("permcheck")] [RequireSudo] // Use RequireSudo attribute -public async Task YourCommandAsync() +public async Task PermCheck() { ulong userId = Context.User.Id; From 9e15bc2a1fddc83946413897b0497a2d91d53d36 Mon Sep 17 00:00:00 2001 From: Xieon Date: Wed, 11 Oct 2023 20:55:02 -0400 Subject: [PATCH 4/4] Updates to Owner method implementation Testing latest random changes most to embed and owner module implementation, code will be cleaned up later --- .../Commands/Management/OwnerModule.cs | 88 +++++++++----- .../Commands/Management/PoolModule.cs | 115 ++++++++++++++---- .../Commands/Management/SudoModule.cs | 58 +++++---- .../Helpers/DiscordTradeNotifier.cs | 37 +++--- 4 files changed, 198 insertions(+), 100 deletions(-) diff --git a/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs b/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs index 288e125..fdcc934 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/OwnerModule.cs @@ -5,29 +5,57 @@ using System.Threading.Tasks; //I'm going to be using a lot of libraries and subliraries that we not initially used in the original project source code - -//These will be required to use parts of my code -using Discord.WebSocket; // We need this subclass to be able to attach deleted Pk9 files and restore them. +//These will be required to use parts of my codeusing Discord.WebSocket; // We need this subclass to be able to attach deleted Pk9 files and restore them. using Discord.Net; // This is to handle deleted message exceptions using System.Net; // We need this to catch exceptions for deleted messages using Discord.Commands; using Discord; +using System.Collections.Generic; namespace SysBot.Pokemon.Discord { public class OwnerModule : SudoModule { + + private List ownerIds; // Declare a field to store the loaded owner IDs + + [Command("addSudo")] [Summary("Adds mentioned user to global sudo")] [RequireSudo] // ReSharper disable once UnusedParameter.Global public async Task SudoUsers([Remainder] string _) { - + ownerIds = LoadOwnerIdsFromFile(); + var users = Context.Message.MentionedUsers; var objects = users.Select(GetReference); SysCordSettings.Settings.GlobalSudoList.AddIfNew(objects); await ReplyAsync("Done.").ConfigureAwait(false); } + + private List LoadOwnerIdsFromFile() + { + // Define the path to your owners.txt file + string ownersFilePath = Path.Combine("parameters", "owners.txt"); + + if (File.Exists(ownersFilePath)) + { + // Read the file and split it by commas to get a list of owner IDs + string[] ownerIdsStr = File.ReadAllText(ownersFilePath).Split(','); + // Convert the strings to ulong and return the list of owner IDs + List ownerIds = ownerIdsStr.Select(str => ulong.Parse(str.Trim())).ToList(); + return ownerIds; + } + else + { + // If the file doesn't exist, create it and make it empty + File.WriteAllText(ownersFilePath, string.Empty); + + // Return an empty list since there are no owner IDs yet + return new List();; + } +} [Command("removeSudo")] [Summary("Removes mentioned user from global sudo")] @@ -35,16 +63,27 @@ public async Task SudoUsers([Remainder] string _) // ReSharper disable once UnusedParameter.Global public async Task RemoveSudoUsers([Remainder] string _) { - /* - // We commented this out to prevent the wrong user getting sudo, and removing other sudo users before someone can execute the kill command - var users = Context.Message.MentionedUsers; - var objects = users.Select(GetReference); - SysCordSettings.Settings.GlobalSudoList.RemoveAll(z => objects.Any(o => o.ID == z.ID)); - await ReplyAsync("Done.").ConfigureAwait(false); - */ - await ReplyAsync("Sudo must be removed in person from console currently").ConfigureAwait(false); + + ulong userId = Context.User.Id; + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + if (ownerIds.Contains(userId.ToString())) + { + var users = Context.Message.MentionedUsers; + var objects = users.Select(GetReference); + SysCordSettings.Settings.GlobalSudoList.RemoveAll(z => objects.Any(o => o.ID == z.ID)); + await ReplyAsync("Done -Owner Removed Sudo from User ").ConfigureAwait(false); + } + else + { + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); + } } + + // Sudo required [Command("addChannel")] [Summary("Adds a channel to the list of channels that are accepting commands.")] [RequireSudo] // Changed this to require sudo perms instead of owner @@ -56,7 +95,7 @@ public async Task AddChannel() await ReplyAsync("Done.").ConfigureAwait(false); } - //This ccommand isn't complete yet - + //This ccommand isn't complete yet - Sudo command only currently [Command("undelete")] [Summary("Undeletes a specific message by ID.")] [RequireSudo] @@ -95,19 +134,7 @@ public async Task UndeleteMessageAsync(ulong messageId) } } - [Command("removeChannel")] - [Summary("Removes a channel from the list of channels that are accepting commands.")] - [RequireSudo] // Changed to allow sudo to execut - // ReSharper disable once UnusedParameter.Global - public async Task RemoveChannel() - { - var obj = GetReference(Context.Message.Channel); - SysCordSettings.Settings.ChannelWhitelist.RemoveAll(z => z.ID == obj.ID); - await ReplyAsync("Done.").ConfigureAwait(false); - } - - - //Command edited to include double verification check - if user has sudo, and is in owner list + // Sudo + Owners.txt Verification method implemented [Command("leave")] [Alias("bye")] [Summary("Leaves the current server.")] @@ -131,11 +158,12 @@ public async Task Leave() } } - // Changed to Sudo from Owner, and require Sudo and id match in parameter.tct to execute. + // Sudo + Owners.txt Verification method implemented [Command("leaveguild")] [Alias("lg")] [Summary("Leaves guild based on supplied ID.")] - [RequireSudo] //changed to require sudo and match id in parameters/owner + [RequireSudo] + //changed to require sudo and match id in parameters/owner // ReSharper disable once UnusedParameter.Global public async Task LeaveGuild(string userInput) { @@ -173,11 +201,11 @@ public async Task LeaveGuild(string userInput) } - // Changed to invlude double verification method + // Sudo + Owners.txt Verification method implemented [Command("leaveall")] [Summary("Leaves all servers the bot is currently in.")] [RequireSudo] - // ReSharper disable once UnusedParameter.Global + // ReSharper disable once UnusedParameter.Globa public async Task LeaveAll() { @@ -203,7 +231,7 @@ public async Task LeaveAll() } - // Changed to Sudo + List verification method + // Sudo + Owners.txt Verification method implemented [Command("sudoku")] [Alias("kill", "shutdown")] [Summary("Causes the entire process to end itself!")] diff --git a/SysBot.Pokemon.Discord/Commands/Management/PoolModule.cs b/SysBot.Pokemon.Discord/Commands/Management/PoolModule.cs index 86959c5..dd12554 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/PoolModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/PoolModule.cs @@ -1,14 +1,20 @@ using Discord; using Discord.Commands; using PKHeX.Core; +using System; +using System.IO; using System.Linq; -using System.Threading.Tasks; +using System.Text; // Used for creating combined Stringe. +using System.Threading.Tasks; namespace SysBot.Pokemon.Discord { [Summary("Distribution Pool Module")] public class PoolModule : ModuleBase where T : PKM, new() { + private object msg; + private object options; + [Command("poolReload")] [Summary("Reloads the bot pool from the setting's folder.")] [RequireSudo] @@ -24,32 +30,93 @@ public async Task ReloadPoolAsync() await ReplyAsync($"Reloaded from folder. Pool count: {hub.Ledy.Pool.Count}").ConfigureAwait(false); } - [Command("pool")] - [Summary("Displays the details of Pokémon files in the random pool.")] - public async Task DisplayPoolCountAsync() - { - var me = SysCord.Runner; - var hub = me.Hub; - var pool = hub.Ledy.Pool; - var count = pool.Count; - if (count is > 0 and < 20) + //New command for displaying the pool. + [Command("pool")] + [Summary("Displays the details of Pokémon in the random pool.")] + public async Task DisplayPoolCountAsync() { - var lines = pool.Files.Select((z, i) => $"{i + 1:00}: {z.Key} = {(Species)z.Value.RequestInfo.Species}"); - var msg = string.Join("\n", lines); - - var embed = new EmbedBuilder(); - embed.AddField(x => + var me = SysCord.Runner; + var hub = me.Hub; + var pool = hub.Ledy.Pool; + var count = pool.Count; + + if (count > 0) { - x.Name = $"Count: {count}"; - x.Value = msg; - x.IsInline = false; - }); - await ReplyAsync("Pool Details", embed: embed.Build()).ConfigureAwait(false); - } - else - { - await ReplyAsync($"Pool Count: {count}").ConfigureAwait(false); + var total = count; + + // Initialize a counter to keep track of displayed Pokémon. + var displayedPokémon = 0; + + var embed = new EmbedBuilder(); + var pokémonInformation = new StringBuilder(); + + while (count > 0 && displayedPokémon < 10) // Continue until 20 Pokémon are displayed. + { + var lines = pool.Files.Select((z, i) => $"{i + 1:00}: {z.Key} = {(Species)z.Value.RequestInfo.Species}"); + var msg = string.Join("\n", lines); + + pokémonInformation.AppendLine($"Count: {count}"); + pokémonInformation.AppendLine(msg); + + count--; + displayedPokémon++; // Increment the counter. + } + + embed.AddField("Total Pokémon in Pool", total, true); + embed.AddField("Pokémon Information", pokémonInformation.ToString(), false); + + await ReplyAsync("Pool Details", embed: embed.Build()).ConfigureAwait(false); + } + else + { + await ReplyAsync($"Pool Count: {count}").ConfigureAwait(false); + } } + + [Command("poolpic")] + [Summary("Displays the first 10 Pokémon images in the pool.")] + public async Task DisplayPoolPicturesAsync(params string[] pokemonNames) + { + var me = SysCord.Runner; + var hub = me.Hub; + _ = hub.Ledy.Pool; + + var embed = new EmbedBuilder(); + embed.Title = "Pool Pictures"; + + var displayedPokémon = 0; + + foreach (var pokemonName in pokemonNames) + { + if (displayedPokémon >= 10) + { + break; // Limit to 10 thumbnails. + } + + var imagePath = $".\\pkmnpic\\{pokemonName}.png"; // Adjust the path as needed. + + if (File.Exists(imagePath)) + { + var thumbnailUrl = $"attachment://{pokemonName}.png"; + var imageStream = new FileStream(imagePath, FileMode.Open, FileAccess.Read); + embed.AddField($"The First 10 Pokemon in the XGC Current Distro",$"The first 10 Pokemon", true); + // Add the Pokémon name as a field. + embed.AddField("Pokémon", pokemonName); + + // Set the thumbnail for the embed. + embed.WithThumbnailUrl(thumbnailUrl); + + displayedPokémon++; // Increment the counter. + } + } + + await ReplyAsync(embed: embed.Build()); + } + + + private Task ReplyAsync(Embed embed, bool isTTS, object options, bool isEphemeral, object allowedMentions, object value) + { + throw new NotImplementedException(); } } } \ No newline at end of file diff --git a/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs b/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs index 3f4d7c7..478c58c 100644 --- a/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs +++ b/SysBot.Pokemon.Discord/Commands/Management/SudoModule.cs @@ -8,7 +8,7 @@ //Discord Libraries using Discord; using Discord.Commands; -// using Discord.Net; //commented out until we use it, which eventually we weill. +using Discord.Net; //commented out until we use it, which eventually we weill. namespace SysBot.Pokemon.Discord { @@ -77,33 +77,39 @@ public async Task UnBlackListIDs([Summary("Comma Separated Discord IDs")][Remain await ReplyAsync("Done.").ConfigureAwait(false); } - -[Command("permcheck")] -[RequireSudo] // Use RequireSudo attribute -public async Task PermCheck() -{ - ulong userId = Context.User.Id; - - // Read the contents of owners.txt - string ownersFileContent = File.ReadAllText("parameters/owners.txt"); - - // Split the content by commas to get an array of owner Discord IDs - string[] ownerIds = ownersFileContent.Split(','); - - if (ownerIds.Contains(userId.ToString())) - { - // You can execute the command logic here for owners - await ReplyAsync("You are the owner. You can execute this command."); - } - else - { - // Provide a message for sudo users who are not owners - await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); - } -} - + [Command("permcheck")] + [RequireSudo] // Use RequireSudo attribute + public async Task PermCheck() + { + ulong userId = Context.User.Id; + // Read the contents of owners.txt + string ownersFileContent = File.ReadAllText("parameters/owners.txt"); + // Split the content by commas to get an array of owner Discord IDs + string[] ownerIds = ownersFileContent.Split(','); + if (ownerIds.Contains(userId.ToString())) + { + // You can execute the command logic here for owners + await ReplyAsync("You are the owner. You can execute this command."); + } + else + { + // Provide a message for sudo users who are not owners + await ReplyAsync("You are a sudo user, but not the owner. You cannot execute this command."); + } + } + // Sudo Verification required only + [Command("removeChannel")] + [Summary("Removes a channel from the list of channels that are accepting commands.")] + [RequireSudo] // Changed to allow sudo to execute + // ReSharper disable once UnusedParameter.Global + public async Task RemoveChannel() + { + var obj = GetReference((IUser)Context.Message.Channel); + SysCordSettings.Settings.ChannelWhitelist.RemoveAll(z => z.ID == obj.ID); + await ReplyAsync("Done.").ConfigureAwait(false); + } [Command("blacklistSummary")] diff --git a/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs b/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs index 31e4f62..a77517f 100644 --- a/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs +++ b/SysBot.Pokemon.Discord/Helpers/DiscordTradeNotifier.cs @@ -89,6 +89,8 @@ public async void TradeFinished(PokeRoutineExecutor routine, PokeTradeDetail< ////////////////////////////////////////////////////////////// //BEGINNING OF THE FULL EMBED CODE ADDED TO DISCORDTRADENOTIFIER.CS + + // Define the path to the folder containing PNG files var folderPath = @"C:\Users\Xieon\Desktop\repositories\test\SysBot.PokemonScarletViolet\SysBot.Pokemon.WinForms\bin\x64\Debug\net7.0-windows\pkmnpic"; // Create the full path to the PNG file based on {(Species)tradedToUser} @@ -163,23 +165,21 @@ public async void TradeFinished(PokeRoutineExecutor routine, PokeTradeDetail< */ -/* - // Establish Variables that are set to the different Data.(Field) variables - - var item = Data.HeldItem; - var holding = ""; - - // + // Held Item Code Block + string holding = $""; + var item = Data.HeldItem; if(item < 0) { - holding = "No item"; + holding = "Pokemon not holding an item"; } else { - holding = $"Holding Item # {Data.HeldItem}"; + //holding = Data.Name.HeldItem; + + holding = $"Pokemong is holding {item} "; } -*/ - string holding = $""; + + var ability = Data.Ability; var ot = Data.OT_Name; // The IGN of the trainer who requested a trade. var tid = Data.DisplayTID; //The TID as it appears in game. var stats = $"ATK:{atk} / DEF:{def} / SpD:{spd} / SpA:{spa} / Spe:{spe} / HP:{hp}"; //build the stats straings @@ -195,23 +195,18 @@ public async void TradeFinished(PokeRoutineExecutor routine, PokeTradeDetail< var embed = new EmbedBuilder(); var colon = $":"; var dream = $"ball_dream"; - var displaytest = $"{colon}{dream}{colon}"; + _ = $"{colon}{dream}{colon}"; - //// Test Code for the Moves. - var moveList = Data.Moves.ToList; + //// Test Code for the Moves. + var moveList = Data.Moves.ToList; embed.WithTitle("XGC MEMBER TRADE REQUEST COMPLETED"); embed.AddField("Trainer", Trader.Mention, true); // Display trainer's name in an inline field embed.AddField("Received Pokémon", $"{shiny}{(Species)tradedToUser} {holding}", true); // Display received Pokémon with or without shiny indicator embed.AddField("Trainer IG Info", $"OT: {ot} / TID: {tid}",true); embed.AddField("IV Spread", $"{stats}", true); - embed.AddField("MOVES #'s", $"{m1}\n{m2}\n{m3}\n{m4}",true); - embed.AddField("Move List" , moveList, true); // New line Added to the Embed - embed.AddField("Breloom?", $"Breloom override is off, if it was on would you have gotten Breloom instead?{breloom}"); - - // var mblink = $"data:image/jpeg;base64,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"; - + embed.AddField("Ability:",$"{ability}", true); //If the ball requested is in XGC Server - how do we display it as an image in the embed? /* @@ -252,6 +247,8 @@ public async void TradeFinished(PokeRoutineExecutor routine, PokeTradeDetail< embed.AddField("Received Pokémon", $"{(Species)tradedToUser}", true); // Display received Pokémon embed.AddField("Trainer Info",$"OT:{ot} / TID:{tid}"); embed.AddField("IV Spread",$"{stats}",true); + embed.AddField("Missing Image",$"Note to Staff {(Species)tradedToUser} is missing an image", true); // let staff know that there's a missing database image. + embed.AddField("Ability:",$"{ability}", true); //embed.AddField("Ball",$"{ballemote}",true); embed.AddField("Thanks for being a member", ":heart:"); // Display a heart thanking the user for using the bot await CommandSentChannel.SendMessageAsync(embed: embed.Build()).ConfigureAwait(false); // Send the embed in the same channel where the command was sent