diff --git a/DisCatSharp.ApplicationCommands/Checks/ApplicationCommandEqualityChecks.cs b/DisCatSharp.ApplicationCommands/Checks/ApplicationCommandEqualityChecks.cs
index 61b0b12dc..d7e3dff46 100644
--- a/DisCatSharp.ApplicationCommands/Checks/ApplicationCommandEqualityChecks.cs
+++ b/DisCatSharp.ApplicationCommands/Checks/ApplicationCommandEqualityChecks.cs
@@ -1,312 +1,319 @@
// This file is part of the DisCatSharp project, based off DSharpPlus.
//
// Copyright (c) 2021-2022 AITSYS
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System;
using System.Collections.Generic;
using System.Linq;
using DisCatSharp.Entities;
using DisCatSharp.Enums;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace DisCatSharp.ApplicationCommands.Checks;
internal static class ApplicationCommandEqualityChecks
{
///
/// Whether two application commands are equal.
///
/// Source command.
/// Command to check against.
/// The discord client.
- internal static bool IsEqualTo(this DiscordApplicationCommand ac1, DiscordApplicationCommand targetApplicationCommand, DiscordClient client)
+ /// Whether the equal check is performed for a guild command.
+ internal static bool IsEqualTo(this DiscordApplicationCommand ac1, DiscordApplicationCommand targetApplicationCommand, DiscordClient client, bool IsGuild)
{
if (targetApplicationCommand is null || ac1 is null)
return false;
DiscordApplicationCommand sourceApplicationCommand = new(
ac1.Name, ac1.Description, ac1.Options,
ac1.Type,
ac1.NameLocalizations, ac1.DescriptionLocalizations,
ac1.DefaultMemberPermissions, ac1.DmPermission ?? true//, ac1.IsNsfw
);
+ if (IsGuild)
+ {
+ sourceApplicationCommand.DmPermission = true;
+ targetApplicationCommand.DmPermission = true;
+ }
+
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, "[AC Change Check] Command {name}\n\n[{jsonOne},{jsontwo}]\n\n", ac1.Name, JsonConvert.SerializeObject(sourceApplicationCommand), JsonConvert.SerializeObject(targetApplicationCommand));
return ac1.Type == targetApplicationCommand.Type && sourceApplicationCommand.SoftEqual(targetApplicationCommand, ac1.Type, ApplicationCommandsExtension.Configuration?.EnableLocalization ?? false);
}
///
/// Checks softly whether two s are the same.
/// Excluding id, application id and version here.
///
/// Source application command.
/// Application command to check against.
/// The application command type.
/// Whether localization is enabled.
internal static bool SoftEqual(this DiscordApplicationCommand source, DiscordApplicationCommand target, ApplicationCommandType type, bool localizationEnabled = false)
{
var sDmPerm = source.DmPermission ?? true;
var tDmPerm = target.DmPermission ?? true;
return localizationEnabled
? type switch
{
ApplicationCommandType.ChatInput => DeepEqual(source, target, true, sDmPerm, tDmPerm),
_ => source.Name == target.Name
&& source.Type == target.Type && source.NameLocalizations == target.NameLocalizations
&& source.DefaultMemberPermissions == target.DefaultMemberPermissions
&& sDmPerm == tDmPerm
//&& (source.IsNsfw == target.IsNsfw)
}
: type switch
{
ApplicationCommandType.ChatInput => DeepEqual(source, target, false, sDmPerm, tDmPerm),
_ => source.Name == target.Name
&& source.Type == target.Type
&& source.DefaultMemberPermissions == target.DefaultMemberPermissions
&& sDmPerm == tDmPerm
//&& (source.IsNsfw == target.IsNsfw)
};
}
///
/// Checks deeply whether two s are the same.
/// Excluding id, application id and version here.
///
/// Source application command.
/// Application command to check against.
/// Whether localization is enabled.
/// The source dm permission.
/// The target dm permission.
internal static bool DeepEqual(DiscordApplicationCommand source, DiscordApplicationCommand target, bool localizationEnabled = false, bool sDmPerm = true, bool tDmPerm = true)
{
var rootCheck = true;
/*//Console.WriteLine($"{source.Name == target.Name}");
//Console.WriteLine($"{source.Description == target.Description}");
//Console.WriteLine($"{source.Type == target.Type}");
//Console.WriteLine($"{source.DefaultMemberPermissions == target.DefaultMemberPermissions}");
//Console.WriteLine($"{sDmPerm == tDmPerm}");*/
rootCheck = source.Name == target.Name && source.Description == target.Description && source.Type == target.Type && source.DefaultMemberPermissions == target.DefaultMemberPermissions && sDmPerm == tDmPerm;
if (localizationEnabled)
rootCheck = rootCheck && source.NameLocalizations == target.NameLocalizations && source.DescriptionLocalizations == target.DescriptionLocalizations;
////Console.WriteLine($"{rootCheck}");
if (source.Options == null && target.Options == null)
return rootCheck;
else if ((source.Options != null && target.Options == null) || (source.Options == null && target.Options != null))
return false;
else if (source.Options.Any(o => o.Type == ApplicationCommandOptionType.SubCommandGroup) && target.Options.Any(o => o.Type == ApplicationCommandOptionType.SubCommandGroup))
{
List minimalSourceOptions = new();
List minimalTargetOptions = new();
foreach (var option in source.Options)
{
List minimalSubSourceOptions = new();
foreach (var subOption in option.Options)
{
List minimalSubSubSourceOptions = null;
if (subOption.Options != null)
{
minimalSubSubSourceOptions = new();
foreach (var subSubOption in subOption.Options)
minimalSubSubSourceOptions.Add(new DiscordApplicationCommandOption(
subSubOption.Name, subSubOption.Description, subSubOption.Type, subSubOption.Required,
subSubOption.Choices, null, subSubOption.ChannelTypes, subSubOption.AutoComplete,
subSubOption.MinimumValue, subSubOption.MaximumValue,
localizationEnabled ? subSubOption.NameLocalizations : null,
localizationEnabled ? subSubOption.DescriptionLocalizations : null,
subSubOption.MinimumLength, subSubOption.MaximumLength
));
minimalSubSourceOptions.Add(new DiscordApplicationCommandOption(
subOption.Name, subOption.Description, subOption.Type,
options: minimalSubSubSourceOptions,
nameLocalizations: localizationEnabled ? subOption.NameLocalizations : null,
descriptionLocalizations: localizationEnabled ? subOption.DescriptionLocalizations : null
));
}
}
minimalSourceOptions.Add(new DiscordApplicationCommandOption(
option.Name, option.Description, option.Type,
options: minimalSubSourceOptions,
nameLocalizations: localizationEnabled ? option.NameLocalizations : null,
descriptionLocalizations: localizationEnabled ? option.DescriptionLocalizations : null
));
}
foreach (var option in target.Options)
{
List minimalSubTargetOptions = new();
foreach (var subOption in option.Options)
{
List minimalSubSubTargetOptions = null;
if (subOption.Options != null && subOption.Options.Any())
{
minimalSubSubTargetOptions = new();
foreach (var subSubOption in subOption.Options)
minimalSubSubTargetOptions.Add(new DiscordApplicationCommandOption(
subSubOption.Name, subSubOption.Description, subSubOption.Type, subSubOption.Required,
subSubOption.Choices, null, subSubOption.ChannelTypes, subSubOption.AutoComplete,
subSubOption.MinimumValue, subSubOption.MaximumValue,
localizationEnabled ? subSubOption.NameLocalizations : null,
localizationEnabled ? subSubOption.DescriptionLocalizations : null,
subSubOption.MinimumLength, subSubOption.MaximumLength
));
minimalSubTargetOptions.Add(new DiscordApplicationCommandOption(
subOption.Name, subOption.Description, subOption.Type,
options: minimalSubSubTargetOptions,
nameLocalizations: localizationEnabled ? subOption.NameLocalizations : null,
descriptionLocalizations: localizationEnabled ? subOption.DescriptionLocalizations : null
));
}
}
minimalTargetOptions.Add(new DiscordApplicationCommandOption(
option.Name, option.Description, option.Type,
options: minimalSubTargetOptions,
nameLocalizations: localizationEnabled ? option.NameLocalizations : null,
descriptionLocalizations: localizationEnabled ? option.DescriptionLocalizations : null
));
}
var sOpt = JsonConvert.SerializeObject(minimalSourceOptions, Formatting.None);
var tOpt = JsonConvert.SerializeObject(minimalTargetOptions, Formatting.None);
//Console.WriteLine("Checking equality subcommandgroup");
//Console.WriteLine($"{rootCheck}");
//Console.WriteLine($"{sOpt}");
//Console.WriteLine($"{tOpt}");
return rootCheck && sOpt == tOpt;
}
else if (source.Options.Any(o => o.Type == ApplicationCommandOptionType.SubCommand) && target.Options.Any(o => o.Type == ApplicationCommandOptionType.SubCommand))
{
List minimalSourceOptions = new();
List minimalTargetOptions = new();
foreach (var option in source.Options)
{
List minimalSubSourceOptions =null;
if (option.Options != null)
{
minimalSubSourceOptions = new();
foreach (var subOption in option.Options)
minimalSubSourceOptions.Add(new DiscordApplicationCommandOption(
subOption.Name, subOption.Description, subOption.Type, subOption.Required,
subOption.Choices, null, subOption.ChannelTypes, subOption.AutoComplete,
subOption.MinimumValue, subOption.MaximumValue,
localizationEnabled ? subOption.NameLocalizations : null,
localizationEnabled ? subOption.DescriptionLocalizations : null,
subOption.MinimumLength, subOption.MaximumLength
));
}
minimalSourceOptions.Add(new DiscordApplicationCommandOption(
option.Name, option.Description, option.Type,
options: minimalSubSourceOptions,
nameLocalizations: localizationEnabled ? option.NameLocalizations : null,
descriptionLocalizations: localizationEnabled ? option.DescriptionLocalizations : null
));
}
foreach (var option in target.Options)
{
List minimalSubTargetOptions = null;
if (option.Options != null && option.Options.Any())
{
minimalSubTargetOptions = new();
foreach (var subOption in option.Options)
minimalSubTargetOptions.Add(new DiscordApplicationCommandOption(
subOption.Name, subOption.Description, subOption.Type, subOption.Required,
subOption.Choices, null, subOption.ChannelTypes, subOption.AutoComplete,
subOption.MinimumValue, subOption.MaximumValue,
localizationEnabled ? subOption.NameLocalizations : null,
localizationEnabled ? subOption.DescriptionLocalizations : null,
subOption.MinimumLength, subOption.MaximumLength
));
}
minimalTargetOptions.Add(new DiscordApplicationCommandOption(
option.Name, option.Description, option.Type,
options: minimalSubTargetOptions,
nameLocalizations: localizationEnabled ? option.NameLocalizations : null,
descriptionLocalizations: localizationEnabled ? option.DescriptionLocalizations : null
));
}
var sOpt = JsonConvert.SerializeObject(minimalSourceOptions, Formatting.None);
var tOpt = JsonConvert.SerializeObject(minimalTargetOptions, Formatting.None);
//Console.WriteLine("Checking equality subcommand");
//Console.WriteLine($"{rootCheck}");
//Console.WriteLine($"{sOpt}");
//Console.WriteLine($"{tOpt}");
return rootCheck && sOpt == tOpt;
}
else
{
List minimalSourceOptions = new();
List minimalTargetOptions = new();
foreach (var option in source.Options)
minimalSourceOptions.Add(new DiscordApplicationCommandOption(
option.Name, option.Description, option.Type, option.Required,
option.Choices, null, option.ChannelTypes, option.AutoComplete, option.MinimumValue, option.MaximumValue,
localizationEnabled ? option.NameLocalizations : null,
localizationEnabled ? option.DescriptionLocalizations : null,
option.MinimumLength, option.MaximumLength
));
foreach (var option in target.Options)
minimalTargetOptions.Add(new DiscordApplicationCommandOption(
option.Name, option.Description, option.Type, option.Required,
option.Choices, null, option.ChannelTypes, option.AutoComplete, option.MinimumValue, option.MaximumValue,
localizationEnabled ? option.NameLocalizations : null,
localizationEnabled ? option.DescriptionLocalizations : null,
option.MinimumLength, option.MaximumLength
));
var sOpt = JsonConvert.SerializeObject(minimalSourceOptions, Formatting.None);
var tOpt = JsonConvert.SerializeObject(minimalTargetOptions, Formatting.None);
//Console.WriteLine("Checking equality other");
//Console.WriteLine($"{rootCheck}");
//Console.WriteLine($"{sOpt}");
//Console.WriteLine($"{tOpt}");
return rootCheck && sOpt == tOpt;
}
}
}
diff --git a/DisCatSharp.ApplicationCommands/Workers/RegistrationWorker.cs b/DisCatSharp.ApplicationCommands/Workers/RegistrationWorker.cs
index 642dba1d3..6ff129c1a 100644
--- a/DisCatSharp.ApplicationCommands/Workers/RegistrationWorker.cs
+++ b/DisCatSharp.ApplicationCommands/Workers/RegistrationWorker.cs
@@ -1,541 +1,541 @@
// This file is part of the DisCatSharp project, based off DSharpPlus.
//
// Copyright (c) 2021-2022 AITSYS
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DisCatSharp.ApplicationCommands.Checks;
using DisCatSharp.Common;
using DisCatSharp.Entities;
using DisCatSharp.Exceptions;
using Microsoft.Extensions.Logging;
namespace DisCatSharp.ApplicationCommands.Workers;
///
/// Represents a .
///
internal class RegistrationWorker
{
///
/// Registers the global commands.
///
/// The discord client.
/// The command list.
/// A list of registered commands.
internal static async Task> RegisterGlobalCommandsAsync(DiscordClient client, List commands)
{
var (changedCommands, unchangedCommands) = BuildGlobalOverwriteList(client, commands);
var globalCommandsCreateList = BuildGlobalCreateList(client, commands);
var globalCommandsDeleteList = BuildGlobalDeleteList(client, commands);
if (globalCommandsCreateList.NotEmptyAndNotNull() && unchangedCommands.NotEmptyAndNotNull() && changedCommands.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Creating, re-using and overwriting application commands.");
foreach (var cmd in globalCommandsCreateList)
{
var discordBackendCommand = await client.CreateGlobalApplicationCommandAsync(cmd);
commands.Add(discordBackendCommand);
}
foreach (var cmd in changedCommands)
{
var command = cmd.Value;
var discordBackendCommand = await client.EditGlobalApplicationCommandAsync(cmd.Key, action =>
{
action.Name = command.Name;
action.NameLocalizations = command.NameLocalizations;
action.Description = command.Description;
action.DescriptionLocalizations = command.DescriptionLocalizations;
if(command.Options != null && command.Options.Any())
action.Options = Optional.Some(command.Options);
action.DefaultMemberPermissions = command.DefaultMemberPermissions;
action.DmPermission = command.DmPermission ?? true;
//action.IsNsfw = command.IsNsfw;
});
commands.Add(discordBackendCommand);
}
commands.AddRange(unchangedCommands);
}
else if (globalCommandsCreateList.NotEmptyAndNotNull() && (unchangedCommands.NotEmptyAndNotNull() || changedCommands.NotEmptyAndNotNull()))
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Creating, re-using and overwriting application commands.");
foreach (var cmd in globalCommandsCreateList)
{
var discordBackendCommand = await client.CreateGlobalApplicationCommandAsync(cmd);
commands.Add(discordBackendCommand);
}
if (changedCommands.NotEmptyAndNotNull())
foreach (var cmd in changedCommands)
{
var command = cmd.Value;
var discordBackendCommand = await client.EditGlobalApplicationCommandAsync(cmd.Key, action =>
{
action.Name = command.Name;
action.NameLocalizations = command.NameLocalizations;
action.Description = command.Description;
action.DescriptionLocalizations = command.DescriptionLocalizations;
if(command.Options != null && command.Options.Any())
action.Options = Optional.Some(command.Options);
action.DefaultMemberPermissions = command.DefaultMemberPermissions;
action.DmPermission = command.DmPermission ?? true;
//action.IsNsfw = command.IsNsfw;
});
commands.Add(discordBackendCommand);
}
if (unchangedCommands.NotEmptyAndNotNull())
commands.AddRange(unchangedCommands);
}
else if (globalCommandsCreateList.EmptyOrNull() && unchangedCommands.NotEmptyAndNotNull() && changedCommands.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Editing & re-using application commands.");
foreach (var cmd in changedCommands)
{
var command = cmd.Value;
var discordBackendCommand = await client.EditGlobalApplicationCommandAsync(cmd.Key, action =>
{
action.Name = command.Name;
action.NameLocalizations = command.NameLocalizations;
action.Description = command.Description;
action.DescriptionLocalizations = command.DescriptionLocalizations;
if(command.Options != null && command.Options.Any())
action.Options = Optional.Some(command.Options);
action.DefaultMemberPermissions = command.DefaultMemberPermissions;
action.DmPermission = command.DmPermission ?? true;
//action.IsNsfw = command.IsNsfw;
});
commands.Add(discordBackendCommand);
}
commands.AddRange(unchangedCommands);
}
else if (globalCommandsCreateList.EmptyOrNull() && changedCommands.NotEmptyAndNotNull() && unchangedCommands.EmptyOrNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Overwriting all application commands.");
List overwriteList = new();
foreach (var overwrite in changedCommands)
{
var cmd = overwrite.Value;
cmd.Id = overwrite.Key;
overwriteList.Add(cmd);
}
var discordBackendCommands = await client.BulkOverwriteGlobalApplicationCommandsAsync(overwriteList);
commands.AddRange(discordBackendCommands);
}
else if (globalCommandsCreateList.NotEmptyAndNotNull() && changedCommands.EmptyOrNull() && unchangedCommands.EmptyOrNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Creating all application commands.");
var cmds = await client.BulkOverwriteGlobalApplicationCommandsAsync(globalCommandsCreateList);
commands.AddRange(cmds);
}
else if (globalCommandsCreateList.EmptyOrNull() && changedCommands.EmptyOrNull() && unchangedCommands.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Re-using all application commands.");
commands.AddRange(unchangedCommands);
}
if (globalCommandsDeleteList.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, $"[AC GLOBAL] Deleting missing application commands.");
foreach (var cmdId in globalCommandsDeleteList)
try
{
await client.DeleteGlobalApplicationCommandAsync(cmdId);
}
catch (NotFoundException)
{
client.Logger.LogError(@"Could not delete global command {cmd}. Please clean up manually", cmdId);
}
}
return commands.NotEmptyAndNotNull() ? commands : null;
}
///
/// Registers the guild commands.
///
/// The discord client.
/// The target guild id.
/// The command list.
/// A list of registered commands.
internal static async Task> RegisterGuildCommandsAsync(DiscordClient client, ulong guildId, List commands)
{
var (changedCommands, unchangedCommands) = BuildGuildOverwriteList(client, guildId, commands);
var guildCommandsCreateList = BuildGuildCreateList(client, guildId, commands);
var guildCommandsDeleteList = BuildGuildDeleteList(client, guildId, commands);
if (guildCommandsCreateList.NotEmptyAndNotNull() && unchangedCommands.NotEmptyAndNotNull() && changedCommands.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Creating, re-using and overwriting application commands. Guild ID: {guild}", guildId);
foreach (var cmd in guildCommandsCreateList)
{
var discordBackendCommand = await client.CreateGuildApplicationCommandAsync(guildId, cmd);
commands.Add(discordBackendCommand);
}
foreach (var cmd in changedCommands)
{
var command = cmd.Value;
var discordBackendCommand = await client.EditGuildApplicationCommandAsync(guildId, cmd.Key, action =>
{
action.Name = command.Name;
action.NameLocalizations = command.NameLocalizations;
action.Description = command.Description;
action.DescriptionLocalizations = command.DescriptionLocalizations;
if(command.Options != null && command.Options.Any())
action.Options = Optional.Some(command.Options);
action.DefaultMemberPermissions = command.DefaultMemberPermissions;
action.DmPermission = command.DmPermission ?? true;
//action.IsNsfw = command.IsNsfw;
});
commands.Add(discordBackendCommand);
}
commands.AddRange(unchangedCommands);
}
else if (guildCommandsCreateList.NotEmptyAndNotNull() && (unchangedCommands.NotEmptyAndNotNull() || changedCommands.NotEmptyAndNotNull()))
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Creating, re-using and overwriting application commands. Guild ID: {guild}", guildId);
foreach (var cmd in guildCommandsCreateList)
{
var discordBackendCommand = await client.CreateGuildApplicationCommandAsync(guildId, cmd);
commands.Add(discordBackendCommand);
}
if (changedCommands.NotEmptyAndNotNull())
foreach (var cmd in changedCommands)
{
var command = cmd.Value;
var discordBackendCommand = await client.EditGuildApplicationCommandAsync(guildId, cmd.Key, action =>
{
action.Name = command.Name;
action.NameLocalizations = command.NameLocalizations;
action.Description = command.Description;
action.DescriptionLocalizations = command.DescriptionLocalizations;
if(command.Options != null && command.Options.Any())
action.Options = Optional.Some(command.Options);
action.DefaultMemberPermissions = command.DefaultMemberPermissions;
action.DmPermission = command.DmPermission ?? true;
//action.IsNsfw = command.IsNsfw;
});
commands.Add(discordBackendCommand);
}
if (unchangedCommands.NotEmptyAndNotNull())
commands.AddRange(unchangedCommands);
}
else if (guildCommandsCreateList.EmptyOrNull() && unchangedCommands.NotEmptyAndNotNull() && changedCommands.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Editing & re-using application commands. Guild ID: {guild}", guildId);
foreach (var cmd in changedCommands)
{
var command = cmd.Value;
var discordBackendCommand = await client.EditGuildApplicationCommandAsync(guildId, cmd.Key, action =>
{
action.Name = command.Name;
action.NameLocalizations = command.NameLocalizations;
action.Description = command.Description;
action.DescriptionLocalizations = command.DescriptionLocalizations;
if(command.Options != null && command.Options.Any())
action.Options = Optional.Some(command.Options);
if (command.DefaultMemberPermissions.HasValue)
action.DefaultMemberPermissions = command.DefaultMemberPermissions.Value;
if (command.DmPermission.HasValue)
action.DmPermission = command.DmPermission.Value;
//action.IsNsfw = command.IsNsfw;
});
commands.Add(discordBackendCommand);
}
commands.AddRange(unchangedCommands);
}
else if (guildCommandsCreateList.EmptyOrNull() && changedCommands.NotEmptyAndNotNull() && unchangedCommands.EmptyOrNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Overwriting all application commands. Guild ID: {guild}", guildId);
List overwriteList = new();
foreach (var overwrite in changedCommands)
{
var cmd = overwrite.Value;
cmd.Id = overwrite.Key;
overwriteList.Add(cmd);
}
var discordBackendCommands = await client.BulkOverwriteGuildApplicationCommandsAsync(guildId, overwriteList);
commands.AddRange(discordBackendCommands);
}
else if (guildCommandsCreateList.NotEmptyAndNotNull() && changedCommands.EmptyOrNull() && unchangedCommands.EmptyOrNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Creating all application commands. Guild ID: {guild}", guildId);
var cmds = await client.BulkOverwriteGuildApplicationCommandsAsync(guildId, guildCommandsCreateList);
commands.AddRange(cmds);
}
else if (guildCommandsCreateList.EmptyOrNull() && changedCommands.EmptyOrNull() && unchangedCommands.NotEmptyAndNotNull())
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Re-using all application commands Guild ID: {guild}.", guildId);
commands.AddRange(unchangedCommands);
}
if (guildCommandsDeleteList.NotEmptyAndNotNull())
foreach (var cmdId in guildCommandsDeleteList)
{
client.Logger.Log(ApplicationCommandsExtension.ApplicationCommandsLogLevel, @"[AC GUILD] Deleting missing application commands. Guild ID: {guild}", guildId);
try
{
await client.DeleteGuildApplicationCommandAsync(guildId, cmdId);
}
catch (NotFoundException)
{
client.Logger.LogError(@"Could not delete guild command {cmd} in guild {guild}. Please clean up manually", cmdId, guildId);
}
}
return commands.NotEmptyAndNotNull() ? commands : null;
}
///
/// Builds a list of guild command ids to be deleted on discords backend.
///
/// The discord client.
/// The guild id these commands belong to.
/// The command list.
/// A list of command ids.
private static List BuildGuildDeleteList(DiscordClient client, ulong guildId, List updateList)
{
if (ApplicationCommandsExtension.GuildDiscordCommands == null || !ApplicationCommandsExtension.GuildDiscordCommands.Any()
|| !ApplicationCommandsExtension.GuildDiscordCommands.GetFirstValueByKey(guildId, out var discord)
)
return null;
List invalidCommandIds = new();
if (discord == null)
return null;
if (updateList == null)
foreach (var cmd in discord)
invalidCommandIds.Add(cmd.Id);
else
foreach (var cmd in discord)
if (!updateList.Any(ul => ul.Name == cmd.Name))
invalidCommandIds.Add(cmd.Id);
return invalidCommandIds;
}
///
/// Builds a list of guild commands to be created on discords backend.
///
/// The discord client.
/// The guild id these commands belong to.
/// The command list.
///
private static List BuildGuildCreateList(DiscordClient client, ulong guildId, List updateList)
{
if (ApplicationCommandsExtension.GuildDiscordCommands == null || !ApplicationCommandsExtension.GuildDiscordCommands.Any()
|| updateList == null || !ApplicationCommandsExtension.GuildDiscordCommands.GetFirstValueByKey(guildId, out var discord)
)
return updateList;
List newCommands = new();
if (discord == null)
return updateList;
foreach (var cmd in updateList)
if (discord.All(d => d.Name != cmd.Name))
newCommands.Add(cmd);
return newCommands;
}
///
/// Builds a list of guild commands to be overwritten on discords backend.
///
/// The discord client.
/// The guild id these commands belong to.
/// The command list.
/// A dictionary of command id and command.
private static (
Dictionary changedCommands,
List unchangedCommands
) BuildGuildOverwriteList(DiscordClient client, ulong guildId, List updateList)
{
if (ApplicationCommandsExtension.GuildDiscordCommands == null || !ApplicationCommandsExtension.GuildDiscordCommands.Any()
|| ApplicationCommandsExtension.GuildDiscordCommands.All(l => l.Key != guildId) || updateList == null
|| !ApplicationCommandsExtension.GuildDiscordCommands.GetFirstValueByKey(guildId, out var discord)
)
return (null, null);
Dictionary updateCommands = new();
List unchangedCommands = new();
if (discord == null)
return (null, null);
foreach (var cmd in updateList)
if (discord.GetFirstValueWhere(d => d.Name == cmd.Name, out var command))
- if (command.IsEqualTo(cmd, client))
+ if (command.IsEqualTo(cmd, client, true))
{
if (ApplicationCommandsExtension.DebugEnabled)
client.Logger.LogDebug(@"[AC] Command {cmdName} unchanged", cmd.Name);
cmd.Id = command.Id;
cmd.ApplicationId = command.ApplicationId;
cmd.Version = command.Version;
unchangedCommands.Add(cmd);
}
else
{
if (ApplicationCommandsExtension.DebugEnabled)
client.Logger.LogDebug(@"[AC] Command {cmdName} changed", cmd.Name);
updateCommands.Add(command.Id, cmd);
}
return (updateCommands, unchangedCommands);
}
///
/// Builds a list of global command ids to be deleted on discords backend.
///
/// The discord client.
/// The command list.
/// A list of command ids.
private static List BuildGlobalDeleteList(DiscordClient client, List updateList = null)
{
if (ApplicationCommandsExtension.GlobalDiscordCommands == null || !ApplicationCommandsExtension.GlobalDiscordCommands.Any()
|| ApplicationCommandsExtension.GlobalDiscordCommands == null
)
return null;
var discord = ApplicationCommandsExtension.GlobalDiscordCommands;
List invalidCommandIds = new();
if (discord == null)
return null;
if (updateList == null)
foreach (var cmd in discord)
invalidCommandIds.Add(cmd.Id);
else
foreach (var cmd in discord)
if (updateList.All(ul => ul.Name != cmd.Name))
invalidCommandIds.Add(cmd.Id);
return invalidCommandIds;
}
///
/// Builds a list of global commands to be created on discords backend.
///
/// The discord client.
/// The command list.
/// A list of commands.
private static List BuildGlobalCreateList(DiscordClient client, List updateList)
{
if (ApplicationCommandsExtension.GlobalDiscordCommands == null || !ApplicationCommandsExtension.GlobalDiscordCommands.Any() || updateList == null)
return updateList;
var discord = ApplicationCommandsExtension.GlobalDiscordCommands;
List newCommands = new();
if (discord == null)
return updateList;
foreach (var cmd in updateList)
if (discord.All(d => d.Name != cmd.Name))
newCommands.Add(cmd);
return newCommands;
}
///
/// Builds a list of global commands to be overwritten on discords backend.
///
/// The discord client.
/// The command list.
/// A dictionary of command ids and commands.
private static (
Dictionary changedCommands,
List unchangedCommands
) BuildGlobalOverwriteList(DiscordClient client, List updateList)
{
if (ApplicationCommandsExtension.GlobalDiscordCommands == null || !ApplicationCommandsExtension.GlobalDiscordCommands.Any()
|| updateList == null || ApplicationCommandsExtension.GlobalDiscordCommands == null
)
return (null, null);
var discord = ApplicationCommandsExtension.GlobalDiscordCommands;
if (discord == null)
return (null, null);
Dictionary updateCommands = new();
List unchangedCommands = new();
foreach (var cmd in updateList)
if (discord.GetFirstValueWhere(d => d.Name == cmd.Name, out var command))
- if (command.IsEqualTo(cmd, client))
+ if (command.IsEqualTo(cmd, client, false))
{
if (ApplicationCommandsExtension.DebugEnabled)
client.Logger.LogDebug(@"[AC] Command {cmdName} unchanged", cmd.Name);
cmd.Id = command.Id;
cmd.ApplicationId = command.ApplicationId;
cmd.Version = command.Version;
unchangedCommands.Add(cmd);
}
else
{
if (ApplicationCommandsExtension.DebugEnabled)
client.Logger.LogDebug(@"[AC] Command {cmdName} changed", cmd.Name);
updateCommands.Add(command.Id, cmd);
}
return (updateCommands, unchangedCommands);
}
}