gambling commands now show amount bet. Slightly changed the layout. Updated some gambling strings

added .btr excl
This commit is contained in:
Toastie 2024-11-28 19:12:37 +13:00
parent 97871f3e47
commit ae338db294
Signed by: toastie_t0ast
GPG key ID: 27F3B6855AFD40A4
18 changed files with 178 additions and 74 deletions

View file

@ -12,6 +12,7 @@ Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except da
- `.btr list` to list all button roles on the server
- `.btr rm` to remove a button role from the specified message
- `.btr rma` to remove all button roles on the specified message
- `.btr excl` to toggle exclusive button roles (only 1 role per message or any number)
- Use `.h` on any of the above for more info
- Added `.wrongsong` which will delete the last queued song.
- Useful in case you made a mistake, or the bot queued a wrong song

View file

@ -22,4 +22,6 @@ public sealed class ButtonRole
[MaxLength(50)]
public string Label { get; set; } = string.Empty;
public bool Exclusive { get; set; }
}

View file

@ -12,8 +12,8 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace EllieBot.Migrations.PostgreSql
{
[DbContext(typeof(PostgreSqlContext))]
[Migration("20241127120348_guildcolors")]
partial class guildcolors
[Migration("20241126033634_btnroles_guildcolors")]
partial class btnroles_guildcolors
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -479,6 +479,10 @@ namespace EllieBot.Migrations.PostgreSql
.HasColumnType("character varying(100)")
.HasColumnName("emote");
b.Property<bool>("Exclusive")
.HasColumnType("boolean")
.HasColumnName("exclusive");
b.Property<decimal>("GuildId")
.HasColumnType("numeric(20,0)")
.HasColumnName("guildid");

View file

@ -6,7 +6,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
namespace EllieBot.Migrations.PostgreSql
{
/// <inheritdoc />
public partial class guildcolors : Migration
public partial class btnroles_guildcolors : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -24,7 +24,8 @@ namespace EllieBot.Migrations.PostgreSql
position = table.Column<int>(type: "integer", nullable: false),
roleid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
emote = table.Column<string>(type: "character varying(100)", maxLength: 100, nullable: false),
label = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false)
label = table.Column<string>(type: "character varying(50)", maxLength: 50, nullable: false),
exclusive = table.Column<bool>(type: "boolean", nullable: false)
},
constraints: table =>
{

View file

@ -476,6 +476,10 @@ namespace EllieBot.Migrations.PostgreSql
.HasColumnType("character varying(100)")
.HasColumnName("emote");
b.Property<bool>("Exclusive")
.HasColumnType("boolean")
.HasColumnName("exclusive");
b.Property<decimal>("GuildId")
.HasColumnType("numeric(20,0)")
.HasColumnName("guildid");

View file

@ -11,8 +11,8 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace EllieBot.Migrations
{
[DbContext(typeof(SqliteContext))]
[Migration("20241127120303_guildcolors")]
partial class guildcolors
[Migration("20241126033626_btnroles_guildcolors")]
partial class btnroles_guildcolors
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
@ -357,6 +357,9 @@ namespace EllieBot.Migrations
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<bool>("Exclusive")
.HasColumnType("INTEGER");
b.Property<ulong>("GuildId")
.HasColumnType("INTEGER");

View file

@ -5,7 +5,7 @@
namespace EllieBot.Migrations
{
/// <inheritdoc />
public partial class guildcolors : Migration
public partial class btnroles_guildcolors : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
@ -23,7 +23,8 @@ namespace EllieBot.Migrations
Position = table.Column<int>(type: "INTEGER", nullable: false),
RoleId = table.Column<ulong>(type: "INTEGER", nullable: false),
Emote = table.Column<string>(type: "TEXT", maxLength: 100, nullable: false),
Label = table.Column<string>(type: "TEXT", maxLength: 50, nullable: false)
Label = table.Column<string>(type: "TEXT", maxLength: 50, nullable: false),
Exclusive = table.Column<bool>(type: "INTEGER", nullable: false)
},
constraints: table =>
{

View file

@ -354,6 +354,9 @@ namespace EllieBot.Migrations
.HasMaxLength(100)
.HasColumnType("TEXT");
b.Property<bool>("Exclusive")
.HasColumnType("INTEGER");
b.Property<ulong>("GuildId")
.HasColumnType("INTEGER");

View file

@ -1,4 +1,5 @@
using EllieBot.Db.Models;
using EllieBot.Common.TypeReaders.Models;
using EllieBot.Db.Models;
using EllieBot.Modules.Administration.Services;
using System.Text;
using ContextType = Discord.Commands.ContextType;
@ -7,6 +8,7 @@ namespace EllieBot.Modules.Administration;
public partial class Administration
{
[Group("btr")]
public partial class ButtonRoleCommands : EllieModule<ButtonRolesService>
{
private List<ActionRowBuilder> GetActionRows(IReadOnlyList<ButtonRole> roles)
@ -265,5 +267,30 @@ public partial class Administration
})
.SendAsync();
}
[Cmd]
[RequireContext(ContextType.Guild)]
[BotPerm(GuildPerm.ManageRoles)]
[RequireUserPermission(GuildPerm.ManageRoles)]
public Task BtnRoleExclusive(MessageLink link, PermissionAction exclusive)
=> BtnRoleExclusive(link.Message.Id, exclusive);
[Cmd]
[RequireContext(ContextType.Guild)]
[BotPerm(GuildPerm.ManageRoles)]
[RequireUserPermission(GuildPerm.ManageRoles)]
public async Task BtnRoleExclusive(ulong messageId, PermissionAction exclusive)
{
var res = await _service.SetExclusiveButtonRoles(ctx.Guild.Id, messageId, exclusive.Value);
if (res)
{
await Response().Confirm(strs.btnrole_exclusive).SendAsync();
}
else
{
await Response().Confirm(strs.btnrole_multiple).SendAsync();
}
}
}
}

