finalized rewritten xp loop, updated xp.yml

This commit is contained in:
Toastie 2025-02-08 16:33:05 +13:00
parent dbc312dd9d
commit 06970eb9d3
Signed by: toastie_t0ast
GPG key ID: 0861BE54AD481DC7
15 changed files with 487 additions and 526 deletions

View file

@ -0,0 +1,14 @@
#nullable disable warnings
using System.ComponentModel.DataAnnotations;
namespace EllieBot.Modules.Xp.Services;
public sealed class UserXpBatch
{
[Key]
public ulong UserId { get; set; }
public ulong GuildId { get; set; }
public string Username { get; set; } = string.Empty;
public string AvatarId { get; set; } = string.Empty;
}

View file

@ -31,11 +31,13 @@ public partial class Xp : EllieModule<XpService>
private readonly DownloadTracker _tracker;
private readonly ICurrencyProvider _gss;
private readonly XpTemplateService _templateService;
public Xp(DownloadTracker tracker, ICurrencyProvider gss)
public Xp(DownloadTracker tracker, ICurrencyProvider gss, XpTemplateService templateService)
{
_tracker = tracker;
_gss = gss;
_templateService = templateService;
}
[Cmd]
@ -325,7 +327,7 @@ public partial class Xp : EllieModule<XpService>
[OwnerOnly]
public async Task XpTemplateReload()
{
_service.ReloadXpTemplate();
_templateService.ReloadXpTemplate();
await Task.Delay(1000);
await Response().Confirm(strs.template_reloaded).SendAsync();
}

View file

@ -10,25 +10,19 @@ namespace EllieBot.Modules.Xp;
public sealed partial class XpConfig : ICloneable<XpConfig>
{
[Comment("""DO NOT CHANGE""")]
public int Version { get; set; } = 7;
public int Version { get; set; } = 10;
[Comment("""How much XP will the users receive per message""")]
public int XpPerMessage { get; set; } = 3;
public int TextXpPerMessage { get; set; } = 3;
[Comment("""How often can the users receive XP, in seconds""")]
public float MessageXpCooldown { get; set; } = 300;
public int TextXpCooldown { get; set; } = 300;
[Comment("""Amount of xp users gain from posting an image""")]
public int XpFromImage { get; set; } = 0;
public int TextXpFromImage { get; set; } = 3;
[Comment("""Average amount of xp earned per minute in VC""")]
public double VoiceXpPerMinute { get; set; } = 0;
[Comment("""The maximum amount of minutes the bot will keep track of a user in a voice channel""")]
public int VoiceMaxMinutes { get; set; } = 720;
[Comment("""The amount of currency users will receive for each point of global xp that they earn""")]
public float CurrencyPerXp { get; set; } = 0;
public int VoiceXpPerMinute { get; set; } = 3;
[Comment("""Xp Shop config""")]
public ShopConfig Shop { get; set; } = new();
@ -36,44 +30,44 @@ public sealed partial class XpConfig : ICloneable<XpConfig>
public sealed class ShopConfig
{
[Comment("""
Whether the xp shop is enabled
True -> Users can access the xp shop using .xpshop command
False -> Users can't access the xp shop
""")]
Whether the xp shop is enabled
True -> Users can access the xp shop using .xpshop command
False -> Users can't access the xp shop
""")]
public bool IsEnabled { get; set; } = false;
[Comment("""
Which patron tier do users need in order to use the .xpshop bgs command
Leave at 'None' if patron system is disabled or you don't want any restrictions
""")]
Which patron tier do users need in order to use the .xpshop bgs command
Leave at 'None' if patron system is disabled or you don't want any restrictions
""")]
public PatronTier BgsTierRequirement { get; set; } = PatronTier.None;
[Comment("""
Which patron tier do users need in order to use the .xpshop frames command
Leave at 'None' if patron system is disabled or you don't want any restrictions
""")]
Which patron tier do users need in order to use the .xpshop frames command
Leave at 'None' if patron system is disabled or you don't want any restrictions
""")]
public PatronTier FramesTierRequirement { get; set; } = PatronTier.None;
[Comment("""
Frames available for sale. Keys are unique IDs.
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
Removing a key which previously existed means that all previous purchases will also be unusable.
To remove an item from the shop, but keep previous purchases, set the price to -1
""")]
Frames available for sale. Keys are unique IDs.
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
Removing a key which previously existed means that all previous purchases will also be unusable.
To remove an item from the shop, but keep previous purchases, set the price to -1
""")]
public Dictionary<string, ShopItemInfo>? Frames { get; set; } = new()
{
{"default", new() {Name = "No frame", Price = 0, Url = string.Empty}}
{ "default", new() { Name = "No frame", Price = 0, Url = string.Empty } }
};
[Comment("""
Backgrounds available for sale. Keys are unique IDs.
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
Removing a key which previously existed means that all previous purchases will also be unusable.
To remove an item from the shop, but keep previous purchases, set the price to -1
""")]
Backgrounds available for sale. Keys are unique IDs.
Do not change keys as they are not publicly visible. Only change properties (name, price, id)
Removing a key which previously existed means that all previous purchases will also be unusable.
To remove an item from the shop, but keep previous purchases, set the price to -1
""")]
public Dictionary<string, ShopItemInfo>? Bgs { get; set; } = new()
{
{"default", new() {Name = "Default Background", Price = 0, Url = string.Empty}}
{ "default", new() { Name = "Default Background", Price = 0, Url = string.Empty } }
};
}
@ -81,16 +75,17 @@ public sealed partial class XpConfig : ICloneable<XpConfig>
{
[Comment("""Visible name of the item""")]
public string Name { get; set; }
[Comment("""Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase""")]
[Comment(
"""Price of the item. Set to -1 if you no longer want to sell the item but want the users to be able to keep their old purchase""")]
public int Price { get; set; }
[Comment("""Direct url to the .png image which will be applied to the user's XP card""")]
public string Url { get; set; }
[Comment("""Optional preview url which will show instead of the real URL in the shop """)]
public string Preview { get; set; }
[Comment("""Optional description of the item""")]
public string Desc { get; set; }
}

