diff --git a/locale/Messages.resx b/locale/Messages.resx
index 7b9a471..cf6f89d 100644
--- a/locale/Messages.resx
+++ b/locale/Messages.resx
@@ -654,4 +654,10 @@
Your random number is:
+
+ Timestamp for {0}:
+
+
+ Offset: {0}
+
diff --git a/locale/Messages.ru.resx b/locale/Messages.ru.resx
index 8489a45..aff4dd3 100644
--- a/locale/Messages.ru.resx
+++ b/locale/Messages.ru.resx
@@ -654,4 +654,10 @@
Ваше случайное число:
+
+ Временная метка для {0}:
+
+
+ Офсет: {0}
+
diff --git a/locale/Messages.tt-ru.resx b/locale/Messages.tt-ru.resx
index df98622..7c65929 100644
--- a/locale/Messages.tt-ru.resx
+++ b/locale/Messages.tt-ru.resx
@@ -654,4 +654,10 @@
ваше рандомное число:
+
+ таймштамп для {0}:
+
+
+ офсет: {0}
+
diff --git a/src/Commands/ToolsCommandGroup.cs b/src/Commands/ToolsCommandGroup.cs
index 64e6729..6abb918 100644
--- a/src/Commands/ToolsCommandGroup.cs
+++ b/src/Commands/ToolsCommandGroup.cs
@@ -19,7 +19,7 @@ using Remora.Results;
namespace Octobot.Commands;
///
-/// Handles tool commands: /showinfo, /random.
+/// Handles tool commands: /showinfo, /random, /timestamp.
///
[UsedImplicitly]
public class ToolsCommandGroup : CommandGroup
@@ -289,4 +289,74 @@ public class ToolsCommandGroup : CommandGroup
return await _feedback.SendContextualEmbedResultAsync(embed, ct);
}
+
+ private static readonly TimestampStyle[] AllStyles =
+ {
+ TimestampStyle.ShortDate,
+ TimestampStyle.LongDate,
+ TimestampStyle.ShortTime,
+ TimestampStyle.LongTime,
+ TimestampStyle.ShortDateTime,
+ TimestampStyle.LongDateTime,
+ TimestampStyle.RelativeTime
+ };
+
+ ///
+ /// A slash command that shows the current timestamp with an optional offset in all styles supported by Discord.
+ ///
+ /// The offset for the current timestamp.
+ ///
+ /// A feedback sending result which may or may not have succeeded.
+ ///
+ [Command("timestamp")]
+ [DiscordDefaultDMPermission(false)]
+ [Description("Shows a timestamp in all styles")]
+ [UsedImplicitly]
+ public async Task ExecuteTimestampAsync(
+ [Description("Offset from current time")]
+ TimeSpan? offset = null)
+ {
+ if (!_context.TryGetContextIDs(out var guildId, out _, out var userId))
+ {
+ return new ArgumentInvalidError(nameof(_context), "Unable to retrieve necessary IDs from command context");
+ }
+
+ var userResult = await _userApi.GetUserAsync(userId, CancellationToken);
+ if (!userResult.IsDefined(out var user))
+ {
+ return Result.FromError(userResult);
+ }
+
+ var data = await _guildData.GetData(guildId, CancellationToken);
+ Messages.Culture = GuildSettings.Language.Get(data.Settings);
+
+ return await SendTimestampAsync(offset, user, CancellationToken);
+ }
+
+ private async Task SendTimestampAsync(TimeSpan? offset, IUser user, CancellationToken ct)
+ {
+ var timestamp = DateTimeOffset.UtcNow.Add(offset ?? TimeSpan.Zero).ToUnixTimeSeconds();
+
+ var description = new StringBuilder().Append("# ").AppendLine(timestamp.ToString());
+
+ if (offset is not null)
+ {
+ description.AppendLine(string.Format(
+ Messages.TimestampOffset, Markdown.InlineCode(offset.ToString() ?? string.Empty))).AppendLine();
+ }
+
+ foreach (var markdownTimestamp in AllStyles.Select(style => Markdown.Timestamp(timestamp, style)))
+ {
+ description.Append("- ").Append(Markdown.InlineCode(markdownTimestamp))
+ .Append(" → ").AppendLine(markdownTimestamp);
+ }
+
+ var embed = new EmbedBuilder().WithSmallTitle(
+ string.Format(Messages.TimestampTitle, user.GetTag()), user)
+ .WithDescription(description.ToString())
+ .WithColour(ColorsList.Blue)
+ .Build();
+
+ return await _feedback.SendContextualEmbedResultAsync(embed, ct);
+ }
}
diff --git a/src/Messages.Designer.cs b/src/Messages.Designer.cs
index 3c2c747..549a681 100644
--- a/src/Messages.Designer.cs
+++ b/src/Messages.Designer.cs
@@ -1135,5 +1135,21 @@ namespace Octobot {
return ResourceManager.GetString("RandomOutput", resourceCulture);
}
}
+
+ internal static string TimestampTitle
+ {
+ get
+ {
+ return ResourceManager.GetString("TimestampTitle", resourceCulture);
+ }
+ }
+
+ internal static string TimestampOffset
+ {
+ get
+ {
+ return ResourceManager.GetString("TimestampOffset", resourceCulture);
+ }
+ }
}
}