View file

@ -42,32 +42,49 @@ public sealed class ButtonRolesService : IEService, IReadyExecutor
_ = Task.Run(async () =>
{
await using var uow = _db.GetDbContext();
var buttonRole = await uow.GetTable<ButtonRole>()
.Where(x => x.ButtonId == smc.Data.CustomId && x.MessageId == smc.Message.Id)
.FirstOrDefaultAsyncLinqToDB();
if (buttonRole is null)
return;
var guild = _client.GetGuild(buttonRole.GuildId);
if (guild is null)
return;
var role = guild.GetRole(buttonRole.RoleId);
if (role is null)
return;
if (smc.User is not IGuildUser user)
return;
if (user.GetRoles().Any(x => x.Id == role.Id))
try
{
await user.RemoveRoleAsync(role.Id);
return;
}
await using var uow = _db.GetDbContext();
var buttonRole = await uow.GetTable<ButtonRole>()
.Where(x => x.ButtonId == smc.Data.CustomId && x.MessageId == smc.Message.Id)
.FirstOrDefaultAsyncLinqToDB();
await user.AddRoleAsync(role.Id);
if (buttonRole is null)
return;
var guild = _client.GetGuild(buttonRole.GuildId);
if (guild is null)
return;
var role = guild.GetRole(buttonRole.RoleId);
if (role is null)
return;
if (smc.User is not IGuildUser user)
return;
if (user.GetRoles().Any(x => x.Id == role.Id))
{
await user.RemoveRoleAsync(role.Id);
return;
}
if (buttonRole.Exclusive)
{
var otherRoles = await uow.GetTable<ButtonRole>()
.Where(x => x.GuildId == smc.GuildId && x.MessageId == smc.Message.Id)
.Select(x => x.RoleId)
.ToListAsyncLinqToDB();
await user.RemoveRolesAsync(otherRoles);
}
await user.AddRoleAsync(role.Id);
}
catch (Exception ex)
{
Log.Warning(ex, "Unable to handle button role interaction for user {UserId}", inter.User.Id);
}
});
}
@ -108,7 +125,8 @@ public sealed class ButtonRolesService : IEService, IReadyExecutor
: 1,
Emote = emoteStr,
Label = string.Empty,
ButtonId = $"{BTN_PREFIX}:{guildId}:{guid}"
ButtonId = $"{BTN_PREFIX}:{guildId}:{guid}",
Exclusive = (uow.GetTable<ButtonRole>().Where(x => x.GuildId == guildId && x.MessageId == messageId).All(x => x.Exclusive))
},
_ => new()
{
@ -151,4 +169,16 @@ public sealed class ButtonRolesService : IEService, IReadyExecutor
.OrderBy(x => x.Id)
.ToListAsyncLinqToDB();
}
}
public async Task<bool> SetExclusiveButtonRoles(ulong guildId, ulong messageId, bool exclusive)
{
await using var uow = _db.GetDbContext();
return await uow.GetTable<ButtonRole>()
.Where(x => x.GuildId == guildId && x.MessageId == messageId)
.UpdateAsync((_) => new()
{
Exclusive = exclusive
})
> 0;
}
}