View file

@ -15,24 +15,29 @@ public sealed class XpConfigService : ConfigServiceBase<XpConfig>
: base(FILE_PATH, serializer, pubSub, _changeKey)
{
AddParsedProp("txt.cooldown",
conf => conf.MessageXpCooldown,
float.TryParse,
conf => conf.TextXpCooldown,
int.TryParse,
(f) => f.ToString("F2"),
x => x > 0);
AddParsedProp("txt.per_msg", conf => conf.XpPerMessage, int.TryParse, ConfigPrinters.ToString, x => x >= 0);
AddParsedProp("txt.per_image", conf => conf.XpFromImage, int.TryParse, ConfigPrinters.ToString, x => x > 0);
AddParsedProp("voice.per_minute",
conf => conf.VoiceXpPerMinute,
double.TryParse,
AddParsedProp("txt.permsg",
conf => conf.TextXpPerMessage,
int.TryParse,
ConfigPrinters.ToString,
x => x >= 0);
AddParsedProp("voice.max_minutes",
conf => conf.VoiceMaxMinutes,
AddParsedProp("txt.perimage",
conf => conf.TextXpFromImage,
int.TryParse,
ConfigPrinters.ToString,
x => x > 0);
AddParsedProp("voice.perminute",
conf => conf.VoiceXpPerMinute,
int.TryParse,
ConfigPrinters.ToString,
x => x >= 0);
AddParsedProp("shop.is_enabled",
conf => conf.Shop.IsEnabled,
bool.TryParse,
@ -43,21 +48,11 @@ public sealed class XpConfigService : ConfigServiceBase<XpConfig>
private void Migrate()
{
if (data.Version < 2)
if (data.Version < 10)
{
ModifyConfig(c =>
{
c.Version = 2;
c.XpFromImage = 0;
});
}
if (data.Version < 7)
{
ModifyConfig(c =>
{
c.Version = 7;
c.MessageXpCooldown *= 60;
c.Version = 10;
});
}
}

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,8 @@ namespace EllieBot.Modules.Xp;
public class XpTemplate
{
public int Version { get; set; } = 0;
public int Version { get; set; } = 2;
[JsonProperty("output_size")]
public XpTemplatePos OutputSize { get; set; } = new()
{

View file

@ -217,7 +217,7 @@ public class XpSvc : GrpcXp.GrpcXpBase, IGrpcSvc, IEService
throw new RpcException(new Status(StatusCode.NotFound, "Guild not found"));
var data = await _xp.GetGuildUserXps(request.GuildId, request.Page - 1);
var total = await _xp.GetTotalGuildUsers(request.GuildId);
var total = await _xp.GetGuildXpUsersCountAsync(request.GuildId);
var reply = new GetXpLbReply
{

View file

@ -9,12 +9,12 @@ namespace Ellie.Common;
public sealed class MemoryBotCache : IBotCache
{
// needed for overwrites and Delete return value
private readonly object _cacheLock = new object();
private readonly ConcurrentDictionary<string, object> _locks = new();
private readonly MemoryCache _cache;
public MemoryBotCache()
{
_cache = new MemoryCache(new MemoryCacheOptions());
_cache = new(new MemoryCacheOptions());
}
public ValueTask<bool> AddAsync<T>(TypedKey<T> key, T value, TimeSpan? expiry = null, bool overwrite = true)
@ -26,12 +26,14 @@ public sealed class MemoryBotCache : IBotCache
item.AbsoluteExpirationRelativeToNow = expiry;
return new(true);
}
lock (_cacheLock)
var cacheLock = _locks.GetOrAdd(key.Key, static _ => new());
lock (cacheLock)
{
if (_cache.TryGetValue(key.Key, out var old) && old is not null)
return new(false);
using var item = _cache.CreateEntry(key.Key);
item.Value = value;
item.AbsoluteExpirationRelativeToNow = expiry;
@ -61,9 +63,10 @@ public sealed class MemoryBotCache : IBotCache
public ValueTask<bool> RemoveAsync<T>(TypedKey<T> key)
{
lock (_cacheLock)
var cacheLock = _locks.GetOrAdd(key.Key, static _ => new());
lock (cacheLock)
{
var toReturn = _cache.TryGetValue(key.Key, out var old ) && old is not null;
var toReturn = _cache.TryGetValue(key.Key, out var old) && old is not null;
_cache.Remove(key.Key);
return new(toReturn);
}

View file

@ -1,17 +1,13 @@
# DO NOT CHANGE
version: 7
version: 10
# How much XP will the users receive per message
xpPerMessage: 3
textXpPerMessage: 3
# How often can the users receive XP, in seconds
messageXpCooldown: 300
textXpCooldown: 300
# Amount of xp users gain from posting an image
xpFromImage: 0
textXpFromImage: 3
# Average amount of xp earned per minute in VC
voiceXpPerMinute: 0
# The maximum amount of minutes the bot will keep track of a user in a voice channel
voiceMaxMinutes: 720
# The amount of currency users will receive for each point of global xp that they earn
currencyPerXp: 0
# Xp Shop config
shop:
# Whether the xp shop is enabled

View file

@ -1,5 +1,5 @@
{
"Version": 1,
"Version": 2,
"output_size": {
"X": 800,
"Y": 392