Added .shopadd cmd

This commit is contained in:
Kwoth
2024-04-23 14:18:30 +00:00
parent 1aebca14e1
commit 74690c73d6
22 changed files with 18474 additions and 6275 deletions

View File

@@ -2,6 +2,14 @@
Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.0/) except date format. a-c-f-r-o
## [5.0.0]
### Added
- `.shopadd command` You can now sell commands in the shop. The command will execute as if you were the one running it when someone buys it
- type `.h .shopadd` for more info
-
## [4.3.22] - 23.04.2023
### Added

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.203.0" />
<PackageReference Include="Discord.Net" Version="3.204.0" />
</ItemGroup>
<ItemGroup>

View File

@@ -5,8 +5,8 @@ public enum ShopEntryType
{
Role,
List
//Infinite_List,
List,
Command
}
public class ShopEntry : DbEntity, IIndexed
@@ -25,6 +25,9 @@ public class ShopEntry : DbEntity, IIndexed
//list
public HashSet<ShopEntryItem> Items { get; set; } = new();
public ulong? RoleRequirement { get; set; }
// command
public string Command { get; set; }
}
public class ShopEntryItem : DbEntity

View File

@@ -7,7 +7,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.203.0" />
<PackageReference Include="Discord.Net" Version="3.204.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
</ItemGroup>

View File

@@ -4,6 +4,7 @@ using Nadeko.Bot.Db.Models;
using System.Collections.Immutable;
using LinqToDB;
using LinqToDB.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using NadekoBot.Db.Models;
namespace NadekoBot.Modules.Administration.Services;

View File

@@ -14,7 +14,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="3.203.0" />
<PackageReference Include="Discord.Net" Version="3.204.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
</ItemGroup>

View File

@@ -1,4 +1,6 @@
#nullable disable
using Nadeko.Bot.Db.Models;
namespace NadekoBot.Modules.Gambling.Services;
public interface IShopService
@@ -40,4 +42,5 @@ public interface IShopService
Task<bool> MoveEntryAsync(ulong guildId, int fromIndex, int toIndex);
Task<bool> SetItemRoleRequirementAsync(ulong guildId, int index, ulong? roleId);
Task<ShopEntry> AddShopCommandAsync(ulong guildId, ulong userId, int price, string command);
}

View File

@@ -4,6 +4,7 @@ using NadekoBot.Db;
using NadekoBot.Modules.Gambling.Common;
using NadekoBot.Modules.Gambling.Services;
using Nadeko.Bot.Db.Models;
using NadekoBot.Modules.Administration;
namespace NadekoBot.Modules.Gambling;
@@ -22,6 +23,12 @@ public partial class Gambling
Role
}
public enum Command
{
Command,
Cmd
}
private readonly DbService _db;
private readonly ICurrencyService _cs;
@@ -156,7 +163,7 @@ public partial class Gambling
return;
}
if (entry.Type == ShopEntryType.List)
else if (entry.Type == ShopEntryType.List)
{
if (entry.Items.Count == 0)
{
@@ -213,11 +220,79 @@ public partial class Gambling
else
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
}
else if (entry.Type == ShopEntryType.Command)
{
var guild = ctx.Guild as SocketGuild;
var channel = ctx.Channel as ISocketMessageChannel;
var msg = ctx.Message as SocketUserMessage;
var user = await ctx.Guild.GetUserAsync(entry.AuthorId);
if (guild is null || channel is null || msg is null || user is null)
{
await ReplyErrorLocalizedAsync(strs.shop_command_invalid_context);
return;
}
if (!await _cs.RemoveAsync(ctx.User.Id, entry.Price, new("shop", "buy", entry.Type.ToString())))
{
await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign));
return;
}
else
{
var cmd = entry.Command.Replace("%you%", ctx.User.Id.ToString());
var eb = _eb.Create()
.WithPendingColor()
.WithTitle("Executing shop command")
.WithDescription(cmd);
var msgTask = ctx.Channel.EmbedAsync(eb);
await _cs.AddAsync(entry.AuthorId,
GetProfitAmount(entry.Price),
new("shop", "sell", entry.Name));
await _cmdHandler.TryRunCommand(guild,
channel,
new DoAsUserMessage(
msg,
user,
cmd
));
try
{
var pendingMsg = await msgTask;
await pendingMsg.EditAsync(SmartEmbedText.FromEmbed(eb
.WithOkColor()
.WithTitle("Shop command executed")
.Build()));
}
catch
{
}
}
}
}
private static long GetProfitAmount(int price)
=> (int)Math.Ceiling(0.90 * price);
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
[BotPerm(GuildPerm.ManageRoles)]
public async Task ShopAdd(Command _, int price, [Leftover] string command)
{
if (price < 1)
return;
var entry = await _service.AddShopCommandAsync(ctx.Guild.Id, ctx.User.Id, price, command);
await ctx.Channel.EmbedAsync(EntryToEmbed(entry).WithTitle(GetText(strs.shop_item_add)));
}
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
@@ -471,6 +546,14 @@ public partial class Gambling
.AddField(GetText(strs.type), GetText(strs.random_unique_item), true);
}
else if (entry.Type == ShopEntryType.Command)
{
return embed
.AddField(GetText(strs.name), Format.Code(entry.Command), true)
.AddField(GetText(strs.price), N(entry.Price), true)
.AddField(GetText(strs.type), entry.Type.ToString(), true);
}
//else if (entry.Type == ShopEntryType.Infinite_List)
// return embed.AddField(GetText(strs.name), GetText(strs.shop_role(Format.Bold(entry.RoleName)), true))
// .AddField(GetText(strs.price), entry.Price.ToString(), true)
@@ -490,6 +573,9 @@ public partial class Gambling
+ GetText(strs.shop_role(Format.Bold(ctx.Guild.GetRole(entry.RoleId)?.Name ?? "MISSING_ROLE")));
if (entry.Type == ShopEntryType.List)
return prepend + GetText(strs.unique_items_left(entry.Items.Count)) + "\n" + entry.Name;
if (entry.Type == ShopEntryType.Command)
return prepend + Format.Code(entry.Command);
return prepend;
}
}