View file

@ -57,7 +57,7 @@ public partial class Gambling
i.Dispose();
var eb = CreateEmbed()
.WithOkColor();
.WithOkColor();
var toSend = string.Empty;
if (cardObjects.Count == 5)
@ -172,13 +172,14 @@ public partial class Gambling
}
var eb = CreateEmbed()
.WithOkColor()
.WithAuthor(ctx.User)
.WithDescription(result.Card.GetEmoji())
.AddField(GetText(strs.guess), GetGuessInfo(val, col), true)
.AddField(GetText(strs.card), GetCardInfo(result.Card), true)
.AddField(GetText(strs.won), N((long)result.Won), false)
.WithImageUrl("attachment://card.png");
.WithOkColor()
.WithAuthor(ctx.User)
.WithDescription(result.Card.GetEmoji())
.AddField(GetText(strs.guess), GetGuessInfo(val, col), true)
.AddField(GetText(strs.card), GetCardInfo(result.Card), false)
.AddField(GetText(strs.bet), N(amount), true)
.AddField(GetText(strs.won), N((long)result.Won), true)
.WithImageUrl("attachment://card.png");
using var img = await GetCardImageAsync(result.Card);
await using var imgStream = await img.ToStreamAsync();

View file

@ -85,10 +85,10 @@ public partial class Gambling
: Format.Bold(GetText(strs.tails))));
var eb = CreateEmbed()
.WithOkColor()
.WithAuthor(ctx.User)
.WithDescription(msg)
.WithImageUrl($"attachment://{imgName}");
.WithOkColor()
.WithAuthor(ctx.User)
.WithDescription(msg)
.WithImageUrl($"attachment://{imgName}");
await ctx.Channel.SendFileAsync(stream,
imgName,
@ -123,18 +123,22 @@ public partial class Gambling
var won = (long)result.Won;
if (won > 0)
{
str = Format.Bold(GetText(strs.flip_guess(N(won))));
str = Format.Bold(GetText(strs.betflip_guess));
}
else
{
str = Format.Bold(GetText(strs.better_luck));
}
await Response().Embed(CreateEmbed()
.WithAuthor(ctx.User)
.WithDescription(str)
.WithOkColor()
.WithImageUrl(imageToSend.ToString())).SendAsync();
await Response()
.Embed(CreateEmbed()
.WithAuthor(ctx.User)
.WithDescription(str)
.AddField(GetText(strs.bet), N(amount), true)
.AddField(GetText(strs.won), N((long)result.Won), true)
.WithOkColor()
.WithImageUrl(imageToSend.ToString()))
.SendAsync();
}
}
}

View file

@ -718,7 +718,7 @@ public partial class Gambling : GamblingModule<GamblingService>
string str;
if (win > 0)
{
str = GetText(strs.br_win(N(win), result.Threshold + (result.Roll == 100 ? " 👑" : "")));
str = GetText(strs.betroll_win(result.Threshold + (result.Roll == 100 ? " 👑" : "")));
}
else
{
@ -728,7 +728,9 @@ public partial class Gambling : GamblingModule<GamblingService>
var eb = CreateEmbed()
.WithAuthor(ctx.User)
.WithDescription(Format.Bold(str))
.AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture))
.AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture), true)
.AddField(GetText(strs.bet), N(amount), true)
.AddField(GetText(strs.won), N((long)result.Won), true)
.WithOkColor();
await Response().Embed(eb).SendAsync();
@ -922,8 +924,8 @@ public partial class Gambling : GamblingModule<GamblingService>
var eb = CreateEmbed()
.WithOkColor()
.WithDescription(sb.ToString())
.AddField(GetText(strs.multiplier), $"{result.Multiplier:0.##}x", true)
.AddField(GetText(strs.won), $"{(long)result.Won}", true)
.AddField(GetText(strs.bet), N(amount), true)
.AddField(GetText(strs.won), $"{N((long)result.Won)}", true)
.WithAuthor(ctx.User);

