Skip to content

Commit

Permalink
fix: fixed translations (while i'm on it)
Browse files Browse the repository at this point in the history
  • Loading branch information
Lulalaby committed Jan 17, 2024
1 parent abb2e70 commit 1ffb542
Show file tree
Hide file tree
Showing 18 changed files with 165 additions and 138 deletions.
53 changes: 31 additions & 22 deletions DisCatSharp.ApplicationCommands/ApplicationCommandsExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -662,39 +662,37 @@ private async Task RegisterCommands(List<ApplicationCommandsModuleConfiguration>
if (Configuration.GenerateTranslationFilesOnly)
{
var cgwsgs = new List<CommandGroupWithSubGroups>();
var cgs2 = new List<CommandGroup>();
foreach (var cmd in slashGroupsTuple.applicationCommands)
if (cmd.Type is ApplicationCommandType.ChatInput)
{
var cgs = new List<CommandGroup>();
var cs2 = new List<Command>();
if (cmd.Options is not null)
{
foreach (var scg in cmd.Options.Where(x => x.Type is ApplicationCommandOptionType.SubCommandGroup))
{
var cs = new List<Command>();
if (scg.Options is not null)
foreach (var sc in scg.Options)
if (sc.Options is null || sc.Options.Count is 0)
cs.Add(new(sc.Name, sc.Description, null, null));
cs.Add(new(sc.Name, sc.Description, null, null, sc.RawNameLocalizations, sc.RawDescriptionLocalizations));
else
cs.Add(new(sc.Name, sc.Description, [.. sc.Options], null));
cgs.Add(new(scg.Name, scg.Description, cs, null));
cs.Add(new(sc.Name, sc.Description, [.. sc.Options], null, sc.RawNameLocalizations, sc.RawDescriptionLocalizations));
cgs.Add(new(scg.Name, scg.Description, cs, null, scg.RawNameLocalizations, scg.RawDescriptionLocalizations));
}

cgwsgs.Add(new(cmd.Name, cmd.Description, cgs, cmd.Type));
foreach (var sc2 in cmd.Options.Where(x => x.Type is ApplicationCommandOptionType.SubCommand))
if (sc2.Options == null || sc2.Options.Count == 0)
cs2.Add(new(sc2.Name, sc2.Description, null, null, sc2.RawNameLocalizations, sc2.RawDescriptionLocalizations));
else
cs2.Add(new(sc2.Name, sc2.Description, [.. sc2.Options], null, sc2.RawNameLocalizations, sc2.RawDescriptionLocalizations));
}

var cs2 = new List<Command>();
foreach (var sc2 in cmd.Options.Where(x => x.Type is ApplicationCommandOptionType.SubCommand))
if (sc2.Options == null || sc2.Options.Count == 0)
cs2.Add(new(sc2.Name, sc2.Description, null, null));
else
cs2.Add(new(sc2.Name, sc2.Description, [.. sc2.Options], null));
cgs2.Add(new(cmd.Name, cmd.Description, cs2, cmd.Type));
cgwsgs.Add(new(cmd.Name, cmd.Description, cgs, cs2, cmd.Type, cmd.RawNameLocalizations, cmd.RawDescriptionLocalizations));
}

if (cgwsgs.Count is not 0)
groupTranslation.AddRange(cgwsgs.Select(cgwsg => JsonConvert.DeserializeObject<GroupTranslator>(JsonConvert.SerializeObject(cgwsg))!));
if (cgs2.Count is not 0)
groupTranslation.AddRange(cgs2.Select(cg2 => JsonConvert.DeserializeObject<GroupTranslator>(JsonConvert.SerializeObject(cg2))!));
}
}

Expand Down Expand Up @@ -734,12 +732,20 @@ private async Task RegisterCommands(List<ApplicationCommandsModuleConfiguration>
var cs = new List<Command>();
foreach (var cmd in slashCommands.applicationCommands.Where(cmd => cmd.Type is ApplicationCommandType.ChatInput && (cmd.Options is null || !cmd.Options.Any(x => x.Type is ApplicationCommandOptionType.SubCommand or ApplicationCommandOptionType.SubCommandGroup))))
if (cmd.Options == null || cmd.Options.Count == 0)
cs.Add(new(cmd.Name, cmd.Description, null, ApplicationCommandType.ChatInput));
cs.Add(new(cmd.Name, cmd.Description, null, ApplicationCommandType.ChatInput, cmd.RawNameLocalizations, cmd.RawDescriptionLocalizations));
else
cs.Add(new(cmd.Name, cmd.Description, [.. cmd.Options], ApplicationCommandType.ChatInput));
cs.Add(new(cmd.Name, cmd.Description, [.. cmd.Options], ApplicationCommandType.ChatInput, cmd.RawNameLocalizations, cmd.RawDescriptionLocalizations));

if (cs.Count is not 0)
translation.AddRange(cs.Select(c => JsonConvert.DeserializeObject<CommandTranslator>(JsonConvert.SerializeObject(c))!));
//translation.AddRange(cs.Select(c => JsonConvert.DeserializeObject<CommandTranslator>(JsonConvert.SerializeObject(c))!));
{
foreach (var c in cs)
{
var json = JsonConvert.SerializeObject(c);
var obj = JsonConvert.DeserializeObject<CommandTranslator>(json);
translation.Add(obj!);
}
}
}
}