View File

@@ -1,7 +1,6 @@
#nullable disable
using Microsoft.EntityFrameworkCore;
using NadekoBot.Db;
using Nadeko.Bot.Db.Models;
namespace NadekoBot.Modules.Gambling.Services;
@@ -14,7 +13,9 @@ public class ShopService : IShopService, INService
=> _db = db;
private IndexedCollection<ShopEntry> GetEntriesInternal(DbContext uow, ulong guildId)
=> uow.GuildConfigsForId(guildId, set => set.Include(x => x.ShopEntries).ThenInclude(x => x.Items))
=> uow.GuildConfigsForId(guildId,
set => set.Include(x => x.ShopEntries)
.ThenInclude(x => x.Items))
.ShopEntries.ToIndexed();
public async Task<bool> ChangeEntryPriceAsync(ulong guildId, int index, int newPrice)
@@ -109,4 +110,24 @@ public class ShopService : IShopService, INService
await uow.SaveChangesAsync();
return true;
}
public async Task<ShopEntry> AddShopCommandAsync(ulong guildId, ulong userId, int price, string command)
{
await using var uow = _db.GetDbContext();
var entries = GetEntriesInternal(uow, guildId);
var entry = new ShopEntry()
{
AuthorId = userId,
Command = command,
Type = ShopEntryType.Command,
Price = price,
};
entries.Add(entry);
uow.GuildConfigsForId(guildId, set => set).ShopEntries = entries;
await uow.SaveChangesAsync();
return entry;
}
}

View File

@@ -14,7 +14,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Discord.Net.Core" Version="3.203.0" />
<PackageReference Include="Discord.Net.Core" Version="3.204.0" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,5 @@
#nullable disable
using Nadeko.Bot.Db.Models;
using NadekoBot.Db.Models;
namespace NadekoBot.Services.Database.Models;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.Db.Migrations
{
/// <inheritdoc />
public partial class shopcommands : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "command",
table: "shopentry",
type: "text",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "command",
table: "shopentry");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,28 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.Db.Migrations.Sqlite
{
/// <inheritdoc />
public partial class shopcommands : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Command",
table: "ShopEntry",
type: "TEXT",
nullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Command",
table: "ShopEntry");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1751,9 +1751,14 @@ shop:
- ""
- "2"
shopadd:
desc: "Adds an item to the shop by specifying type price and name. Available types are role and list. 90% of currency from each purchase will be received by the user who added the item to the shop."
desc: |-
- Available types are role, list and command.
- If the item is a role, specify a role id or a role name.
- If the item is a command, specify the full command, replacing the user with %user% (for a mention) or %user.id% for user id.
90% of currency from each purchase will be received by the user who added the item to the shop.
args:
- "role 1000 Rich"
- "cmd 1000 .setrole %user% Rich"
shopremove:
desc: "Removes an item from the shop by its ID."
args:

View File

@@ -710,6 +710,7 @@
"shop_item_add": "Shop item added",
"shop_none": "No shop items found on this page.",
"shop_role": "You will get {0} role.",
"shop_command_invalid_context": "Unable to retrieve user, channel or server in order to execute the command.",
"type": "Type",
"gvc_disabled": "Game Voice Channel feature has been disabled on this server.",
"gvc_enabled": "{0} is a Game Voice Channel now.",