View file

@ -66,10 +66,10 @@ public partial class Gambling
var eb = CreateEmbed()
.WithAuthor(ctx.User)
.WithDescription(Format.Bold(text))
.WithImageUrl($"attachment://result.png")
.WithOkColor();
.WithAuthor(ctx.User)
.WithDescription(Format.Bold(text))
.WithImageUrl($"attachment://result.png")
.WithOkColor();
var bb = new ButtonBuilder(emote: Emoji.Parse("🔁"), customId: "slot:again", label: "Pull Again");
var inter = _inter.Create(ctx.User.Id,
@ -168,7 +168,8 @@ public partial class Gambling
await using (var uow = _db.GetDbContext())
{
ownedAmount = uow.Set<DiscordUser>()
.FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount
.FirstOrDefault(x => x.UserId == ctx.User.Id)
?.CurrencyAmount
?? 0;
}

View file

@ -1499,18 +1499,22 @@ snipe:
- snipe
- sn
btnroleadd:
- btnradd
- btnra
- add
- a
btnroleremove:
- btnrrem
- btnrr
- btnrrm
- rem
- r
- rm
btnroleremoveall:
- btnrremall
- btnrra
- remall
- rma
btnrolelist:
- btnrlist
- btnrl
- list
- l
- ls
btnroleexclusive:
- excl
- e
wrongsong:
- wrongsong
- wrongtrack

View file

@ -4769,6 +4769,19 @@ btnrolelist:
- ''
params:
- { }
btnroleexclusive:
desc: |-
Toggles whether button roles are exclusive or not.
If enabled, users can only pick one role from the buttons per message.
If disabled, users can pick any number of roles.
ex:
- '123123123 enable'
- '123123123 disable'
params:
- message:
desc: "A message link or id of the message"
enable:
desc: "Whether to enable or disable exclusive button roles"
wrongsong:
desc: |-
Removes the last queued song.

View file

@ -238,10 +238,10 @@
"sb_user": "User soft-banned",
"awarded": "{2} has awarded {0} to {1}",
"better_luck": "Better luck next time ^_^",
"br_win": "Congratulations! You won {0} for rolling above {1}",
"betroll_win": "Congratulations! You rolled above {0}",
"deck_reshuffled": "Deck reshuffled.",
"flipped": "Flipped {0}",
"flip_guess": "You guessed it! You won {0}",
"betflip_guess": "You guessed it!",
"flip_invalid": "Invalid number specified. You can flip 1 to {0} coins.",
"flip_results": "Flipped {0} coins. {1} heads, {2} tails.",
"cards_left": "{0} cards left in the deck.",
@ -266,7 +266,8 @@
"available_tests": "Available Tests",
"test_results_for": "Test results for {0}",
"won": "Won",
"multiplier": "Multiplier",
"bet": "Bet",
"multi": "Multi",
"tails": "Tail",
"take": "successfully took {0} from {1}",
"take_fail": "was unable to take {0} from {1} because the user doesn't have that much {2}!",
@ -1129,6 +1130,8 @@
"btnrole_none": "There are no button roles on this page.",
"btnrole_removeall_not_found": "Button role successfully removed but message wasn't found.",
"btnrole_removed": "Button role removed.",
"btnrole_exclusive": "Users can now pick only one of the roles from that message.",
"btnrole_multiple": "Users can now pick any number of button roles from that message.",
"no_last_queued_found": "No last queued track found.",
"wrongsong_success": "Oops! Wrong song removed: {0}",
"server_not_found": "Server not found.",