diff --git a/src/NadekoBot/Modules/Gambling/~Shared/Decks/Deck.cs b/src/Nadeko.Econ/Deck.cs similarity index 99% rename from src/NadekoBot/Modules/Gambling/~Shared/Decks/Deck.cs rename to src/Nadeko.Econ/Deck.cs index 1ecbead19..171288cc6 100644 --- a/src/NadekoBot/Modules/Gambling/~Shared/Decks/Deck.cs +++ b/src/Nadeko.Econ/Deck.cs @@ -1,7 +1,7 @@ #nullable disable using Nadeko.Common; -namespace NadekoBot.Modules.Gambling.Common; +namespace Nadeko.Econ; public class Deck { @@ -274,7 +274,7 @@ public class Deck public string GetValueText() => _cardNames[Number]; - + public override string ToString() => _cardNames[Number] + " Of " + Suit; diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawColorGuess.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawColorGuess.cs new file mode 100644 index 000000000..f84134e0e --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawColorGuess.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public enum BetdrawColorGuess +{ + Red, + Black +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawGame.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawGame.cs new file mode 100644 index 000000000..ca40c1f33 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawGame.cs @@ -0,0 +1,83 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public sealed class BetdrawGame +{ + private static readonly NadekoRandom _rng = new(); + + private const decimal SINGLE_GUESS_MULTI = 2.075M; + private const decimal DOUBLE_GUESS_MULTI = 4.15M; + + public BetdrawGame() + { + + } + + public BetdrawResult Draw(BetdrawValueGuess? val, BetdrawColorGuess? col, decimal amount) + { + if (val is null && col is null) + throw new ArgumentNullException(nameof(val)); + + var card = new Deck().CardPool[_rng.Next(0, 52)]; + + var realVal = card.Number < 7 + ? BetdrawValueGuess.Low + : BetdrawValueGuess.High; + + var realCol = card.Suit is Deck.CardSuit.Diamonds or Deck.CardSuit.Hearts + ? BetdrawColorGuess.Red + : BetdrawColorGuess.Black; + + // if card is 7, autoloss + if (card.Number == 7) + { + return new() + { + Won = 0M, + Multiplier = 0M, + ResultType = BetdrawResultType.Lose, + Card = card, + }; + } + + byte win = 0; + if (val is BetdrawValueGuess valGuess) + { + if (realVal != valGuess) + return new() + { + Won = 0M, + Multiplier = 0M, + ResultType = BetdrawResultType.Lose, + Card = card + }; + + ++win; + } + + if (col is BetdrawColorGuess colGuess) + { + if (realCol != colGuess) + return new() + { + Won = 0M, + Multiplier = 0M, + ResultType = BetdrawResultType.Lose, + Card = card + }; + + ++win; + } + + var multi = win == 1 + ? SINGLE_GUESS_MULTI + : DOUBLE_GUESS_MULTI; + + return new() + { + Won = amount * multi, + Multiplier = multi, + ResultType = BetdrawResultType.Win, + Card = card + }; + } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResult.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResult.cs new file mode 100644 index 000000000..7b5a59b32 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResult.cs @@ -0,0 +1,9 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public readonly struct BetdrawResult +{ + public decimal Won { get; init; } + public decimal Multiplier { get; init; } + public BetdrawResultType ResultType { get; init; } + public Deck.Card Card { get; init; } +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResultType.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResultType.cs new file mode 100644 index 000000000..adfc00a05 --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawResultType.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public enum BetdrawResultType +{ + Win, + Lose +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betdraw/BetdrawValueGuess.cs b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawValueGuess.cs new file mode 100644 index 000000000..bb6652b5c --- /dev/null +++ b/src/Nadeko.Econ/Gambling/Betdraw/BetdrawValueGuess.cs @@ -0,0 +1,7 @@ +namespace Nadeko.Econ.Gambling.Betdraw; + +public enum BetdrawValueGuess +{ + High, + Low, +} \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs b/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs index 8e94c21f9..7aad2db55 100644 --- a/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs +++ b/src/Nadeko.Econ/Gambling/Betflip/BetflipGame.cs @@ -3,26 +3,31 @@ public sealed class BetflipGame { private readonly decimal _winMulti; - private readonly NadekoRandom _rng; + private static readonly NadekoRandom _rng = new NadekoRandom(); public BetflipGame(decimal winMulti) { _winMulti = winMulti; - _rng = new NadekoRandom(); } public BetflipResult Flip(byte guess, decimal amount) { var side = _rng.Next(0, 2); - decimal won = 0; - if (side == guess) - won = amount * _winMulti; - + { + return new BetflipResult() + { + Side = side, + Won = amount * _winMulti, + Multiplier = _winMulti + }; + } + return new BetflipResult() { - Side = side, - Won = won, + Side = side, + Won = 0, + Multiplier = 0, }; } } \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs b/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs index e415c73aa..8111db4f4 100644 --- a/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs +++ b/src/Nadeko.Econ/Gambling/Betflip/BetflipResult.cs @@ -4,4 +4,5 @@ public readonly struct BetflipResult { public decimal Won { get; init; } public byte Side { get; init; } + public decimal Multiplier { get; init; } } \ No newline at end of file diff --git a/src/Nadeko.Econ/Gambling/Wof/WofGame.cs b/src/Nadeko.Econ/Gambling/Wof/WofGame.cs index fbe8eae32..a8114feb0 100644 --- a/src/Nadeko.Econ/Gambling/Wof/WofGame.cs +++ b/src/Nadeko.Econ/Gambling/Wof/WofGame.cs @@ -2,15 +2,14 @@ public sealed class LulaGame { - public static IReadOnlyList DEFAULT_MULTIPLIERS = new[] { 1.7M, 1.5M, 0.2M, 0.1M, 0.3M, 0.5M, 1.2M, 2.4M }; + private static readonly IReadOnlyList DEFAULT_MULTIPLIERS = new[] { 1.7M, 1.5M, 0.2M, 0.1M, 0.3M, 0.5M, 1.2M, 2.4M }; private readonly IReadOnlyList _multipliers; - private readonly NadekoRandom _rng; + private static readonly NadekoRandom _rng = new(); public LulaGame(IReadOnlyList multipliers) { _multipliers = multipliers; - _rng = new(); } public LulaGame() : this(DEFAULT_MULTIPLIERS) diff --git a/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs b/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs index 45268d24c..d39b3eb8a 100644 --- a/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs +++ b/src/NadekoBot/Modules/Gambling/BlackJack/Blackjack.cs @@ -1,4 +1,6 @@ #nullable disable +using Nadeko.Econ; + namespace NadekoBot.Modules.Gambling.Common.Blackjack; public class Blackjack diff --git a/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs b/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs index c1d1a3ba3..6bb256c8a 100644 --- a/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs +++ b/src/NadekoBot/Modules/Gambling/BlackJack/Player.cs @@ -1,4 +1,6 @@ #nullable disable +using Nadeko.Econ; + namespace NadekoBot.Modules.Gambling.Common.Blackjack; public abstract class Player diff --git a/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs b/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs index ab81adda5..708946b90 100644 --- a/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs +++ b/src/NadekoBot/Modules/Gambling/DiceRoll/DiceRollCommands.cs @@ -30,14 +30,23 @@ public partial class Gambling var num1 = gen / 10; var num2 = gen % 10; - + using var img1 = await GetDiceAsync(num1); using var img2 = await GetDiceAsync(num2); using var img = new[] { img1, img2 }.Merge(out var format); await using var ms = await img.ToStreamAsync(format); + + var fileName = $"dice.{format.FileExtensions.First()}"; + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .AddField(GetText(strs.roll2), gen) + .WithImageUrl($"attachment://{fileName}"); + await ctx.Channel.SendFileAsync(ms, - $"dice.{format.FileExtensions.First()}", - Format.Bold(ctx.User.ToString()) + " " + GetText(strs.dice_rolled(Format.Code(gen.ToString())))); + fileName, + embed: eb.Build()); } [Cmd] @@ -105,14 +114,18 @@ public partial class Gambling foreach (var d in dice) d.Dispose(); + var imageName = $"dice.{format.FileExtensions.First()}"; + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .AddField(GetText(strs.rolls), values.Select(x => Format.Code(x.ToString())).Join(' '), true) + .AddField(GetText(strs.total), values.Sum(), true) + .WithDescription(GetText(strs.dice_rolled_num(Format.Bold(values.Count.ToString())))) + .WithImageUrl($"attachment://{imageName}"); + await ctx.Channel.SendFileAsync(ms, - $"dice.{format.FileExtensions.First()}", - Format.Bold(ctx.User.ToString()) - + " " - + GetText(strs.dice_rolled_num(Format.Bold(values.Count.ToString()))) - + " " - + GetText(strs.total_average(Format.Bold(values.Sum().ToString()), - Format.Bold((values.Sum() / (1.0f * values.Count)).ToString("N2"))))); + imageName, + embed: eb.Build()); } private async Task InternallDndRoll(string arg, bool ordered) @@ -130,9 +143,8 @@ public partial class Gambling rolls.Add(_fateRolls[rng.Next(0, _fateRolls.Length)]); var embed = _eb.Create() .WithOkColor() - .WithDescription(ctx.User.Mention - + " " - + GetText(strs.dice_rolled_num(Format.Bold(n1.ToString())))) + .WithAuthor(ctx.User) + .WithDescription(GetText(strs.dice_rolled_num(Format.Bold(n1.ToString())))) .AddField(Format.Bold("Result"), string.Join(" ", rolls.Select(c => Format.Code($"[{c}]")))); @@ -160,10 +172,9 @@ public partial class Gambling var sum = arr.Sum(); var embed = _eb.Create() .WithOkColor() - .WithDescription(ctx.User.Mention - + " " - + GetText(strs.dice_rolled_num(n1 + $"`1 - {n2}`"))) - .AddField(Format.Bold("Rolls"), + .WithAuthor(ctx.User) + .WithDescription(GetText(strs.dice_rolled_num(n1 + $"`1 - {n2}`"))) + .AddField(Format.Bold(GetText(strs.rolls)), string.Join(" ", (ordered ? arr.OrderBy(x => x).AsEnumerable() : arr).Select(x => Format.Code(x.ToString())))) diff --git a/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs b/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs index c4e52225a..fe154a20a 100644 --- a/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Draw/DrawCommands.cs @@ -1,5 +1,7 @@ #nullable disable +using Nadeko.Econ; using NadekoBot.Modules.Gambling.Common; +using NadekoBot.Modules.Gambling.Services; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using Image = SixLabors.ImageSharp.Image; @@ -9,23 +11,23 @@ namespace NadekoBot.Modules.Gambling; public partial class Gambling { [Group] - public partial class DrawCommands : NadekoModule + public partial class DrawCommands : GamblingSubmodule { private static readonly ConcurrentDictionary _allDecks = new(); private readonly IImageCache _images; - public DrawCommands(IImageCache images) + public DrawCommands(IImageCache images, GamblingConfigService gcs) : base(gcs) => _images = images; - private async Task<(Stream ImageStream, string ToSend)> InternalDraw(int num, ulong? guildId = null) + private async Task InternalDraw(int count, ulong? guildId = null) { - if (num is < 1 or > 10) - throw new ArgumentOutOfRangeException(nameof(num)); + if (count is < 1 or > 10) + throw new ArgumentOutOfRangeException(nameof(count)); var cards = guildId is null ? new() : _allDecks.GetOrAdd(ctx.Guild, _ => new()); var images = new List>(); var cardObjects = new List(); - for (var i = 0; i < num; i++) + for (var i = 0; i < count; i++) { if (cards.CardPool.Count == 0 && i != 0) { @@ -43,22 +45,43 @@ public partial class Gambling var currentCard = cards.Draw(); cardObjects.Add(currentCard); - var cardName = currentCard.ToString().ToLowerInvariant().Replace(' ', '_'); - images.Add(Image.Load(await File.ReadAllBytesAsync($"data/images/cards/{cardName}.jpg"))); + var image = await GetCardImageAsync(currentCard); + images.Add(image); } + var imgName = "cards.jpg"; using var img = images.Merge(); foreach (var i in images) i.Dispose(); - var toSend = $"{Format.Bold(ctx.User.ToString())}"; + var eb = _eb.Create(ctx) + .WithOkColor(); + + var toSend = string.Empty; if (cardObjects.Count == 5) - toSend += $" drew `{Deck.GetHandValue(cardObjects)}`"; + eb.AddField(GetText(strs.hand_value), Deck.GetHandValue(cardObjects), true); if (guildId is not null) - toSend += "\n" + GetText(strs.cards_left(Format.Bold(cards.CardPool.Count.ToString()))); + toSend += GetText(strs.cards_left(Format.Bold(cards.CardPool.Count.ToString()))); - return (img.ToStream(), toSend); + eb.WithDescription(toSend) + .WithAuthor(ctx.User) + .WithImageUrl($"attachment://{imgName}"); + + if (count > 1) + eb.AddField(GetText(strs.cards), count.ToString(), true); + + await using var imageStream = await img.ToStreamAsync(); + await ctx.Channel.SendFileAsync(imageStream, + imgName, + embed: eb.Build()); + } + + private async Task> GetCardImageAsync(Deck.Card currentCard) + { + var cardName = currentCard.ToString().ToLowerInvariant().Replace(' ', '_'); + var cardBytes = await File.ReadAllBytesAsync($"data/images/cards/{cardName}.jpg"); + return Image.Load(cardBytes); } [Cmd] @@ -66,30 +89,24 @@ public partial class Gambling public async partial Task Draw(int num = 1) { if (num < 1) - num = 1; + return; + if (num > 10) num = 10; - var (imageStream, toSend) = await InternalDraw(num, ctx.Guild.Id); - await using (imageStream) - { - await ctx.Channel.SendFileAsync(imageStream, num + " cards.jpg", toSend); - } + await InternalDraw(num, ctx.Guild.Id); } [Cmd] public async partial Task DrawNew(int num = 1) { if (num < 1) - num = 1; + return; + if (num > 10) num = 10; - var (imageStream, toSend) = await InternalDraw(num); - await using (imageStream) - { - await ctx.Channel.SendFileAsync(imageStream, num + " cards.jpg", toSend); - } + await InternalDraw(num); } [Cmd] @@ -108,5 +125,98 @@ public partial class Gambling await ReplyConfirmLocalizedAsync(strs.deck_reshuffled); } + + [Cmd] + [RequireContext(ContextType.Guild)] + public partial Task BetDraw(ShmartNumber amount, InputValueGuess val, InputColorGuess? col = null) + => BetDrawInternal(amount, val, col); + + [Cmd] + [RequireContext(ContextType.Guild)] + public partial Task BetDraw(ShmartNumber amount, InputColorGuess col, InputValueGuess? val = null) + => BetDrawInternal(amount, val, col); + + public async Task BetDrawInternal(long amount, InputValueGuess? val, InputColorGuess? col) + { + var res = await _service.BetDrawAsync(ctx.User.Id, + amount, + (byte?)val, + (byte?)col); + + if (!res.TryPickT0(out var result, out _)) + { + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); + return; + } + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .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"); + + using var img = await GetCardImageAsync(result.Card); + await using var imgStream = await img.ToStreamAsync(); + await ctx.Channel.SendFileAsync(imgStream, "card.png", embed: eb.Build()); + } + + private string GetGuessInfo(InputValueGuess? valG, InputColorGuess? colG) + { + var val = valG switch + { + InputValueGuess.H => "Hi ⬆️", + InputValueGuess.L => "Lo ⬇️", + _ => "❓" + }; + + var col = colG switch + { + InputColorGuess.Red => "R 🔴", + InputColorGuess.Black => "B ⚫", + _ => "❓" + }; + + return $"{val} / {col}"; + } + private string GetCardInfo(Deck.Card card) + { + var val = card.Number switch + { + < 7 => "Lo ⬇️", + > 7 => "Hi ⬆️", + _ => "7 💀" + }; + + var col = card.Number == 7 + ? "7 💀" + : card.Suit switch + { + Deck.CardSuit.Diamonds or Deck.CardSuit.Hearts => "R 🔴", + _ => "B ⚫" + }; + + return $"{val} / {col}"; + } + + public enum InputValueGuess + { + High = 0, + H = 0, + Hi = 0, + Low = 1, + L = 1, + Lo = 1, + } + + public enum InputColorGuess + { + R = 0, + Red = 0, + B = 1, + Bl = 1, + Black = 1, + } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs b/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs index 145e4ebe4..eaf593296 100644 --- a/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs +++ b/src/NadekoBot/Modules/Gambling/FlipCoin/FlipCoinCommands.cs @@ -76,17 +76,23 @@ public partial class Gambling foreach (var i in imgs) i.Dispose(); + var imgName = $"coins.{format.FileExtensions.First()}"; + var msg = count != 1 - ? Format.Bold(ctx.User.ToString()) - + " " - + GetText(strs.flip_results(count, headCount, tailCount)) - : Format.Bold(ctx.User.ToString()) - + " " - + GetText(strs.flipped(headCount > 0 - ? Format.Bold(GetText(strs.heads)) - : Format.Bold(GetText(strs.tails)))); + ? Format.Bold(GetText(strs.flip_results(count, headCount, tailCount))) + : GetText(strs.flipped(headCount > 0 + ? Format.Bold(GetText(strs.heads)) + : Format.Bold(GetText(strs.tails)))); + + var eb = _eb.Create(ctx) + .WithOkColor() + .WithAuthor(ctx.User) + .WithDescription(msg) + .WithImageUrl($"attachment://{imgName}"); - await ctx.Channel.SendFileAsync(stream, $"{count} coins.{format.FileExtensions.First()}", msg); + await ctx.Channel.SendFileAsync(stream, + imgName, + embed: eb.Build()); } [Cmd] diff --git a/src/NadekoBot/Modules/Gambling/Gambling.cs b/src/NadekoBot/Modules/Gambling/Gambling.cs index dd0633029..56765e225 100644 --- a/src/NadekoBot/Modules/Gambling/Gambling.cs +++ b/src/NadekoBot/Modules/Gambling/Gambling.cs @@ -345,7 +345,8 @@ public partial class Gambling : GamblingModule ("award", var name, ulong userId) => GetText(strs.curtr_award(name, userId)), ("take", var name, ulong userId) => GetText(strs.curtr_take(name, userId)), ("blackjack", _, _) => $"Blackjack - {subType}", - ("wheel", _, _) => $"Wheel Of Fortune - {subType}", + ("wheel", _, _) => $"Lucky Ladder - {subType}", + ("lula", _, _) => $"Lucky Ladder - {subType}", ("rps", _, _) => $"Rock Paper Scissors - {subType}", (null, _, _) => null, (_, null, _) => null, @@ -671,7 +672,7 @@ public partial class Gambling : GamblingModule var eb = _eb.Create(ctx) .WithAuthor(ctx.User) - .WithFooter(str) + .WithDescription(Format.Bold(str)) .AddField(GetText(strs.roll2), result.Roll.ToString(CultureInfo.InvariantCulture)) .WithOkColor(); @@ -772,7 +773,6 @@ public partial class Gambling : GamblingModule Scissors = 2 } - // todo check if trivia is being disposed [Cmd] public async partial Task Rps(InputRpsPick pick, ShmartNumber amount = default) { @@ -839,7 +839,7 @@ public partial class Gambling : GamblingModule if (!await CheckBetMandatory(amount)) return; - var res = await _gs.WofAsync(ctx.User.Id, amount); + var res = await _gs.LulaAsync(ctx.User.Id, amount); if (!res.TryPickT0(out var result, out _)) { await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); @@ -871,4 +871,99 @@ public partial class Gambling : GamblingModule await ctx.Channel.EmbedAsync(eb); } + + + public enum GambleTestTarget + { + Slot, + BetDraw, + BetDrawHL, + BetDrawRB, + Betflip, + BetflipT, + Lula, + Rps, + } + + [Cmd] + [OwnerOnly] + public async partial Task BetTest() + { + await SendConfirmAsync(GetText(strs.available_tests), + Enum.GetValues() + .Select(x => $"`{x}`") + .Join(", ")); + } + + [Cmd] + [OwnerOnly] + public async partial Task BetTest(GambleTestTarget target, int tests = 1000) + { + if (tests <= 0) + return; + + await ctx.Channel.TriggerTypingAsync(); + + var streak = 0; + var maxW = 0; + var maxL = 0; + + var dict = new Dictionary(); + for (var i = 0; i < tests; i++) + { + var multi = target switch + { + GambleTestTarget.BetDraw => (await _gs.BetDrawAsync(ctx.User.Id, 0, 1, 0)).AsT0.Multiplier, + GambleTestTarget.BetDrawRB => (await _gs.BetDrawAsync(ctx.User.Id, 0, null, 1)).AsT0.Multiplier, + GambleTestTarget.BetDrawHL => (await _gs.BetDrawAsync(ctx.User.Id, 0, 0, null)).AsT0.Multiplier, + GambleTestTarget.Slot => (await _gs.SlotAsync(ctx.User.Id, 0)).AsT0.Multiplier, + GambleTestTarget.Betflip => (await _gs.BetFlipAsync(ctx.User.Id, 0, 0)).AsT0.Multiplier, + GambleTestTarget.BetflipT => (await _gs.BetFlipAsync(ctx.User.Id, 0, 1)).AsT0.Multiplier, + GambleTestTarget.Lula => (await _gs.LulaAsync(ctx.User.Id, 0)).AsT0.Multiplier, + GambleTestTarget.Rps => (await _gs.RpsAsync(ctx.User.Id, 0, (byte)(i % 3))).AsT0.Multiplier, + _ => throw new ArgumentOutOfRangeException(nameof(target)) + }; + + if (dict.ContainsKey(multi)) + dict[multi] += 1; + else + dict.Add(multi, 1); + + if (multi < 1) + { + if (streak <= 0) + --streak; + else + streak = -1; + + maxL = Math.Max(maxL, -streak); + } + else if (multi > 1) + { + if (streak >= 0) + ++streak; + else + streak = 1; + + maxW = Math.Max(maxW, streak); + } + } + + var sb = new StringBuilder(); + decimal payout = 0; + foreach (var key in dict.Keys.OrderByDescending(x => x)) + { + sb.AppendLine($"x**{key}** occured `{dict[key]}` times. {dict[key] * 1.0f / tests * 100}%"); + payout += key * dict[key]; + } + + sb.AppendLine(); + sb.AppendLine($"Longest win streak: `{maxW}`"); + sb.AppendLine($"Longest lose streak: `{maxL}`"); + + await SendConfirmAsync(GetText(strs.test_results_for(target)), + sb.ToString(), + footer: $"Total Bet: {tests} | Payout: {payout:F0} | {payout * 1.0M / tests * 100}%"); + } + } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs b/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs index e0edf47b4..aeef3bcab 100644 --- a/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs +++ b/src/NadekoBot/Modules/Gambling/Slot/SlotCommands.cs @@ -1,4 +1,4 @@ -#nullable disable +#nullable disable warnings using NadekoBot.Db.Models; using NadekoBot.Modules.Gambling.Common; using NadekoBot.Modules.Gambling.Services; @@ -73,178 +73,58 @@ public partial class Gambling await ctx.Channel.EmbedAsync(embed); } - - [Cmd] - [OwnerOnly] - public async partial Task SlotTest(int tests = 1000) + public sealed class SlotInteraction : NInteraction { - if (tests <= 0) - return; - //multi vs how many times it occured - - int streak = 0; - int maxW = 0; - int maxL = 0; - - var dict = new Dictionary(); - for (var i = 0; i < tests; i++) + public SlotInteraction(DiscordSocketClient client, ulong userId, Func action) : base(client, userId, action) { - var res = await _service.SlotAsync(ctx.User.Id, 0); - var multi = res.AsT0.Multiplier; - if (dict.ContainsKey(multi)) - dict[multi] += 1; - else - dict.Add(multi, 1); - - if (multi == 0) - { - if (streak <= 0) - --streak; - else - streak = -1; - - maxL = Math.Max(maxL, -streak); - } - else - { - if (streak >= 0) - ++streak; - else - streak = 1; - - maxW = Math.Max(maxW, streak); - } - } - - var sb = new StringBuilder(); - decimal payout = 0; - foreach (var key in dict.Keys.OrderByDescending(x => x)) - { - sb.AppendLine($"x{key} occured `{dict[key]}` times. {dict[key] * 1.0f / tests * 100}%"); - payout += key * dict[key]; } - sb.AppendLine(); - sb.AppendLine($"Longest win streak: `{maxW}`"); - sb.AppendLine($"Longest lose streak: `{maxL}`"); - - await SendConfirmAsync("Slot Test Results", - sb.ToString(), - footer: $"Total Bet: {tests} | Payout: {payout:F0} | {payout * 1.0M / tests * 100}%"); + protected override NadekoInteractionData Data { get; } = new(Emoji.Parse("🔁"), + "slot:again", + "Pull Again"); } [Cmd] public async partial Task Slot(ShmartNumber amount) { + if (!await CheckBetMandatory(amount)) + return; + + // var slotInteraction = CreateSlotInteractionIntenal(amount); + + await ctx.Channel.TriggerTypingAsync(); + if (!_runningUsers.Add(ctx.User.Id)) return; try { - if (!await CheckBetMandatory(amount)) - return; - - await ctx.Channel.TriggerTypingAsync(); - - var maybeResult = await _service.SlotAsync(ctx.User.Id, amount); - - if (!maybeResult.TryPickT0(out var result, out var error)) + if (await InternalSlotAsync(amount) is not SlotResult result) { - if (error == GamblingError.InsufficientFunds) - await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); - + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); return; } - lock (_slotStatsLock) - { - totalBet += amount; - totalPaidOut += result.Won; - } + var msg = GetSlotMessageInternal(result); - long ownedAmount; - await using (var uow = _db.GetDbContext()) - { - ownedAmount = uow.Set().FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount - ?? 0; - } + using var image = await GenerateSlotImageAsync(amount, result); + await using var imgStream = await image.ToStreamAsync(); - var slotBg = await _images.GetSlotBgAsync(); - using (var bgImage = Image.Load(slotBg, out _)) - { - var numbers = new int[3]; - result.Rolls.CopyTo(numbers, 0); - Color fontColor = Config.Slots.CurrencyFontColor; + var eb = _eb.Create(ctx) + .WithAuthor(ctx.User) + .WithDescription(Format.Bold(msg)) + .WithImageUrl($"attachment://result.png") + .WithOkColor(); + + // var inter = slotInteraction.GetInteraction(); + await ctx.Channel.SendFileAsync(imgStream, + "result.png", + embed: eb.Build() + // components: inter.CreateComponent() + ); - bgImage.Mutate(x => x.DrawText(new() - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = 140 - } - }, - ((long)result.Won).ToString(), - _fonts.DottyFont.CreateFont(65), - fontColor, - new(227, 92))); - - var bottomFont = _fonts.DottyFont.CreateFont(50); - - bgImage.Mutate(x => x.DrawText(new() - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = 135 - } - }, - amount.ToString(), - bottomFont, - fontColor, - new(129, 472))); - - bgImage.Mutate(x => x.DrawText(new() - { - TextOptions = new() - { - HorizontalAlignment = HorizontalAlignment.Center, - VerticalAlignment = VerticalAlignment.Center, - WrapTextWidth = 135 - } - }, - ownedAmount.ToString(), - bottomFont, - fontColor, - new(325, 472))); - //sw.PrintLap("drew red text"); - - for (var i = 0; i < 3; i++) - { - using var img = Image.Load(await _images.GetSlotEmojiAsync(numbers[i])); - bgImage.Mutate(x => x.DrawImage(img, new Point(148 + (105 * i), 217), 1f)); - } - - var multi = result.Multiplier.ToString("0.##"); - var msg = result.WinType switch - { - SlotWinType.SingleJoker => GetText(strs.slot_single(CurrencySign, multi)), - SlotWinType.DoubleJoker => GetText(strs.slot_two(CurrencySign, multi)), - SlotWinType.TrippleNormal => GetText(strs.slot_three(multi)), - SlotWinType.TrippleJoker => GetText(strs.slot_jackpot(multi)), - _ => GetText(strs.better_luck), - }; - - await using (var imgStream = await bgImage.ToStreamAsync()) - { - await ctx.Channel.SendFileAsync(imgStream, - "result.png", - Format.Bold(ctx.User.ToString()) + " " + msg); - } - } + // await inter.RunAsync(resMsg); } finally { @@ -252,5 +132,156 @@ public partial class Gambling _runningUsers.TryRemove(ctx.User.Id); } } + + // private SlotInteraction CreateSlotInteractionIntenal(long amount) + // { + // return new SlotInteraction((DiscordSocketClient)ctx.Client, + // ctx.User.Id, + // async (smc) => + // { + // try + // { + // if (await InternalSlotAsync(amount) is not SlotResult result) + // { + // await smc.RespondErrorAsync(_eb, GetText(strs.not_enough(CurrencySign)), true); + // return; + // } + // + // var msg = GetSlotMessageInternal(result); + // + // using var image = await GenerateSlotImageAsync(amount, result); + // await using var imgStream = await image.ToStreamAsync(); + // + // var guid = Guid.NewGuid(); + // var imgName = $"result_{guid}.png"; + // + // var slotInteraction = CreateSlotInteractionIntenal(amount).GetInteraction(); + // + // await smc.Message.ModifyAsync(m => + // { + // m.Content = msg; + // m.Attachments = new[] + // { + // new FileAttachment(imgStream, imgName) + // }; + // m.Components = slotInteraction.CreateComponent(); + // }); + // + // _ = slotInteraction.RunAsync(smc.Message); + // } + // catch (Exception ex) + // { + // Log.Error(ex, "Error pulling slot again"); + // } + // // finally + // // { + // // await Task.Delay(1000); + // // _runningUsers.TryRemove(ctx.User.Id); + // // } + // }); + // } + + private string GetSlotMessageInternal(SlotResult result) + { + var multi = result.Multiplier.ToString("0.##"); + var msg = result.WinType switch + { + SlotWinType.SingleJoker => GetText(strs.slot_single(CurrencySign, multi)), + SlotWinType.DoubleJoker => GetText(strs.slot_two(CurrencySign, multi)), + SlotWinType.TrippleNormal => GetText(strs.slot_three(multi)), + SlotWinType.TrippleJoker => GetText(strs.slot_jackpot(multi)), + _ => GetText(strs.better_luck), + }; + return msg; + } + + private async Task InternalSlotAsync(long amount) + { + var maybeResult = await _service.SlotAsync(ctx.User.Id, amount); + + if (!maybeResult.TryPickT0(out var result, out var error)) + { + await ReplyErrorLocalizedAsync(strs.not_enough(CurrencySign)); + return null; + } + + lock (_slotStatsLock) + { + totalBet += amount; + totalPaidOut += result.Won; + } + + return result; + } + + private async Task> GenerateSlotImageAsync(long amount, SlotResult result) + { + long ownedAmount; + await using (var uow = _db.GetDbContext()) + { + ownedAmount = uow.Set().FirstOrDefault(x => x.UserId == ctx.User.Id)?.CurrencyAmount + ?? 0; + } + + var slotBg = await _images.GetSlotBgAsync(); + var bgImage = Image.Load(slotBg, out _); + var numbers = new int[3]; + result.Rolls.CopyTo(numbers, 0); + + Color fontColor = Config.Slots.CurrencyFontColor; + + bgImage.Mutate(x => x.DrawText(new() + { + TextOptions = new() + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + WrapTextWidth = 140 + } + }, + ((long)result.Won).ToString(), + _fonts.DottyFont.CreateFont(65), + fontColor, + new(227, 92))); + + var bottomFont = _fonts.DottyFont.CreateFont(50); + + bgImage.Mutate(x => x.DrawText(new() + { + TextOptions = new() + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + WrapTextWidth = 135 + } + }, + amount.ToString(), + bottomFont, + fontColor, + new(129, 472))); + + bgImage.Mutate(x => x.DrawText(new() + { + TextOptions = new() + { + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + WrapTextWidth = 135 + } + }, + ownedAmount.ToString(), + bottomFont, + fontColor, + new(325, 472))); + //sw.PrintLap("drew red text"); + + for (var i = 0; i < 3; i++) + { + using var img = Image.Load(await _images.GetSlotEmojiAsync(numbers[i])); + bgImage.Mutate(x => x.DrawImage(img, new Point(148 + (105 * i), 217), 1f)); + } + + return bgImage; + } } } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs b/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs index 312d662fc..26b4ffb59 100644 --- a/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs +++ b/src/NadekoBot/Modules/Gambling/~Shared/Decks/QuadDeck.cs @@ -1,4 +1,6 @@ -namespace NadekoBot.Modules.Gambling.Common; +using Nadeko.Econ; + +namespace NadekoBot.Modules.Gambling.Common; public class QuadDeck : Deck { diff --git a/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs b/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs index e23d8d30a..dd199de7a 100644 --- a/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs +++ b/src/NadekoBot/Modules/Gambling/~Shared/IGamblingService.cs @@ -1,5 +1,6 @@ #nullable disable using Nadeko.Econ.Gambling; +using Nadeko.Econ.Gambling.Betdraw; using Nadeko.Econ.Gambling.Rps; using OneOf; @@ -7,10 +8,11 @@ namespace NadekoBot.Modules.Gambling; public interface IGamblingService { - Task> WofAsync(ulong userId, long amount); + Task> LulaAsync(ulong userId, long amount); Task> BetRollAsync(ulong userId, long amount); Task> BetFlipAsync(ulong userId, long amount, byte guess); Task> SlotAsync(ulong userId, long amount); Task FlipAsync(int count); Task> RpsAsync(ulong userId, long amount, byte pick); + Task> BetDrawAsync(ulong userId, long amount, byte? guessValue, byte? guessColor); } \ No newline at end of file diff --git a/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs b/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs index 944548f35..e5240c530 100644 --- a/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs +++ b/src/NadekoBot/Modules/Gambling/~Shared/NewGamblingService.cs @@ -1,5 +1,6 @@ #nullable disable using Nadeko.Econ.Gambling; +using Nadeko.Econ.Gambling.Betdraw; using Nadeko.Econ.Gambling.Rps; using NadekoBot.Modules.Gambling.Services; using OneOf; @@ -17,9 +18,7 @@ public sealed class NewGamblingService : IGamblingService, INService _cs = cs; } - // todo input checks - // todo ladder of fortune - public async Task> WofAsync(ulong userId, long amount) + public async Task> LulaAsync(ulong userId, long amount) { if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount)); @@ -64,9 +63,9 @@ public sealed class NewGamblingService : IGamblingService, INService var game = new BetrollGame(_bcs.Data.BetRoll.Pairs .Select(x => (x.WhenAbove, (decimal)x.MultiplyBy)) .ToList()); - + var result = game.Roll(amount); - + var won = (long)result.Won; if (won > 0) { @@ -81,6 +80,9 @@ public sealed class NewGamblingService : IGamblingService, INService if (amount < 0) throw new ArgumentOutOfRangeException(nameof(amount)); + if (guess > 1) + throw new ArgumentOutOfRangeException(nameof(guess)); + if (amount > 0) { var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("betflip", "bet")); @@ -102,6 +104,42 @@ public sealed class NewGamblingService : IGamblingService, INService return result; } + + public async Task> BetDrawAsync(ulong userId, long amount, byte? guessValue, byte? guessColor) + { + if (amount < 0) + throw new ArgumentOutOfRangeException(nameof(amount)); + + if (guessColor is null && guessValue is null) + throw new ArgumentNullException(); + + if (guessColor > 1) + throw new ArgumentOutOfRangeException(nameof(guessColor)); + + if (guessValue > 1) + throw new ArgumentOutOfRangeException(nameof(guessValue)); + + if (amount > 0) + { + var isTakeSuccess = await _cs.RemoveAsync(userId, amount, new("betflip", "bet")); + + if (!isTakeSuccess) + { + return GamblingError.InsufficientFunds; + } + } + + var game = new BetdrawGame(); + var result = game.Draw((BetdrawValueGuess?)guessValue, (BetdrawColorGuess?)guessColor, amount); + + var won = (long)result.Won; + if (won > 0) + { + await _cs.AddAsync(userId, won, new("betflip", "win")); + } + + return result; + } public async Task> SlotAsync(ulong userId, long amount) { @@ -132,6 +170,9 @@ public sealed class NewGamblingService : IGamblingService, INService public Task FlipAsync(int count) { + if (count < 1) + throw new ArgumentOutOfRangeException(nameof(count)); + var game = new BetflipGame(0); var results = new FlipResult[count]; diff --git a/src/NadekoBot/Modules/Nsfw/Nsfw.cs b/src/NadekoBot/Modules/Nsfw/Nsfw.cs index 513357807..8427da096 100644 --- a/src/NadekoBot/Modules/Nsfw/Nsfw.cs +++ b/src/NadekoBot/Modules/Nsfw/Nsfw.cs @@ -108,7 +108,7 @@ public partial class NSFW : NadekoModule return t; }); - await ReplyConfirmLocalizedAsync(strs.autohentai_started(interval, string.Join(", ", tags))); + await SendConfirmAsync($"Autohentai started. Interval: {interval}, Tags: {string.Join(", ", tags)}"); } [Cmd] diff --git a/src/NadekoBot/data/aliases.yml b/src/NadekoBot/data/aliases.yml index 5ffd3140c..2c5521fac 100644 --- a/src/NadekoBot/data/aliases.yml +++ b/src/NadekoBot/data/aliases.yml @@ -1,1212 +1,1215 @@ h: -- help -- h + - help + - h gencmdlist: -- gencmdlist + - gencmdlist donate: -- donate + - donate modules: -- modules -- mdls + - modules + - mdls commands: -- commands -- cmds + - commands + - cmds greetdel: -- greetdel -- grdel + - greetdel + - grdel greet: -- greet + - greet greetmsg: -- greetmsg + - greetmsg bye: -- bye + - bye byemsg: -- byemsg + - byemsg byedel: -- byedel + - byedel greetdm: -- greetdm + - greetdm greettest: -- greettest + - greettest greetdmtest: -- greetdmtest + - greetdmtest byetest: -- byetest + - byetest boost: -- boost + - boost boostmsg: -- boostmsg + - boostmsg boostdel: -- boostdel + - boostdel logserver: -- logserver + - logserver logignore: -- logignore + - logignore repeatlist: -- repeatlist -- replst -- replist -- repli + - repeatlist + - replst + - replist + - repli repeatremove: -- repeatremove -- reprm + - repeatremove + - reprm repeatinvoke: -- repeatinvoke -- repinv + - repeatinvoke + - repinv repeat: -- repeat + - repeat repeatredundant: -- repeatredun -- repred + - repeatredun + - repred rotateplaying: -- rotateplaying -- ropl + - rotateplaying + - ropl addplaying: -- addplaying -- adpl + - addplaying + - adpl listplaying: -- listplaying -- lipl + - listplaying + - lipl removeplaying: -- removeplaying -- rmpl + - removeplaying + - rmpl vcrolelist: -- vcrolelist + - vcrolelist vcrole: -- vcrole + - vcrole vcrolerm: -- vcrolerm + - vcrolerm asar: -- asar + - asar rsar: -- rsar + - rsar lsar: -- lsar + - lsar sargn: -- sargn + - sargn togglexclsar: -- togglexclsar -- tesar + - togglexclsar + - tesar iam: -- iam + - iam iamnot: -- iamnot -- iamn + - iamnot + - iamn fwclear: -- fwclear + - fwclear aliasesclear: -- aliasesclear -- aliasclear + - aliasesclear + - aliasclear autoassignrole: -- autoassignrole -- aar + - autoassignrole + - aar leave: -- leave + - leave slowmode: -- slowmode + - slowmode delmsgoncmd: -- delmsgoncmd -- dmc + - delmsgoncmd + - dmc restart: -- restart + - restart setrole: -- setrole -- sr -- giverole + - setrole + - sr + - giverole removerole: -- removerole -- rr + - removerole + - rr renamerole: -- renamerole -- renr + - renamerole + - renr removeallroles: -- removeallroles -- rar + - removeallroles + - rar rolehoist: -- rolehoist -- rh + - rolehoist + - rh createrole: -- createrole -- cr + - createrole + - cr deleterole: -- deleterole -- dr + - deleterole + - dr rolecolor: -- rolecolor -- roleclr + - rolecolor + - roleclr ban: -- ban -- b + - ban + - b softban: -- softban -- sb + - softban + - sb kick: -- kick -- k + - kick + - k mute: -- mute + - mute voiceunmute: -- voiceunmute + - voiceunmute deafen: -- deafen -- deaf + - deafen + - deaf undeafen: -- undeafen -- undef + - undeafen + - undef delvoichanl: -- delvoichanl -- dvch + - delvoichanl + - dvch creatvoichanl: -- creatvoichanl -- cvch + - creatvoichanl + - cvch deltxtchanl: -- deltxtchanl -- dtch + - deltxtchanl + - dtch creatxtchanl: -- creatxtchanl -- ctch + - creatxtchanl + - ctch settopic: -- settopic -- st + - settopic + - st setchanlname: -- setchanlname -- schn + - setchanlname + - schn prune: -- prune -- clear + - prune + - clear die: -- die + - die setname: -- setname -- newnm + - setname + - newnm setnick: -- setnick + - setnick setavatar: -- setavatar -- setav + - setavatar + - setav setgame: -- setgame + - setgame send: -- send + - send savechat: -- savechat + - savechat remind: -- remind + - remind reminddelete: -- reminddelete -- remindrm -- reminddel + - reminddelete + - remindrm + - reminddel remindlist: -- remindlist -- remindl -- remindlst + - remindlist + - remindl + - remindlst serverinfo: -- serverinfo -- sinfo + - serverinfo + - sinfo channelinfo: -- channelinfo -- cinfo + - channelinfo + - cinfo userinfo: -- userinfo -- uinfo + - userinfo + - uinfo whosplaying: -- whosplaying -- whpl + - whosplaying + - whpl inrole: -- inrole + - inrole checkperms: -- checkperms + - checkperms stats: -- stats + - stats userid: -- userid -- uid + - userid + - uid channelid: -- channelid -- cid + - channelid + - cid serverid: -- serverid -- sid + - serverid + - sid roles: -- roles + - roles channeltopic: -- channeltopic -- ct + - channeltopic + - ct chnlfilterinv: -- chnlfilterinv -- cfi + - chnlfilterinv + - cfi srvrfilterinv: -- srvrfilterinv -- sfi + - srvrfilterinv + - sfi chnlfilterlin: -- chnlfilterlin -- cfl + - chnlfilterlin + - cfl srvrfilterlin: -- srvrfilterlin -- sfl + - srvrfilterlin + - sfl chnlfilterwords: -- chnlfilterwords -- cfw + - chnlfilterwords + - cfw filterword: -- filterword -- fw + - filterword + - fw srvrfilterwords: -- srvrfilterwords -- sfw + - srvrfilterwords + - sfw lstfilterwords: -- lstfilterwords -- lfw + - lstfilterwords + - lfw permrole: -- permrole -- pr + - permrole + - pr verbose: -- verbose -- v + - verbose + - v srvrmdl: -- srvrmdl -- sm + - srvrmdl + - sm srvrcmd: -- srvrcmd -- sc + - srvrcmd + - sc rolemdl: -- rolemdl -- rm + - rolemdl + - rm rolecmd: -- rolecmd -- rc + - rolecmd + - rc chnlmdl: -- chnlmdl -- cm + - chnlmdl + - cm chnlcmd: -- chnlcmd -- cc + - chnlcmd + - cc usrmdl: -- usrmdl -- um + - usrmdl + - um usrcmd: -- usrcmd -- uc + - usrcmd + - uc allsrvrmdls: -- allsrvrmdls -- asm + - allsrvrmdls + - asm allchnlmdls: -- allchnlmdls -- acm + - allchnlmdls + - acm allrolemdls: -- allrolemdls -- arm + - allrolemdls + - arm userblacklist: -- userblacklist -- ubl + - userblacklist + - ubl channelblacklist: -- channelblacklist -- cbl + - channelblacklist + - cbl serverblacklist: -- serverblacklist -- sbl + - serverblacklist + - sbl cmdcooldown: -- cmdcooldown -- cmdcd + - cmdcooldown + - cmdcd allcmdcooldowns: -- allcmdcooldowns -- cmdcds + - allcmdcooldowns + - cmdcds quoteadd: -- quoteadd -- . + - quoteadd + - . quoteprint: -- quoteprint -- .. + - quoteprint + - .. quoteshow: -- quoteshow -- qshow + - quoteshow + - qshow quotesearch: -- quotesearch -- qsearch + - quotesearch + - qsearch quoteid: -- quoteid -- qid + - quoteid + - qid quotedelete: -- quotedelete -- qdel + - quotedelete + - qdel draw: -- draw + - draw drawnew: -- drawnew + - drawnew playlistshuffle: -- playlistshuffle -- shuffle -- sh -- plsh + - playlistshuffle + - shuffle + - sh + - plsh flip: -- flip + - flip betflip: -- betflip -- bf + - betflip + - bf +betdraw: + - betdraw + - bd roll: -- roll + - roll rolluo: -- rolluo + - rolluo nroll: -- nroll + - nroll race: -- race + - race joinrace: -- joinrace -- jr + - joinrace + - jr nunchi: -- nunchi + - nunchi connect4: -- connect4 -- con4 + - connect4 + - con4 raffle: -- raffle + - raffle raffleany: -- raffleany + - raffleany give: -- give + - give award: -- award + - award take: -- take + - take betroll: -- betroll -- br + - betroll + - br luckyladder: -- luckyladder -- lula -- wheel -- wof + - luckyladder + - lula + - wheel + - wof leaderboard: -- leaderboard -- lb + - leaderboard + - lb trivia: -- trivia -- t + - trivia + - t tl: -- tl + - tl tq: -- tq + - tq typestart: -- typestart + - typestart typestop: -- typestop + - typestop typeadd: -- typeadd + - typeadd pollend: -- pollend + - pollend pick: -- pick + - pick plant: -- plant + - plant gencurrency: -- gencurrency -- gc + - gencurrency + - gc gencurlist: -- gencurlist -- gclist + - gencurlist + - gclist choose: -- choose + - choose rps: -- rps + - rps linux: -- linux + - linux next: -- next -- n + - next + - n play: -- play -- p -- start + - play + - p + - start stop: -- stop -- s + - stop + - s destroy: -- destroy -- d + - destroy + - d pause: -- pause + - pause queue: -- queue -- q -- yq -- enqueue + - queue + - q + - yq + - enqueue queuenext: -- queuenext -- qn + - queuenext + - qn queuesearch: -- queuesearch -- qs -- yqs + - queuesearch + - qs + - yqs soundcloudqueue: -- soundcloudqueue -- sq + - soundcloudqueue + - sq listqueue: -- listqueue -- lq + - listqueue + - lq nowplaying: -- nowplaying -- np + - nowplaying + - np volume: -- volume -- vol -- defvol + - volume + - vol + - defvol playlist: -- playlist -- pl + - playlist + - pl soundcloudpl: -- soundcloudpl -- scpl + - soundcloudpl + - scpl localplaylist: -- localplaylist -- lopl + - localplaylist + - lopl radio: -- radio -- ra + - radio + - ra local: -- local -- lo + - local + - lo join: -- join -- j -- move -- mv + - join + - j + - move + - mv trackremove: -- songremove -- srm -- trackremove -- trm + - songremove + - srm + - trackremove + - trm trackmove: -- trackmove -- tm -- movesong -- ms + - trackmove + - tm + - movesong + - ms queuerepeat: -- queuerepeat -- qrp -- rpl + - queuerepeat + - qrp + - rpl queueautoplay: -- queueautoplay -- qap + - queueautoplay + - qap save: -- save + - save streamrole: -- streamrole + - streamrole load: -- load + - load playlists: -- playlists -- pls + - playlists + - pls playlistshow: -- playlistshow -- plshow + - playlistshow + - plshow deleteplaylist: -- deleteplaylist -- delpls + - deleteplaylist + - delpls streamadd: -- streamadd -- sta -- stadd + - streamadd + - sta + - stadd streamremove: -- streamremove -- strm + - streamremove + - strm streamsclear: - streamsclear - stclear streamlist: -- streamlist -- stl -- streamslist + - streamlist + - stl + - streamslist streamoffline: -- streamoffline -- sto -- stoff + - streamoffline + - sto + - stoff streamonlinedelete: -- streamonlinedelete -- stondel + - streamonlinedelete + - stondel streammessage: -- streammsg -- stm -- stmsg + - streammsg + - stm + - stmsg streammessageall: -- streammsgall -- stma -- stmsga + - streammsgall + - stma + - stmsga streamcheck: -- streamcheck -- stc + - streamcheck + - stc convert: -- convert + - convert convertlist: -- convertlist + - convertlist wowjoke: -- wowjoke + - wowjoke calculate: -- calculate -- calc + - calculate + - calc osu: -- osu + - osu gatari: -- gatari + - gatari osu5: -- osu5 + - osu5 pokemon: -- pokemon -- poke + - pokemon + - poke pokemonability: -- pokemonability -- pokeab + - pokemonability + - pokeab memelist: -- memelist + - memelist memegen: -- memegen + - memegen weather: -- weather -- we + - weather + - we youtube: -- youtube -- yt + - youtube + - yt anime: -- anime -- ani -- aq + - anime + - ani + - aq steam: -- steam + - steam movie: -- movie -- omdb -- imdb + - movie + - omdb + - imdb manga: -- manga -- mang -- mq + - manga + - mang + - mq randomcat: -- randomcat -- meow + - randomcat + - meow randomdog: -- randomdog -- woof + - randomdog + - woof randomfood: -- randomfood -- yum + - randomfood + - yum randombird: -- randombird -- birb -- bird + - randombird + - birb + - bird image: -- image -- img -- rimg + - image + - img + - rimg lmgtfy: -- lmgtfy + - lmgtfy google: - google - search - g - s hearthstone: -- hearthstone -- hs + - hearthstone + - hs urbandict: -- urbandict -- ud + - urbandict + - ud catfact: -- catfact + - catfact yomama: -- yomama -- ym + - yomama + - ym randjoke: -- randjoke -- rj + - randjoke + - rj chucknorris: -- chucknorris -- cn + - chucknorris + - cn magicitem: -- magicitem -- mi + - magicitem + - mi revav: -- revav + - revav revimg: -- revimg + - revimg safebooru: -- safebooru + - safebooru wiki: -- wiki -- wikipedia + - wiki + - wikipedia color: -- color -- clr + - color + - clr avatar: -- avatar -- av + - avatar + - av hentai: -- hentai + - hentai nhentai: - nhentai danbooru: -- danbooru + - danbooru derpibooru: -- derpibooru -- derpi + - derpibooru + - derpi gelbooru: -- gelbooru + - gelbooru rule34: -- rule34 + - rule34 e621: -- e621 + - e621 boobs: -- boobs + - boobs butts: -- butts -- ass -- butt + - butts + - ass + - butt translate: -- translate -- trans + - translate + - trans translangs: -- translangs + - translangs guide: -- guide -- readme + - guide + - readme calcops: -- calcops + - calcops delallquotes: -- delallquotes -- daq -- delallq + - delallquotes + - daq + - delallq greetdmmsg: -- greetdmmsg + - greetdmmsg cash: -- cash -- $ -- currency -- $$ -- $$$ -- cur + - cash + - $ + - currency + - $$ + - $$$ + - cur currencytransactions: -- curtrs + - curtrs currencytransaction: - curtr listperms: -- listperms -- lp + - listperms + - lp allusrmdls: -- allusrmdls -- aum + - allusrmdls + - aum moveperm: -- moveperm -- mp + - moveperm + - mp removeperm: -- removeperm -- rp + - removeperm + - rp showemojis: -- showemojis -- se + - showemojis + - se emojiadd: -- emojiadd -- ea + - emojiadd + - ea deckshuffle: -- deckshuffle -- dsh + - deckshuffle + - dsh forwardmessages: -- forwardmessages -- fwmsgs + - forwardmessages + - fwmsgs forwardtoall: -- forwardtoall -- fwtoall + - forwardtoall + - fwtoall resetperms: -- resetperms + - resetperms antiraid: -- antiraid + - antiraid antispam: -- antispam + - antispam antialt: -- antialt + - antialt chatmute: -- chatmute + - chatmute voicemute: -- voicemute + - voicemute konachan: -- konachan + - konachan sankaku: - sankaku muterole: -- muterole -- setmuterole + - muterole + - setmuterole adsarm: -- adsarm + - adsarm setstream: -- setstream + - setstream chatunmute: -- chatunmute + - chatunmute unmute: -- unmute + - unmute xkcd: -- xkcd + - xkcd placelist: -- placelist + - placelist place: -- place + - place poll: -- poll -- ppoll + - poll + - ppoll autotranslang: -- autotranslang -- atl + - autotranslang + - atl autotranslate: -- autotranslate -- at -- autotrans + - autotranslate + - at + - autotrans listquotes: -- listquotes -- liqu + - listquotes + - liqu typedel: -- typedel + - typedel typelist: -- typelist + - typelist listservers: -- listservers + - listservers hentaibomb: -- hentaibomb + - hentaibomb cleverbot: -- cleverbot + - cleverbot shorten: -- shorten + - shorten wikia: -- wikia -- fandom + - wikia + - fandom yandere: -- yandere + - yandere magicthegathering: -- magicthegathering -- mtg + - magicthegathering + - mtg hangmanlist: -- hangmanlist + - hangmanlist hangman: -- hangman + - hangman hangmanstop: -- hangmanstop + - hangmanstop acrophobia: -- acrophobia -- acro + - acrophobia + - acro logevents: -- logevents + - logevents log: -- log + - log autodisconnect: -- autodisconnect -- autodc + - autodisconnect + - autodc define: -- define -- def + - define + - def activity: -- activity + - activity autohentai: -- autohentai + - autohentai setstatus: -- setstatus + - setstatus invitecreate: -- invitecreate -- invcr + - invitecreate + - invcr invitelist: -- invitelist -- invlist -- invlst + - invitelist + - invlist + - invlst invitedelete: -- invitedelete -- invrm -- invdel + - invitedelete + - invrm + - invdel pollstats: -- pollstats + - pollstats antilist: -- antilist -- antilst + - antilist + - antilst antispamignore: -- antispamignore + - antispamignore eventstart: -- eventstart + - eventstart slotstats: -- slotstats -slottest: -- slottest + - slotstats +bettest: + - bettest slot: -- slot -- slots + - slot + - slots affinity: -- affinity -- waifuaff + - affinity + - waifuaff waifuclaim: -- waifuclaim -- claim + - waifuclaim + - claim waifureset: -- waifureset + - waifureset waifutransfer: -- waifutransfer + - waifutransfer waifugift: -- waifugift -- gift -- gifts + - waifugift + - gift + - gifts waifulb: -- waifulb -- waifus + - waifulb + - waifus divorce: -- divorce + - divorce waifuinfo: -- waifuinfo -- waifustats + - waifuinfo + - waifustats mal: -- mal + - mal setmusicchannel: -- setmusicchannel -- smch + - setmusicchannel + - smch unsetmusicchannel: -- unsetmusicchannel -- usmch + - unsetmusicchannel + - usmch musicquality: -- musicquality -- mquality + - musicquality + - mquality stringsreload: -- stringsreload + - stringsreload shardstats: -- shardstats + - shardstats restartshard: -- restartshard + - restartshard tictactoe: -- tictactoe -- ttt + - tictactoe + - ttt timezones: -- timezones + - timezones timezone: -- timezone + - timezone languagesetdefault: -- langsetdefault -- langsetd + - langsetdefault + - langsetd languageset: -- languageset -- langset + - languageset + - langset languageslist: -- languageslist -- langli + - languageslist + - langli rategirl: -- rategirl + - rategirl aliaslist: -- aliaslist -- cmdmaplist -- aliases + - aliaslist + - cmdmaplist + - aliases alias: -- alias -- cmdmap + - alias + - cmdmap warnlog: -- warnlog + - warnlog warnlogall: -- warnlogall + - warnlogall warn: -- warn + - warn startupcommandadd: -- scadd -- startcmdadd + - scadd + - startcmdadd autocommandadd: -- acadd -- autocmdadd + - acadd + - autocmdadd startupcommandremove: -- scrm -- startcmdrm + - scrm + - startcmdrm autocommandremove: -- acrm -- autocmdrm + - acrm + - autocmdrm startupcommandsclear: -- scclear -- scclr + - scclear + - scclr startupcommandslist: -- sclist -- startcmdlist + - sclist + - startcmdlist autocommandslist: -- aclist -- autolist -- autocommands -- autocmdlist + - aclist + - autolist + - autocommands + - autocmdlist unban: -- unban + - unban banmessage: -- banmessage -- banmsg -- bantemplate -- bantemp + - banmessage + - banmsg + - bantemplate + - bantemp banmessagetest: -- banmsgtest + - banmsgtest banmsgreset: -- banmsgreset + - banmsgreset wait: -- wait + - wait warnexpire: -- warnexpire -- warne + - warnexpire + - warne warnclear: -- warnclear -- warnc + - warnclear + - warnc warnpunishlist: -- warnpunishlist -- warnpl + - warnpunishlist + - warnpl warnpunish: -- warnpunish -- warnp + - warnpunish + - warnp ping: -- ping + - ping time: -- time + - time shop: - shop shopadd: -- shopadd + - shopadd shopremove: -- shopremove -- shoprm + - shopremove + - shoprm shopchangeprice: -- shopchangeprice -- shopprice + - shopchangeprice + - shopprice shopchangename: -- shopchangename -- shopname + - shopchangename + - shopname shopswap: -- shopswap + - shopswap shopmove: -- shopmove + - shopmove buy: -- buy + - buy gamevoicechannel: -- gamevoicechannel -- gvc + - gamevoicechannel + - gvc shoplistadd: -- shoplistadd + - shoplistadd globalcommand: -- globalcommand -- gcmd + - globalcommand + - gcmd globalmodule: -- globalmodule -- gmod + - globalmodule + - gmod globalpermlist: -- globalpermlist -- gpl -- lgp -- globalperms -- listglobalperms + - globalpermlist + - gpl + - lgp + - globalperms + - listglobalperms resetglobalperms: -- resetglobalperms + - resetglobalperms prefix: -- prefix + - prefix defprefix: -- defprefix + - defprefix verboseerror: -- verboseerror -- ve + - verboseerror + - ve streamrolekeyword: -- streamrolekeyword -- srkw + - streamrolekeyword + - srkw streamroleblacklist: -- streamroleblacklist -- srbl + - streamroleblacklist + - srbl streamrolewhitelist: -- streamrolewhitelist -- srwl + - streamrolewhitelist + - srwl config: -- config -- conf + - config + - conf configreload: -- configreload -- creload -- confreload -- crel + - configreload + - creload + - confreload + - crel nsfwtagblacklist: -- nsfwtagbl -- nsfwtbl + - nsfwtagbl + - nsfwtbl experience: -- experience -- xp + - experience + - xp xptemplatereload: -- xptempreload -- xptr + - xptempreload + - xptr xpexclusionlist: -- xpexclusionlist -- xpexl + - xpexclusionlist + - xpexl xpexclude: -- xpexclude -- xpex + - xpexclude + - xpex xpnotify: -- xpnotify -- xpn + - xpnotify + - xpn xpleveluprewards: -- xplvluprewards -- xprews -- xpcrs -- xprrs -- xprolerewards -- xpcurrewards + - xplvluprewards + - xprews + - xpcrs + - xprrs + - xprolerewards + - xpcurrewards xprewsreset: -- xprewsreset + - xprewsreset xprolereward: -- xprolereward -- xprr + - xprolereward + - xprr xpcurrencyreward: -- xpcurreward -- xpcr + - xpcurreward + - xpcr xpleaderboard: -- xpleaderboard -- xplb + - xpleaderboard + - xplb xpgloballeaderboard: -- xpgleaderboard -- xpglb + - xpgleaderboard + - xpglb xpadd: -- xpadd + - xpadd clubcreate: -- clubcreate + - clubcreate clubtransfer: -- clubtransfer + - clubtransfer clubinformation: -- clubinfo + - clubinfo clubapply: -- clubapply + - clubapply clubaccept: -- clubaccept + - clubaccept clubleave: -- clubleave + - clubleave clubdisband: -- clubdisband + - clubdisband clubkick: -- clubkick + - clubkick clubban: -- clubban + - clubban clubunban: -- clubunban + - clubunban clubdescription: -- clubdesc + - clubdesc clubicon: -- clubicon + - clubicon clubapps: -- clubapps + - clubapps clubbans: -- clubbans + - clubbans clubleaderboard: -- clublb -- clubs + - clublb + - clubs clubadmin: -- clubadmin + - clubadmin autoboobs: -- autoboobs + - autoboobs autobutts: -- autobutts + - autobutts eightball: -- eightball -- 8ball + - eightball + - 8ball ytuploadnotif: -- ytuploadnotif -- yun + - ytuploadnotif + - yun feed: -- feed -- feedadd + - feed + - feedadd feedremove: -- feedremove -- feedrm -- feeddel + - feedremove + - feedrm + - feeddel feedlist: -- feedlist -- feeds + - feedlist + - feeds say: -- say + - say sqlexec: -- sqlexec + - sqlexec sqlselect: -- sqlselect + - sqlselect deletewaifus: -- deletewaifus + - deletewaifus deletewaifu: -- deletewaifu + - deletewaifu deletecurrency: -- deletecurrency + - deletecurrency deleteplaylists: -- deleteplaylists + - deleteplaylists deletexp: -- deletexp + - deletexp discordpermoverride: -- dpo + - dpo discordpermoverridelist: -- dpol -- dpoli + - dpol + - dpoli discordpermoverridereset: -- dpor + - dpor rafflecur: -- rafflecur + - rafflecur rip: -- rip + - rip timelyset: -- timelyset + - timelyset timely: -- timely + - timely timelyreset: -- timelyreset + - timelyreset crypto: -- crypto -- c + - crypto + - c rolelevelreq: -- rolelevelreq -- rlr + - rolelevelreq + - rlr massban: - massban masskill: -- masskill + - masskill pathofexile: -- pathofexile -- poe + - pathofexile + - poe pathofexileleagues: -- pathofexileleagues -- poel + - pathofexileleagues + - poel pathofexilecurrency: -- pathofexilecurrency -- poec + - pathofexilecurrency + - poec rollduel: -- rollduel + - rollduel reactionroleadd: -- reactionroleadd -- reroa + - reactionroleadd + - reroa reactionroleslist: -- reactionroleslist -- reroli + - reactionroleslist + - reroli reactionrolesremove: -- reactionrolesremove -- rerorm + - reactionrolesremove + - rerorm reactionrolesdeleteall: -- rerodeleteall -- rerodela + - rerodeleteall + - rerodela reactionrolestransfer: -- rerotransfer -- rerot + - rerotransfer + - rerot blackjack: -- blackjack -- bj + - blackjack + - bj hit: -- hit + - hit stand: -- stand + - stand double: -- double + - double xpreset: -- xpreset + - xpreset bible: -- bible + - bible edit: -- edit + - edit delete: -- delete -- del + - delete + - del roleid: -- roleid -- rid + - roleid + - rid nsfwtoggle: -- nsfwtoggle -- nsfw -- nsfwtgl + - nsfwtoggle + - nsfw + - nsfwtgl economy: -- economy + - economy purgeuser: -- purgeuser + - purgeuser imageonlychannel: - imageonlychannel - imageonly @@ -1279,6 +1282,7 @@ deleteemptyservers: - deleteemptyservers stock: - stock +# Medusa system medusaload: - medusaload - meload @@ -1303,10 +1307,11 @@ bankbalance: - balance - b - bal +# Patron patron: - patron patronmessage: - patronmessage - patronmsg -eval: +eval: - eval \ No newline at end of file diff --git a/src/NadekoBot/data/strings/commands/commands.en-US.yml b/src/NadekoBot/data/strings/commands/commands.en-US.yml index 1c429690e..05d79280d 100644 --- a/src/NadekoBot/data/strings/commands/commands.en-US.yml +++ b/src/NadekoBot/data/strings/commands/commands.en-US.yml @@ -653,7 +653,7 @@ rolluo: - "7" - "3d5" nroll: - desc: "Rolls in a given range. If you specify just one number instead of the range, it will role from 0 to that number." + desc: "Rolls in a given range. If you specify just one number instead of the range, it will roll from 0 to that number." args: - "5" - "5-15" @@ -2231,4 +2231,23 @@ eval: args: - "123 / 4.5f" - "await ctx.OkAsync();" - - 'await ctx.SendConfirmAsync("uwu");' \ No newline at end of file + - 'await ctx.SendConfirmAsync("uwu");' +betdraw: + desc: |- + Bet on the card value and/or color. Specify the amount followed by your guess. + You can specify `r` or `b` for red or black, and `h` or `l` for high or low. + You can specify only h/l or only r/b or both. + Returns are high but **7 always loses**. + args: + - "50 r" + - "200 b l" + - "1000 h" + - "38 hi black" +bettest: + desc: |- + Tests a betting command by specifying the name followed by the number of tests. Some have multiple variations. + See the list of all tests by specifying no parameters. + args: + - "" + - "betflip 1000" + - "slot 2000" diff --git a/src/NadekoBot/data/strings/responses/responses.en-US.json b/src/NadekoBot/data/strings/responses/responses.en-US.json index ba8d0d345..9d5338c54 100644 --- a/src/NadekoBot/data/strings/responses/responses.en-US.json +++ b/src/NadekoBot/data/strings/responses/responses.en-US.json @@ -81,7 +81,6 @@ "boostdel_on": "Boost messages will be deleted after {0} seconds.", "hierarchy": "You can't use this command on users with a role higher or equal than yours (or mine) in the role hierarchy.", "role_too_high": "You can't use this command with roles which are above your highest role, unless you're server administrator.", - "images_loading": "Images will be reloaded within a few seconds.", "insuf_perms_i": "I have insufficient permissions.", "insuf_perms_u": "You have insufficient permissions.", "invalid_format": "Invalid input format.", @@ -216,11 +215,13 @@ "better_luck": "Better luck next time ^_^", "br_win": "Congratulations! You won {0} for rolling above {1}", "deck_reshuffled": "Deck reshuffled.", - "flipped": "flipped {0}.", + "flipped": "Flipped {0}", "flip_guess": "You guessed it! You won {0}", "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.", + "cards": "Cards", + "hand_value": "Hand value", "gifted": "has gifted {0} to {1}", "has": "{0} has {1}", "heads": "Head", @@ -232,11 +233,13 @@ "no_more_cards": "No more cards in the deck.", "raffled_user": "Raffled user", "roll2": "Roll", - "slot_bet": "Bet", + "rolls": "Rolls", "slot_jackpot": "WOAAHHHHHH!!! Congratulations!!! x{0}", "slot_single": "A single {0}, x{1}", "slot_three": "Wow! Lucky! Three of a kind! x{0}", "slot_two": "Good job! Two {0} - bet x{1}", + "available_tests": "Available Tests", + "test_results_for": "Test results for {0}", "won": "Won", "multiplier": "Multiplier", "tails": "Tail", @@ -256,7 +259,6 @@ "usage": "Usage", "options": "Options", "requires": "Requires", - "autohentai_started": "Autohentai started. Reposting every {0}s with one of the following tags:\n{1}", "tag": "Tag", "animal_race": "Animal race", "animal_race_failed": "Failed to start since there was not enough participants.", @@ -319,7 +321,6 @@ "rps_win": "{0} won! {1} beats {2}", "submissions_closed": "Submissions closed", "animal_race_already_started": "Animal Race is already running.", - "total_average": "Total: {0} Average: {1}", "category": "Category", "cleverbot_disabled": "Disabled cleverbot on this server.", "cleverbot_enabled": "Enabled cleverbot on this server.", @@ -327,7 +328,6 @@ "curgen_enabled": "Currency generation has been enabled on this channel.", "curgen_pl": "{0} random {1} appeared!", "curgen_sn": "A random {0} appeared!", - "failed_loading_question": "Failed loading a question.", "game_started": "Game started", "hangman_game_started": "Hangman game started", "hangman_running": "Hangman game already running on this channel.", @@ -357,10 +357,7 @@ "vs": "{0} vs {1}", "attempting_to_queue": "Attempting to queue {0} tracks...", "dir_queue_complete": "Directory queue complete.", - "fairplay": "Fairplay", "finished_track": "Track Finished", - "fp_disabled": "Fair play disabled.", - "fp_enabled": "Fair play enabled.", "from_position": "From position", "id": "Id", "now_playing": "Now playing", @@ -447,10 +444,8 @@ "word_filter_channel_on": "Word filtering enabled on this channel.", "word_filter_server_off": "Word filtering disabled on this server.", "word_filter_server_on": "Word filtering enabled on this server.", - "avatar_none": "User {0} has no avatar set.", "abilities": "Abilities", "anime_no_fav": "No favorite anime yet", - "atl_ad_started": "Started automatic translation of messages on this channel. User messages will be auto-deleted.", "atl_removed": "your auto-translate language has been removed.", "atl_set": "Your auto-translate language has been set to {0}>{1}", "atl_started": "Started automatic translation of messages on this channel.", @@ -458,6 +453,8 @@ "atl_not_enabled": "Automatic translation is not enabled on this channel or you've provided an invalid language.", "bad_input_format": "Bad input format, or something went wrong.", "card_not_found": "Couldn't find that card.", + "card": "Card", + "guess": "Guess", "catfact": "fact", "chapters": "Chapters", "comic_number": "Comic #", @@ -483,7 +480,6 @@ "height_weight": "Height/Weight", "height_weight_val": "{0}m/{1}kg", "humidity": "Humidity", - "image_search_for": "Image search for:", "imdb_fail": "Failed to find that movie.", "invalid_lang": "Invalid source or target language.", "jokes_not_loaded": "Jokes not loaded.", @@ -506,7 +502,6 @@ "pokemon_none": "No pokemon found.", "rating": "Rating", "score": "Score:", - "search_for": "Search for:", "short_url": "Short url", "something_went_wrong": "Something went wrong.", "specify_search_params": "Please specify search parameters.", @@ -793,7 +788,6 @@ "config_prop_not_found": "Property {0} not found on {1} configuration", "config_list": "Config list", "bot_strings_reloaded": "Bot strings have been reloaded.", - "level_req": "Level Req.", "xpn_setting_global": "Global Level-Up notifications", "xpn_setting_server": "Server Level-Up notifications", "xpn_notif_channel": "In the channel where you sent the last message.", @@ -902,7 +896,6 @@ "mass_ban_in_progress": "Banning {0} users...", "mass_ban_completed": "Banned {0} users.", "mass_kill_completed": "Mass Banning and Blacklisting of {0} users is complete.", - "failed_finding_novel": "Can't find that novel. Make sure you've typed the exact full name, and that it exists on novelupdates.com", "club_transfered": "Ownership of the club {0} has been transferred to {1}", "club_transfer_failed": "Transfer failed. You must be the club owner. Target must be a member of your club.", "roll_duel_challenge": "challenged {1} for a roll duel for {2}", @@ -913,11 +906,6 @@ "account_not_found": "That account does not exist or is set to private.", "ninja_not_found": "Currency with that name was not found or an invalid league name was provided.", "leagues_not_found": "Unable to retrieve data from Path of Exile API.", - "reaction_roles_message": "**Roles:** {0}\n**Content:** {1}", - "no_reaction_roles": "There are no ReactionRole features enabled on this server.", - "reaction_cant_access": "I can't access {0} reaction. You can only use emotes from servers I'm in.", - "reaction_role_removed": "Removed ReactionRole message #{0}", - "reaction_roles_full": "You've reached the limit on ReactionRole messages. You have to delete some.", "reminder_list": "List of reminders", "reminder_server_list": "List of server reminders", "reminder_deleted": "Reminder #{0} was deleted.", @@ -966,7 +954,6 @@ "module_description_xp": "Gain xp based on chat activity, check users' xp cards", "module_description_medusa": "**Bot Owner only.** Load, unload and handle dynamic modules. Read more [here](https://nadekobot.readthedocs.io/en/latest/medusa/creating-a-medusa/)", "module_description_missing": "Description is missing for this module.", - "obsolete_use": "⚠ Obsolete, use {0} instead.", "purge_user_confirm": "Are you sure that you want to purge {0} from the database?", "expr_import_no_input": "Invalid input. No valid file upload or input text found.", "expr_import_invalid_data": "Unable to parse the file. Make sure it's a valid .yml file",