mirror of
https://github.com/NoiTheCat/WorldTime.git
synced 2024-11-22 06:34:38 +00:00
Add 12-hour time format (implements #2)
This commit is contained in:
parent
7a7bc097e8
commit
09ba9644dc
8 changed files with 184 additions and 15 deletions
|
@ -25,16 +25,20 @@ public class CommandsBase : InteractionModuleBase<ShardedInteractionContext> {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns a string displaying the current time in the given time zone.
|
/// Returns a string displaying the current time in the given time zone.
|
||||||
/// The result begins with four numbers for sorting purposes. Must be trimmed before output.
|
/// The result begins with six numbers for sorting purposes. Must be trimmed before output.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected static string TzPrint(string zone) {
|
protected static string TzPrint(string zone, bool use12hr) {
|
||||||
var tzdb = DateTimeZoneProviders.Tzdb;
|
var tzdb = DateTimeZoneProviders.Tzdb;
|
||||||
DateTimeZone tz = tzdb.GetZoneOrNull(zone)!;
|
DateTimeZone tz = tzdb.GetZoneOrNull(zone)!;
|
||||||
if (tz == null) throw new Exception("Encountered unknown time zone: " + zone);
|
if (tz == null) throw new Exception("Encountered unknown time zone: " + zone);
|
||||||
|
|
||||||
var now = SystemClock.Instance.GetCurrentInstant().InZone(tz);
|
var now = SystemClock.Instance.GetCurrentInstant().InZone(tz);
|
||||||
var sortpfx = now.ToString("MMdd", DateTimeFormatInfo.InvariantInfo);
|
var sortpfx = now.ToString("MMddHH", DateTimeFormatInfo.InvariantInfo);
|
||||||
var fullstr = now.ToString("dd'-'MMM' 'HH':'mm' 'x' (UTC'o<g>')'", DateTimeFormatInfo.InvariantInfo);
|
string fullstr;
|
||||||
|
if (use12hr) {
|
||||||
|
var ap = now.ToString("tt", DateTimeFormatInfo.InvariantInfo).ToLowerInvariant();
|
||||||
|
fullstr = now.ToString($"MMM' 'dd', 'hh':'mm'{ap} 'x' (UTC'o<g>')'", DateTimeFormatInfo.InvariantInfo);
|
||||||
|
} else fullstr = now.ToString("dd'-'MMM', 'HH':'mm' 'x' (UTC'o<g>')'", DateTimeFormatInfo.InvariantInfo);
|
||||||
return $"{sortpfx}● `{fullstr}`";
|
return $"{sortpfx}● `{fullstr}`";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
28
Commands/ConfigCommands.cs
Normal file
28
Commands/ConfigCommands.cs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
using Discord.Interactions;
|
||||||
|
|
||||||
|
namespace WorldTime.Commands;
|
||||||
|
[Group("config", HelpSettings)]
|
||||||
|
public class ConfigCommands : CommandsBase {
|
||||||
|
internal const string HelpSettings = "Configuration commands for World Time.";
|
||||||
|
internal const string HelpUse12 = "Sets whether to use the 12-hour (AM/PM) format in time zone listings.";
|
||||||
|
|
||||||
|
[RequireGuildContext]
|
||||||
|
[SlashCommand("use-12hour", HelpUse12)]
|
||||||
|
public async Task Cmd12Hour([Summary(description: "True to enable, False to disable.")] bool setting) {
|
||||||
|
if (!IsUserAdmin((SocketGuildUser)Context.User)) {
|
||||||
|
await RespondAsync(ErrNotAllowed, ephemeral: true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var db = DbContext;
|
||||||
|
var gs = db.GuildSettings.Where(r => r.GuildId == Context.Guild.Id).SingleOrDefault();
|
||||||
|
if (gs == null) {
|
||||||
|
gs = new() { GuildId = Context.Guild.Id };
|
||||||
|
db.Add(gs);
|
||||||
|
}
|
||||||
|
|
||||||
|
gs.Use12HourTime = setting;
|
||||||
|
await db.SaveChangesAsync();
|
||||||
|
await RespondAsync($":white_check_mark: Time listing set to **{(setting ? "AM/PM" : "24 hour")}** format.");
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,16 @@
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace WorldTime.Commands;
|
namespace WorldTime.Commands;
|
||||||
public class ApplicationCommands : CommandsBase {
|
public class UserCommands : CommandsBase {
|
||||||
const string EmbedHelpField1 = $"`/help` - {HelpHelp}\n"
|
const string EmbedHelpField1 =
|
||||||
|
$"`/help` - {HelpHelp}\n"
|
||||||
+ $"`/list` - {HelpList}\n"
|
+ $"`/list` - {HelpList}\n"
|
||||||
+ $"`/set` - {HelpSet}\n"
|
+ $"`/set` - {HelpSet}\n"
|
||||||
+ $"`/remove` - {HelpRemove}";
|
+ $"`/remove` - {HelpRemove}";
|
||||||
const string EmbedHelpField2 = $"`/set-for` - {HelpSetFor}\n`/remove-for` - {HelpRemoveFor}";
|
const string EmbedHelpField2 =
|
||||||
|
$"`/config use-12hour` - {ConfigCommands.HelpUse12}\n"
|
||||||
|
+ $"`/set-for` - {HelpSetFor}\n"
|
||||||
|
+ $"`/remove-for` - {HelpRemoveFor}";
|
||||||
|
|
||||||
#region Help strings
|
#region Help strings
|
||||||
const string HelpHelp = "Displays a list of available bot commands.";
|
const string HelpHelp = "Displays a list of available bot commands.";
|
||||||
|
@ -67,23 +71,25 @@ public class ApplicationCommands : CommandsBase {
|
||||||
await RespondAsync(":x: Nothing to show. Register your time zones with the bot using the `/set` command.");
|
await RespondAsync(":x: Nothing to show. Register your time zones with the bot using the `/set` command.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Order times by popularity to limit how many are shown, group by printed name
|
// Order times by popularity to limit how many are shown, group by printed name
|
||||||
var sortedlist = new SortedDictionary<string, List<ulong>>();
|
var sortedlist = new SortedDictionary<string, List<ulong>>();
|
||||||
|
var ampm = db.GuildSettings.Where(s => s.GuildId == Context.Guild.Id).SingleOrDefault()?.Use12HourTime ?? false;
|
||||||
foreach ((string area, List<ulong> users) in userlist.OrderByDescending(o => o.Value.Count).Take(20)) {
|
foreach ((string area, List<ulong> users) in userlist.OrderByDescending(o => o.Value.Count).Take(20)) {
|
||||||
// Filter further to top 20 distinct timezones, even if they are not displayed in the final result
|
// Filter further to top 20 distinct timezones, even if they are not displayed in the final result
|
||||||
var areaprint = TzPrint(area);
|
var areaprint = TzPrint(area, ampm);
|
||||||
if (!sortedlist.ContainsKey(areaprint)) sortedlist.Add(areaprint, new List<ulong>());
|
if (!sortedlist.ContainsKey(areaprint)) sortedlist.Add(areaprint, new List<ulong>());
|
||||||
sortedlist[areaprint].AddRange(users);
|
sortedlist[areaprint].AddRange(users);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int MaxSingleLineLength = 750;
|
const int MaxSingleLineLength = 750;
|
||||||
const int MaxSingleOutputLength = 900;
|
const int MaxSingleOutputLength = 3000;
|
||||||
|
|
||||||
// Build zone listings with users
|
// Build zone listings with users
|
||||||
var outputlines = new List<string>();
|
var outputlines = new List<string>();
|
||||||
foreach ((string area, List<ulong> users) in sortedlist) {
|
foreach ((string area, List<ulong> users) in sortedlist) {
|
||||||
var buffer = new StringBuilder();
|
var buffer = new StringBuilder();
|
||||||
buffer.Append(area[4..] + ": ");
|
buffer.Append(area[6..] + ": ");
|
||||||
bool empty = true;
|
bool empty = true;
|
||||||
foreach (var userid in users) {
|
foreach (var userid in users) {
|
||||||
var userinstance = Context.Guild.GetUser(userid);
|
var userinstance = Context.Guild.GetUser(userid);
|
||||||
|
@ -137,7 +143,8 @@ public class ApplicationCommands : CommandsBase {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var resulttext = TzPrint(result)[4..] + ": " + FormatName(parameter);
|
var ampm = db.GuildSettings.Where(s => s.GuildId == Context.Guild.Id).SingleOrDefault()?.Use12HourTime ?? false;
|
||||||
|
var resulttext = TzPrint(result, ampm)[6..] + ": " + FormatName(parameter);
|
||||||
await RespondAsync(embed: new EmbedBuilder().WithDescription(resulttext).Build());
|
await RespondAsync(embed: new EmbedBuilder().WithDescription(resulttext).Build());
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ public class BotDatabaseContext : DbContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
public DbSet<UserEntry> UserEntries { get; set; } = null!;
|
public DbSet<UserEntry> UserEntries { get; set; } = null!;
|
||||||
|
public DbSet<GuildConfiguration> GuildSettings { get; set; } = null!;
|
||||||
|
|
||||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
=> optionsBuilder
|
=> optionsBuilder
|
||||||
|
@ -24,9 +25,8 @@ public class BotDatabaseContext : DbContext {
|
||||||
.UseSnakeCaseNamingConvention();
|
.UseSnakeCaseNamingConvention();
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
protected override void OnModelCreating(ModelBuilder modelBuilder) {
|
||||||
modelBuilder.Entity<UserEntry>(entity => {
|
modelBuilder.Entity<UserEntry>().HasKey(e => new { e.GuildId, e.UserId }).HasName("userdata_pkey");
|
||||||
entity.HasKey(e => new { e.GuildId, e.UserId }).HasName("userdata_pkey");
|
modelBuilder.Entity<GuildConfiguration>().Property(p => p.Use12HourTime).HasDefaultValue(false);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Helper methods / abstractions
|
#region Helper methods / abstractions
|
||||||
|
|
9
Data/GuildConfiguration.cs
Normal file
9
Data/GuildConfiguration.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace WorldTime.Data;
|
||||||
|
public class GuildConfiguration {
|
||||||
|
[Key]
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
|
public bool Use12HourTime { get; set; }
|
||||||
|
}
|
69
Data/Migrations/20230115041447_Add12HrSetting.Designer.cs
generated
Normal file
69
Data/Migrations/20230115041447_Add12HrSetting.Designer.cs
generated
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using WorldTime.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WorldTime.Data.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(BotDatabaseContext))]
|
||||||
|
[Migration("20230115041447_Add12HrSetting")]
|
||||||
|
partial class Add12HrSetting
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "7.0.1")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorldTime.Data.GuildConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("GuildId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("guild_id");
|
||||||
|
|
||||||
|
b.Property<bool>("Use12HourTime")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("use12hour_time");
|
||||||
|
|
||||||
|
b.HasKey("GuildId")
|
||||||
|
.HasName("pk_guild_settings");
|
||||||
|
|
||||||
|
b.ToTable("guild_settings", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorldTime.Data.UserEntry", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("GuildId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("guild_id");
|
||||||
|
|
||||||
|
b.Property<long>("UserId")
|
||||||
|
.HasColumnType("bigint")
|
||||||
|
.HasColumnName("user_id");
|
||||||
|
|
||||||
|
b.Property<string>("TimeZone")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text")
|
||||||
|
.HasColumnName("zone");
|
||||||
|
|
||||||
|
b.HasKey("GuildId", "UserId")
|
||||||
|
.HasName("userdata_pkey");
|
||||||
|
|
||||||
|
b.ToTable("userdata", (string)null);
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
33
Data/Migrations/20230115041447_Add12HrSetting.cs
Normal file
33
Data/Migrations/20230115041447_Add12HrSetting.cs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace WorldTime.Data.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Add12HrSetting : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "guild_settings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
guildid = table.Column<decimal>(name: "guild_id", type: "numeric(20,0)", nullable: false),
|
||||||
|
use12hourtime = table.Column<bool>(name: "use12hour_time", type: "boolean", nullable: false, defaultValue: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("pk_guild_settings", x => x.guildid);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "guild_settings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,11 +16,30 @@ namespace WorldTime.Data.Migrations
|
||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "6.0.6")
|
.HasAnnotation("ProductVersion", "7.0.1")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("WorldTime.Data.GuildConfiguration", b =>
|
||||||
|
{
|
||||||
|
b.Property<decimal>("GuildId")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("numeric(20,0)")
|
||||||
|
.HasColumnName("guild_id");
|
||||||
|
|
||||||
|
b.Property<bool>("Use12HourTime")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("boolean")
|
||||||
|
.HasDefaultValue(false)
|
||||||
|
.HasColumnName("use12hour_time");
|
||||||
|
|
||||||
|
b.HasKey("GuildId")
|
||||||
|
.HasName("pk_guild_settings");
|
||||||
|
|
||||||
|
b.ToTable("guild_settings", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("WorldTime.Data.UserEntry", b =>
|
modelBuilder.Entity("WorldTime.Data.UserEntry", b =>
|
||||||
{
|
{
|
||||||
b.Property<long>("GuildId")
|
b.Property<long>("GuildId")
|
||||||
|
|
Loading…
Reference in a new issue