feat: premium ID changes
Some checks failed
Build and push Docker image / .net docker build (push) Has been cancelled
.net checks / run .net tests (push) Has been cancelled
.net checks / dotnet-format (push) Has been cancelled
Build and push Rust service Docker images / rust docker build (push) Has been cancelled
rust checks / cargo fmt (push) Has been cancelled

This commit is contained in:
Iris System 2025-12-28 00:06:51 +13:00
parent 41f8beb2aa
commit 24b6b0d455
16 changed files with 306 additions and 3 deletions

View file

@ -0,0 +1,34 @@
using Dapper;
using SqlKata;
using NodaTime;
namespace PluralKit.Core;
public partial class ModelRepository
{
public Task<HidChangelog?> GetHidChangelogById(int id)
{
var query = new Query("hid_changelog").Where("id", id);
return _db.QueryFirst<HidChangelog?>(query);
}
public async Task<HidChangelog> CreateHidChangelog(SystemId system, ulong discord_uid, string hid_type, string hid_old, string hid_new, IPKConnection? conn = null)
{
var query = new Query("hid_changelog").AsInsert(new { system, discord_uid, hid_type, hid_old, hid_new, });
var changelog = await _db.QueryFirst<HidChangelog>(conn, query, "returning *");
_logger.Information("Created HidChangelog {HidChangelogId} for system {SystemId}: {HidType} {OldHid} -> {NewHid}", changelog.Id, system, hid_type, hid_old, hid_new);
return changelog;
}
public Task<int> GetHidChangelogCountForDate(SystemId system, LocalDate date)
{
var query = new Query("hid_changelog")
.SelectRaw("count(*)")
.Where("system", system)
.WhereDate("created", date);
return _db.QueryFirst<int>(query);
}
}

View file

@ -1,4 +1,5 @@
using SqlKata;
using Npgsql;
namespace PluralKit.Core;
@ -20,4 +21,27 @@ public partial class ModelRepository
return config;
}
public async Task<bool> TryUpdateSystemConfigForIdChange(SystemId system, IPKConnection conn = null)
{
var query = new Query("system_config")
.AsUpdate(new
{
premium_id_changes_remaining = new UnsafeLiteral("premium_id_changes_remaining - 1")
})
.Where("system", system);
try
{
await _db.ExecuteQuery(conn, query);
}
catch (PostgresException pe)
{
if (!pe.Message.Contains("violates check constraint"))
throw;
return false;
}
return true;
}
}

View file

@ -0,0 +1,15 @@
using Newtonsoft.Json.Linq;
using NodaTime;
namespace PluralKit.Core;
public class HidChangelog
{
public int Id { get; }
public SystemId System { get; }
public ulong DiscordUid { get; }
public string HidType { get; }
public string HidOld { get; }
public string HidNew { get; }
public Instant Created { get; }
}

View file

@ -28,6 +28,7 @@ public class SystemConfigPatch: PatchObject
public Partial<SystemConfig.ProxySwitchAction> ProxySwitch { get; set; }
public Partial<bool> PremiumLifetime { get; set; }
public Partial<Instant?> PremiumUntil { get; set; }
public Partial<int?> PremiumIdChangesRemaining { get; set; }
public override Query Apply(Query q) => q.ApplyPatch(wrapper => wrapper
.With("ui_tz", UiTz)
@ -49,6 +50,7 @@ public class SystemConfigPatch: PatchObject
.With("name_format", NameFormat)
.With("premium_lifetime", PremiumLifetime)
.With("premium_until", PremiumUntil)
.With("premium_id_changes_remaining", PremiumIdChangesRemaining)
);
public new void AssertIsValid()
@ -128,6 +130,9 @@ public class SystemConfigPatch: PatchObject
if (PremiumUntil.IsPresent)
o.Add("premium_until", PremiumUntil.Value?.FormatExport());
if (PremiumIdChangesRemaining.IsPresent)
o.Add("premium_id_changes_remaining", PremiumIdChangesRemaining.Value);
return o;
}

View file

@ -30,6 +30,7 @@ public class SystemConfig
public bool PremiumLifetime { get; }
public Instant? PremiumUntil { get; }
public int? PremiumIdChangesRemaining { get; }
public enum HidPadFormat
{

View file

@ -22,4 +22,6 @@ public static class Limits
public static readonly long AvatarFileSizeLimit = 1024 * 1024;
public static readonly int AvatarDimensionLimit = 1000;
public static readonly int PremiumDailyHidChanges = 3;
}