Expand Down Expand Up @@ -805,7 +811,7 @@ private async Task RegisterCommands(List<ApplicationCommandsModuleConfiguration>
{
updateList = updateList.DistinctBy(x => x.Name).ToList();
if (Configuration.GenerateTranslationFilesOnly)
await this.CheckRegistrationStartup(translation, groupTranslation);
await this.CheckRegistrationStartup(translation, groupTranslation, guildId);
else
try
{
Expand Down Expand Up @@ -912,7 +918,7 @@ private async Task RegisterCommands(List<ApplicationCommandsModuleConfiguration>
RegisteredCommands = GlobalCommandsInternal
}).ConfigureAwait(false);

await this.CheckRegistrationStartup(translation, groupTranslation);
await this.CheckRegistrationStartup(translation, groupTranslation, guildId);
}
catch (NullReferenceException ex)
{
Expand Down Expand Up @@ -966,15 +972,16 @@ private async Task RegisterCommands(List<ApplicationCommandsModuleConfiguration>
/// </summary>
/// <param name="translation">The optional translations.</param>
/// <param name="groupTranslation">The optional group translations.</param>
private async Task CheckRegistrationStartup(List<CommandTranslator>? translation = null, List<GroupTranslator>? groupTranslation = null)
/// <param name="guildId">The optional guild id.</param>
private async Task CheckRegistrationStartup(List<CommandTranslator>? translation = null, List<GroupTranslator>? groupTranslation = null, ulong? guildId = null)
{
if (Configuration.GenerateTranslationFilesOnly)
{
try
{
if (translation is not null && translation.Count is not 0)
{
var fileName = $"translation_generator_export-shard{this.Client.ShardId}-SINGLE.json";
var fileName = $"translation_generator_export-shard{this.Client.ShardId}-SINGLE-{(guildId.HasValue ? guildId.Value : "global")}.json";
var fs = File.Create(fileName);
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
Expand All @@ -992,7 +999,7 @@ private async Task CheckRegistrationStartup(List<CommandTranslator>? translation

if (groupTranslation is not null && groupTranslation.Count is not 0)
{
var fileName = $"translation_generator_export-shard{this.Client.ShardId}-GROUP.json";
var fileName = $"translation_generator_export-shard{this.Client.ShardId}-GROUP-{(guildId.HasValue ? guildId.Value : "global")}.json";
var fs = File.Create(fileName);
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
Expand Down Expand Up @@ -1031,6 +1038,8 @@ private async Task CheckStartupFinishAsync(ApplicationCommandsExtension sender,
GuildsWithoutScope = s_missingScopeGuildIdsGlobal
}).ConfigureAwait(false);
FinishFired = true;
if (Configuration.GenerateTranslationFilesOnly)
Environment.Exit(0);
}

args.Handled = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,29 @@ namespace DisCatSharp.ApplicationCommands.Attributes;
/// <summary>
/// Defines a cooldown for this command. This allows you to define how many times can users execute a specific command
/// </summary>
/// <remarks>
/// Defines a cooldown for this command. This means that users will be able to use the command a specific number of times before they have to wait to use it again.
/// </remarks>
/// <param name="maxUses">Number of times the command can be used before triggering a cooldown.</param>
/// <param name="resetAfter">Number of seconds after which the cooldown is reset.</param>
/// <param name="bucketType">Type of cooldown bucket. This allows controlling whether the bucket will be cooled down per user, guild, member, channel, and/or globally.</param>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class ContextMenuCooldownAttribute : ApplicationCommandCheckBaseAttribute, ICooldown<BaseContext, CooldownBucket>
public sealed class ContextMenuCooldownAttribute(int maxUses, double resetAfter, CooldownBucketType bucketType) : ApplicationCommandCheckBaseAttribute, ICooldown<BaseContext, CooldownBucket>
{
/// <summary>
/// Gets the maximum number of uses before this command triggers a cooldown for its bucket.
/// </summary>
public int MaxUses { get; }
public int MaxUses { get; } = maxUses;

/// <summary>
/// Gets the time after which the cooldown is reset.
/// </summary>
public TimeSpan Reset { get; }
public TimeSpan Reset { get; } = TimeSpan.FromSeconds(resetAfter);

/// <summary>
/// Gets the type of the cooldown bucket. This determines how cooldowns are applied.
/// </summary>
public CooldownBucketType BucketType { get; }

/// <summary>
/// Defines a cooldown for this command. This means that users will be able to use the command a specific number of times before they have to wait to use it again.
/// </summary>
/// <param name="maxUses">Number of times the command can be used before triggering a cooldown.</param>
/// <param name="resetAfter">Number of seconds after which the cooldown is reset.</param>
/// <param name="bucketType">Type of cooldown bucket. This allows controlling whether the bucket will be cooled down per user, guild, member, channel, and/or globally.</param>
public ContextMenuCooldownAttribute(int maxUses, double resetAfter, CooldownBucketType bucketType)
{
this.MaxUses = maxUses;
this.Reset = TimeSpan.FromSeconds(resetAfter);
this.BucketType = bucketType;
}
public CooldownBucketType BucketType { get; } = bucketType;

/// <summary>
/// Gets a cooldown bucket for given command context.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,29 @@ namespace DisCatSharp.ApplicationCommands.Attributes;
/// <summary>
/// Defines a cooldown for this command. This allows you to define how many times can users execute a specific command.
/// </summary>
/// <remarks>
/// Defines a cooldown for this command. This means that users will be able to use the command a specific number of times before they have to wait to use it again.
/// </remarks>
/// <param name="maxUses">Number of times the command can be used before triggering a cooldown.</param>
/// <param name="resetAfter">Number of seconds after which the cooldown is reset.</param>
/// <param name="bucketType">Type of cooldown bucket. This allows controlling whether the bucket will be cooled down per user, guild, member, channel, and/or globally.</param>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = true, Inherited = false)]
public sealed class SlashCommandCooldownAttribute : ApplicationCommandCheckBaseAttribute, ICooldown<BaseContext, CooldownBucket>
public sealed class SlashCommandCooldownAttribute(int maxUses, double resetAfter, CooldownBucketType bucketType) : ApplicationCommandCheckBaseAttribute, ICooldown<BaseContext, CooldownBucket>
{
/// <summary>
/// Gets the maximum number of uses before this command triggers a cooldown for its bucket.
/// </summary>
public int MaxUses { get; }
public int MaxUses { get; } = maxUses;

/// <summary>
/// Gets the time after which the cooldown is reset.
/// </summary>
public TimeSpan Reset { get; }
public TimeSpan Reset { get; } = TimeSpan.FromSeconds(resetAfter);

/// <summary>
/// Gets the type of the cooldown bucket. This determines how cooldowns are applied.
/// </summary>
public CooldownBucketType BucketType { get; }

/// <summary>
/// Defines a cooldown for this command. This means that users will be able to use the command a specific number of times before they have to wait to use it again.
/// </summary>
/// <param name="maxUses">Number of times the command can be used before triggering a cooldown.</param>
/// <param name="resetAfter">Number of seconds after which the cooldown is reset.</param>
/// <param name="bucketType">Type of cooldown bucket. This allows controlling whether the bucket will be cooled down per user, guild, member, channel, and/or globally.</param>
public SlashCommandCooldownAttribute(int maxUses, double resetAfter, CooldownBucketType bucketType)
{
this.MaxUses = maxUses;
this.Reset = TimeSpan.FromSeconds(resetAfter);
this.BucketType = bucketType;
}
public CooldownBucketType BucketType { get; } = bucketType;

/// <summary>
/// Gets a cooldown bucket for given command context.
Expand Down
17 changes: 14 additions & 3 deletions DisCatSharp.ApplicationCommands/Entities/ChoiceTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,20 @@ internal sealed class ChoiceTranslator
/// Gets the choice name translations.
/// </summary>
[JsonProperty("name_translations")]
internal Dictionary<string, string> NameTranslationsDictionary { get; set; }
internal Dictionary<string, string>? NameTranslationsDictionary { get; set; }

[JsonIgnore]
public DiscordApplicationCommandLocalization NameTranslations
=> new(this.NameTranslationsDictionary);
public DiscordApplicationCommandLocalization? NameTranslations
=> this.NameTranslationsDictionary is not null ? new(this.NameTranslationsDictionary) : null;

internal static ChoiceTranslator FromApplicationCommandChoice(DiscordApplicationCommandOptionChoice option)
{
var translator = new ChoiceTranslator
{
Name = option.Name,
NameTranslationsDictionary = option.RawNameLocalizations
};

return translator;
}
}
14 changes: 7 additions & 7 deletions DisCatSharp.ApplicationCommands/Entities/CommandTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,25 @@ internal sealed class CommandTranslator
/// Gets the command name translations.
/// </summary>
[JsonProperty("name_translations")]
internal Dictionary<string, string> NameTranslationDictionary { get; set; }
internal Dictionary<string, string>? NameTranslationsDictionary { get; set; }

[JsonIgnore]
public DiscordApplicationCommandLocalization NameTranslations
=> new(this.NameTranslationDictionary);
public DiscordApplicationCommandLocalization? NameTranslations
=> this.NameTranslationsDictionary is not null ? new(this.NameTranslationsDictionary) : null;

/// <summary>
/// Gets the command description translations.
/// </summary>
[JsonProperty("description_translations")]
internal Dictionary<string, string> DescriptionTranslationDictionary { get; set; }
internal Dictionary<string, string>? DescriptionTranslationsDictionary { get; set; }

[JsonIgnore]
public DiscordApplicationCommandLocalization DescriptionTranslations
=> new(this.DescriptionTranslationDictionary);
public DiscordApplicationCommandLocalization? DescriptionTranslations
=> this.DescriptionTranslationsDictionary is not null ? new(this.DescriptionTranslationsDictionary) : null;

/// <summary>
/// Gets the option translators, if applicable.
/// </summary>
[JsonProperty("options", NullValueHandling = NullValueHandling.Ignore)]
public List<OptionTranslator> Options { get; set; }
public List<OptionTranslator>? Options { get; set; }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;

using DisCatSharp.Entities;
using DisCatSharp.Enums;
Expand All @@ -12,10 +13,14 @@ internal sealed class CommandGroupWithSubGroups : BaseCommand
[JsonProperty("groups")]
internal List<CommandGroup> SubGroups { get; set; }

internal CommandGroupWithSubGroups(string name, string description, List<CommandGroup> commands, ApplicationCommandType type)
: base(name, description, type)
[JsonProperty("commands")]
internal List<Command> Commands { get; set; }

internal CommandGroupWithSubGroups(string name, string description, List<CommandGroup> subGroups, List<Command> commands, ApplicationCommandType type, Dictionary<string, string>? nameTranslations = null, Dictionary<string, string>? descriptionTranslations = null)
: base(name, description, type, nameTranslations, descriptionTranslations)
{
this.SubGroups = commands;
this.SubGroups = subGroups;
this.Commands = commands;
}
}

Expand All @@ -24,8 +29,8 @@ internal sealed class CommandGroup : BaseCommand
[JsonProperty("commands")]
internal List<Command> Commands { get; set; }

internal CommandGroup(string name, string description, List<Command> commands, ApplicationCommandType? type = null)
: base(name, description, type)
internal CommandGroup(string name, string description, List<Command> commands, ApplicationCommandType? type = null, Dictionary<string, string>? nameTranslations = null, Dictionary<string, string>? descriptionTranslations = null)
: base(name, description, type, nameTranslations, descriptionTranslations)
{
this.Commands = commands;
}
Expand All @@ -34,12 +39,13 @@ internal CommandGroup(string name, string description, List<Command> commands, A
internal sealed class Command : BaseCommand
{
[JsonProperty("options")]
internal List<DiscordApplicationCommandOption>? Options { get; set; }
internal List<OptionTranslator>? Options { get; set; }

internal Command(string name, string? description = null, List<DiscordApplicationCommandOption>? options = null, ApplicationCommandType? type = null)
: base(name, description, type)
internal Command(string name, string? description = null, List<DiscordApplicationCommandOption>? options = null, ApplicationCommandType? type = null, Dictionary<string, string>? nameTranslations = null, Dictionary<string, string>? descriptionTranslations = null)
: base(name, description, type, nameTranslations, descriptionTranslations)
{
this.Options = options;
if (options is not null)
this.Options = options.Select(OptionTranslator.FromApplicationCommandOption).ToList();
}
}

Expand All @@ -48,16 +54,24 @@ internal class BaseCommand
[JsonProperty("name")]
internal string Name { get; set; }

[JsonProperty("name_translations")]
internal Dictionary<string, string>? NameTranslations { get; set; }

[JsonProperty("description", NullValueHandling = NullValueHandling.Ignore)]
internal string? Description { get; set; }

[JsonProperty("description_translations", NullValueHandling = NullValueHandling.Ignore)]
internal Dictionary<string, string>? DescriptionTranslations { get; set; }

[JsonProperty("type", NullValueHandling = NullValueHandling.Ignore)]
internal ApplicationCommandType? Type { get; set; }

internal BaseCommand(string name, string? description = null, ApplicationCommandType? type = null)
internal BaseCommand(string name, string? description = null, ApplicationCommandType? type = null, Dictionary<string, string>? nameTranslations = null, Dictionary<string, string>? descriptionTranslations = null)
{
this.Name = name;
this.Type = type;
this.Description = description;
this.NameTranslations = nameTranslations;
this.DescriptionTranslations = descriptionTranslations;
}
}
12 changes: 6 additions & 6 deletions DisCatSharp.ApplicationCommands/Entities/GroupTranslator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,21 +35,21 @@ internal sealed class GroupTranslator
/// Gets the group name translations.
/// </summary>
[JsonProperty("name_translations")]
internal Dictionary<string, string> NameTranslationsDictionary { get; set; }
internal Dictionary<string, string>? NameTranslationsDictionary { get; set; }

[JsonIgnore]
public DiscordApplicationCommandLocalization NameTranslations
=> new(this.NameTranslationsDictionary);
public DiscordApplicationCommandLocalization? NameTranslations
=> this.NameTranslationsDictionary is not null ? new(this.NameTranslationsDictionary) : null;

/// <summary>
/// Gets the group description translations.
/// </summary>
[JsonProperty("description_translations")]
internal Dictionary<string, string> DescriptionTranslationsDictionary { get; set; }
internal Dictionary<string, string>? DescriptionTranslationsDictionary { get; set; }

[JsonIgnore]
public DiscordApplicationCommandLocalization DescriptionTranslations
=> new(this.DescriptionTranslationsDictionary);
public DiscordApplicationCommandLocalization? DescriptionTranslations
=> this.DescriptionTranslationsDictionary is not null ? new(this.DescriptionTranslationsDictionary) : null;

/// <summary>
/// Gets the sub group translators, if applicable.
Expand Down
Loading

0 comments on commit 1ffb542

Please sign in to comment.