diff --git a/src/NadekoBot/Modules/Xp/Xp.cs b/src/NadekoBot/Modules/Xp/Xp.cs index 7b3a001b5..618cca551 100644 --- a/src/NadekoBot/Modules/Xp/Xp.cs +++ b/src/NadekoBot/Modules/Xp/Xp.cs @@ -334,14 +334,15 @@ public partial class Xp : NadekoModule public enum XpShopInputType { - F = 0, - Frs = 0, - Fs = 0, - Frames = 0, + Backgrounds = 1, B = 1, Bg = 1, Bgs = 1, - Backgrounds = 1 + Frames = 0, + F = 0, + Fr = 0, + Frs = 0, + Fs = 0, } [Cmd] @@ -352,9 +353,12 @@ public partial class Xp : NadekoModule await ReplyErrorLocalizedAsync(strs.xp_shop_disabled); return; } - - await SendConfirmAsync(GetText(strs.available_commands), $@"`{prefix}xpshop bgs` -`{prefix}xpshop frames`"); + + await SendConfirmAsync(GetText(strs.available_commands), + $@"`{prefix}xpshop bgs` +`{prefix}xpshop frames` + +*{GetText(strs.xpshop_website)}*"); } [Cmd] @@ -394,15 +398,18 @@ public partial class Xp : NadekoModule .WithOkColor() .WithTitle(item.Name) .AddField(GetText(strs.price), Gambling.Gambling.N(item.Price, culture), true) - // .AddField(GetText(strs.buy), $"{prefix}xpbuy {key}", true) .WithImageUrl(string.IsNullOrWhiteSpace(item.Preview) ? item.Url : item.Preview); if (!string.IsNullOrWhiteSpace(item.Desc)) - eb.WithDescription(item.Desc); + eb.AddField(GetText(strs.desc), item.Desc); - var tier = _service.GetXpShopTierRequirement(); + if (key == "default") + eb.WithDescription(GetText(strs.xpshop_website)); + + + var tier = _service.GetXpShopTierRequirement(type); if (tier != PatronTier.None) { eb.WithFooter(GetText(strs.xp_shop_buy_required_tier(tier.ToString()))); @@ -456,6 +463,42 @@ public partial class Xp : NadekoModule 1, addPaginatedFooter: false); } + + [Cmd] + public async Task XpShopBuy(XpShopInputType type, string key) + { + var result = await _service.BuyShopItemAsync(ctx.User.Id, (XpShopItemType)type, key); + + if (result != BuyResult.Success) + { + var _ = result switch + { + BuyResult.InsufficientFunds => await ReplyErrorLocalizedAsync(strs.not_enough(_gss.Data.Currency.Sign)), + BuyResult.AlreadyOwned => await ReplyErrorLocalizedAsync(strs.xpshop_already_owned), + BuyResult.UnknownItem => await ReplyErrorLocalizedAsync(strs.xpshop_item_not_found), + BuyResult.InsufficientPatronTier => await ReplyErrorLocalizedAsync(strs.patron_insuff_tier), + _ => throw new ArgumentOutOfRangeException() + }; + return; + } + + await ReplyConfirmLocalizedAsync(strs.xpshop_buy_success(type.ToString().ToLowerInvariant(), + key.ToLowerInvariant())); + } + + [Cmd] + public async Task XpShopUse(XpShopInputType type, string key) + { + var result = await _service.UseShopItemAsync(ctx.User.Id, (XpShopItemType)type, key); + + if (!result) + { + await ReplyConfirmLocalizedAsync(strs.xp_shop_item_cant_use); + return; + } + + await ctx.OkAsync(); + } private async Task OnShopUse(SocketMessageComponent smc, (string? key, XpShopItemType type)? maybeState) { diff --git a/src/NadekoBot/Modules/Xp/XpConfig.cs b/src/NadekoBot/Modules/Xp/XpConfig.cs index b9a1ba2a1..7f4dd7223 100644 --- a/src/NadekoBot/Modules/Xp/XpConfig.cs +++ b/src/NadekoBot/Modules/Xp/XpConfig.cs @@ -10,7 +10,7 @@ namespace NadekoBot.Modules.Xp; public sealed partial class XpConfig : ICloneable { [Comment(@"DO NOT CHANGE")] - public int Version { get; set; } = 4; + public int Version { get; set; } = 5; [Comment(@"How much XP will the users receive per message")] public int XpPerMessage { get; set; } = 3; @@ -37,9 +37,13 @@ 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 command + [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")] - public PatronTier TierRequirement { get; set; } = PatronTier.None; + 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")] + 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) diff --git a/src/NadekoBot/Modules/Xp/XpConfigService.cs b/src/NadekoBot/Modules/Xp/XpConfigService.cs index c420b4ccb..b17b30fe0 100644 --- a/src/NadekoBot/Modules/Xp/XpConfigService.cs +++ b/src/NadekoBot/Modules/Xp/XpConfigService.cs @@ -52,11 +52,11 @@ public sealed class XpConfigService : ConfigServiceBase }); } - if (data.Version < 4) + if (data.Version < 5) { ModifyConfig(c => { - c.Version = 4; + c.Version = 5; }); } } diff --git a/src/NadekoBot/Modules/Xp/XpService.cs b/src/NadekoBot/Modules/Xp/XpService.cs index 4fa126a62..c644f4b92 100644 --- a/src/NadekoBot/Modules/Xp/XpService.cs +++ b/src/NadekoBot/Modules/Xp/XpService.cs @@ -1351,11 +1351,15 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand if (!conf.Shop.IsEnabled) return BuyResult.UnknownItem; - if (conf.Shop.TierRequirement != PatronTier.None && !_creds.IsOwner(userId)) + var req = type == XpShopItemType.Background + ? conf.Shop.BgsTierRequirement + : conf.Shop.FramesTierRequirement; + + if (req != PatronTier.None && !_creds.IsOwner(userId)) { var patron = await _ps.GetPatronAsync(userId); - if ((int)patron.Tier < (int)conf.Shop.TierRequirement) + if ((int)patron.Tier < (int)req) return BuyResult.InsufficientPatronTier; } @@ -1482,8 +1486,12 @@ public class XpService : INService, IReadyExecutor, IExecNoCommand return false; } - public PatronTier GetXpShopTierRequirement() - => _xpConfig.Data.Shop.TierRequirement; + public PatronTier GetXpShopTierRequirement(Xp.XpShopInputType type) + => type switch + { + Xp.XpShopInputType.F => _xpConfig.Data.Shop.FramesTierRequirement, + _ => _xpConfig.Data.Shop.BgsTierRequirement, + }; public bool IsShopEnabled() => _xpConfig.Data.Shop.IsEnabled; diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index 3df0ef602..8c2d94561 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -1064,6 +1064,10 @@ xpadd: - xpadd xpshop: - xpshop +xpshopbuy: + - xpshopbuy +xpshopuse: + - xpshopuse clubcreate: - clubcreate clubtransfer: diff --git a/src/NadekoBot/data/images/frame_silver.png b/src/NadekoBot/data/images/frame_silver.png index 25fc31f65..4dcda7562 100644 Binary files a/src/NadekoBot/data/images/frame_silver.png and b/src/NadekoBot/data/images/frame_silver.png differ diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index 61d253615..86e5298ec 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -2128,6 +2128,16 @@ xpshop: - "bgs" - "frames" - "bgs 3" +xpshopbuy: + desc: "Buy an item from the xp shop by specifying the type and the key of the item." + args: + - "bg open_sea" + - "fr gold" +xpshopuse: + desc: "Use a previously purchased item from the xp shop by specifying the type and the key of the item." + args: + - "bg synth" + - "fr default" bible: desc: "Shows bible verse. You need to supply book name and chapter:verse" args: diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index e7b0a78f0..3e306c022 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -1003,7 +1003,7 @@ "feature_limit_reached_you": "You've reached the limit of {0} for the {1} feature. You may be able to increase this limit by upgrading your patron tier.", "feature_limit_reached_owner": "Server owner has reached the limit of {0} for the {1} feature. Server owner may be able to upgrade this limit by upgrading patron tier.", "feature_limit_reached_either": "The limit of {0} for the {1} feature has been reached. Either you or the server owner may able to upgrade this limit by upgrading the patron tier.", - "xp_shop_buy_required_tier": "Buying items from the shop requires Patron Tier {0} or higher.", + "xp_shop_buy_required_tier": "Buying items from this shop requires Patron Tier {0} or higher.", "available_commands": "Available Commands", "tier": "Tier", "pledge": "Pledge", @@ -1017,5 +1017,10 @@ "patron_not_enabled": "Patron system is disabled.", "results_in": "{0} results in {1}s", "patron_msg_sent": "Done sending messages to patrons at and above tier {1}. {1} successfully sent and {2} failed.", - "xpadd_users": "Added {0} server XP to {1} users." + "xpadd_users": "Added {0} server XP to {1} users.", + "xpshop_buy_success": "Successfully purchased `{0}/{1}`", + "patron_insuff_tier": "Your Patron Tier insufficient to perform this action.", + "xpshop_already_owned": "You already own this item.", + "xpshop_item_not_found": "An item with that key doesn't exist.", + "xpshop_website": "You can see the list of all Xp Shop items here: " } diff --git a/src/NadekoBot/data/xp.yml b/src/NadekoBot/data/xp.yml index 0c9a16c8c..cdd5ef6b1 100644 --- a/src/NadekoBot/data/xp.yml +++ b/src/NadekoBot/data/xp.yml @@ -1,5 +1,5 @@ # DO NOT CHANGE -version: 4 +version: 5 # How much XP will the users receive per message xpPerMessage: 3 # How often can the users receive XP in minutes @@ -16,9 +16,12 @@ shop: # True -> Users can access the xp shop using .xpshop command # False -> Users can't access the xp shop isEnabled: false - # Which patron tier do users need in order to use the .xpshop command + # 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 - tierRequirement: None + bgsTierRequirement: None + # 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 + framesTierRequirement: None # 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.