added timely boost bonus to gambling.yml
.betstats renamed to .gamblestats/.gs added .betstats, .betstats <game> and .betstats <user> <game?> command which shows you your stats for gambling commands
This commit is contained in:
parent
39297c6f83
commit
7da8f2c403
21 changed files with 13690 additions and 6320 deletions
|
@ -11,9 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||
Dockerfile = Dockerfile
|
||||
ellie-menu.ps1 = ellie-menu.ps1
|
||||
LICENSE = LICENSE
|
||||
migrate.ps1 = migrate.ps1
|
||||
README.md = README.md
|
||||
remove-migrations.ps1 = remove-migrations.ps1
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EllieBot", "src\EllieBot\EllieBot.csproj", "{4D9001F7-B3E8-48FE-97AA-CFD36DA65A64}"
|
||||
|
@ -30,7 +28,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ellie.Marmalade", "src\Elli
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EllieBot.Voice", "src\EllieBot.Voice\EllieBot.Voice.csproj", "{1D93CE3C-80B4-49C7-A9A2-99988920AAEC}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EllieBot.GrpcApiBase", "src\EllieBot.GrpcApiBase\EllieBot.GrpcApiBase.csproj", "{3B71F0BF-AE6C-480C-AB88-FCE23EDC7D91}"
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EllieBot.GrpcApiBase", "src\EllieBot.GrpcApiBase\EllieBot.GrpcApiBase.csproj", "{3B71F0BF-AE6C-480C-AB88-FCE23EDC7D91}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
if ($args.Length -eq 0) {
|
||||
Write-Host "Please provide a migration name." -ForegroundColor Red
|
||||
}
|
||||
else {
|
||||
$migrationName = $args[0]
|
||||
dotnet ef migrations add $migrationName -o Migrations/Mysql -c SqliteContext -p src/EllieBot/EllieBot.csproj
|
||||
dotnet ef migrations add $migrationName -o Migrations/PostgreSql -c PostgreSqlContext -p src/EllieBot/EllieBot.csproj
|
||||
}
|
|
@ -62,6 +62,7 @@ public abstract class EllieContext : DbContext
|
|||
public DbSet<ArchivedTodoListModel> TodosArchive { get; set; }
|
||||
public DbSet<HoneypotChannel> HoneyPotChannels { get; set; }
|
||||
|
||||
|
||||
// public DbSet<GuildColors> GuildColors { get; set; }
|
||||
|
||||
|
||||
|
@ -73,6 +74,15 @@ public abstract class EllieContext : DbContext
|
|||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
#region UserBetStats
|
||||
|
||||
modelBuilder.Entity<UserBetStats>()
|
||||
.HasIndex(x => new { x.UserId, x.Game })
|
||||
.IsUnique();
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Flag Translate
|
||||
|
||||
modelBuilder.Entity<FlagTranslateChannel>()
|
||||
|
|
3902
src/EllieBot/Migrations/PostgreSql/20241105024753_betstats.Designer.cs
generated
Normal file
3902
src/EllieBot/Migrations/PostgreSql/20241105024753_betstats.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,48 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EllieBot.Migrations.PostgreSql
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class betstats : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "userbetstats",
|
||||
columns: table => new
|
||||
{
|
||||
id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
userid = table.Column<decimal>(type: "numeric(20,0)", nullable: false),
|
||||
game = table.Column<int>(type: "integer", nullable: false),
|
||||
wincount = table.Column<long>(type: "bigint", nullable: false),
|
||||
losecount = table.Column<long>(type: "bigint", nullable: false),
|
||||
totalbet = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
paidout = table.Column<decimal>(type: "numeric", nullable: false),
|
||||
maxwin = table.Column<long>(type: "bigint", nullable: false),
|
||||
maxbet = table.Column<long>(type: "bigint", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("pk_userbetstats", x => x.id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "ix_userbetstats_userid_game",
|
||||
table: "userbetstats",
|
||||
columns: new[] { "userid", "game" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "userbetstats");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using EllieBot.Db;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using EllieBot.Db;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
@ -801,6 +801,57 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.ToTable("discorduser", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<bool>("AllowTarget")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("allowtarget");
|
||||
|
||||
b.Property<bool>("AutoDeleteTrigger")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("autodeletetrigger");
|
||||
|
||||
b.Property<bool>("ContainsAnywhere")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("containsanywhere");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<bool>("DmResponse")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("dmresponse");
|
||||
|
||||
b.Property<decimal?>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<string>("Reactions")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("reactions");
|
||||
|
||||
b.Property<string>("Response")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("response");
|
||||
|
||||
b.Property<string>("Trigger")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("trigger");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_expressions");
|
||||
|
||||
b.ToTable("expressions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -1700,57 +1751,6 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.ToTable("ncpixel", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<bool>("AllowTarget")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("allowtarget");
|
||||
|
||||
b.Property<bool>("AutoDeleteTrigger")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("autodeletetrigger");
|
||||
|
||||
b.Property<bool>("ContainsAnywhere")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("containsanywhere");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("timestamp without time zone")
|
||||
.HasColumnName("dateadded");
|
||||
|
||||
b.Property<bool>("DmResponse")
|
||||
.HasColumnType("boolean")
|
||||
.HasColumnName("dmresponse");
|
||||
|
||||
b.Property<decimal?>("GuildId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("guildid");
|
||||
|
||||
b.Property<string>("Reactions")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("reactions");
|
||||
|
||||
b.Property<string>("Response")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("response");
|
||||
|
||||
b.Property<string>("Trigger")
|
||||
.HasColumnType("text")
|
||||
.HasColumnName("trigger");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_expressions");
|
||||
|
||||
b.ToTable("expressions", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.PatronUser", b =>
|
||||
{
|
||||
b.Property<decimal>("UserId")
|
||||
|
@ -3227,6 +3227,57 @@ namespace EllieBot.Migrations.PostgreSql
|
|||
b.ToTable("greetsettings", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Services.UserBetStats", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("id");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int>("Game")
|
||||
.HasColumnType("integer")
|
||||
.HasColumnName("game");
|
||||
|
||||
b.Property<long>("LoseCount")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("losecount");
|
||||
|
||||
b.Property<long>("MaxBet")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("maxbet");
|
||||
|
||||
b.Property<long>("MaxWin")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("maxwin");
|
||||
|
||||
b.Property<decimal>("PaidOut")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("paidout");
|
||||
|
||||
b.Property<decimal>("TotalBet")
|
||||
.HasColumnType("numeric")
|
||||
.HasColumnName("totalbet");
|
||||
|
||||
b.Property<decimal>("UserId")
|
||||
.HasColumnType("numeric(20,0)")
|
||||
.HasColumnName("userid");
|
||||
|
||||
b.Property<long>("WinCount")
|
||||
.HasColumnType("bigint")
|
||||
.HasColumnName("wincount");
|
||||
|
||||
b.HasKey("Id")
|
||||
.HasName("pk_userbetstats");
|
||||
|
||||
b.HasIndex("UserId", "Game")
|
||||
.IsUnique()
|
||||
.HasDatabaseName("ix_userbetstats_userid_game");
|
||||
|
||||
b.ToTable("userbetstats", (string)null);
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.GuildConfig", null)
|
||||
|
|
3011
src/EllieBot/Migrations/Sqlite/20241105024653_betstats.Designer.cs
generated
Normal file
3011
src/EllieBot/Migrations/Sqlite/20241105024653_betstats.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
47
src/EllieBot/Migrations/Sqlite/20241105024653_betstats.cs
Normal file
47
src/EllieBot/Migrations/Sqlite/20241105024653_betstats.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace EllieBot.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class betstats : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "UserBetStats",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||
.Annotation("Sqlite:Autoincrement", true),
|
||||
UserId = table.Column<ulong>(type: "INTEGER", nullable: false),
|
||||
Game = table.Column<int>(type: "INTEGER", nullable: false),
|
||||
WinCount = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
LoseCount = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
TotalBet = table.Column<decimal>(type: "TEXT", nullable: false),
|
||||
PaidOut = table.Column<decimal>(type: "TEXT", nullable: false),
|
||||
MaxWin = table.Column<long>(type: "INTEGER", nullable: false),
|
||||
MaxBet = table.Column<long>(type: "INTEGER", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_UserBetStats", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_UserBetStats_UserId_Game",
|
||||
table: "UserBetStats",
|
||||
columns: new[] { "UserId", "Game" },
|
||||
unique: true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "UserBetStats");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using EllieBot.Db;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using EllieBot.Db;
|
||||
|
||||
#nullable disable
|
||||
|
||||
|
@ -598,6 +598,44 @@ namespace EllieBot.Migrations
|
|||
b.ToTable("DiscordUser");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AllowTarget")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoDeleteTrigger")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("ContainsAnywhere")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("DmResponse")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong?>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Reactions")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Response")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Trigger")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Expressions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.ExcludedItem", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
@ -1267,44 +1305,6 @@ namespace EllieBot.Migrations
|
|||
b.ToTable("NCPixel");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.EllieExpression", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AllowTarget")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("AutoDeleteTrigger")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("ContainsAnywhere")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<DateTime?>("DateAdded")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<bool>("DmResponse")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<ulong?>("GuildId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("Reactions")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Response")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<string>("Trigger")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("Expressions");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.PatronUser", b =>
|
||||
{
|
||||
b.Property<ulong>("UserId")
|
||||
|
@ -2399,6 +2399,44 @@ namespace EllieBot.Migrations
|
|||
b.ToTable("GreetSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Services.UserBetStats", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<int>("Game")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("LoseCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("MaxBet")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("MaxWin")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<decimal>("PaidOut")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<decimal>("TotalBet")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
b.Property<ulong>("UserId")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<long>("WinCount")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("UserId", "Game")
|
||||
.IsUnique();
|
||||
|
||||
b.ToTable("UserBetStats");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("EllieBot.Db.Models.AntiAltSetting", b =>
|
||||
{
|
||||
b.HasOne("EllieBot.Db.Models.GuildConfig", null)
|
||||
|
|
|
@ -120,7 +120,7 @@ public partial class Gambling
|
|||
var extra = index == -1 ? "" : $"#{index + 1} {(index == 0 ? "🏆" : "")}";
|
||||
return $"{(int)(p.Progress / 60f * 100),-2}%|{new string('‣', p.Progress) + p.Animal.Icon + extra}";
|
||||
}))}
|
||||
|🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🏁🔚|";
|
||||
|🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁 🏁🔚|";
|
||||
|
||||
var msg = raceMessage;
|
||||
|
||||
|
|
|
@ -71,7 +71,65 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
}
|
||||
|
||||
[Cmd]
|
||||
[Priority(3)]
|
||||
public async Task BetStats()
|
||||
=> await BetStats(ctx.User, null);
|
||||
|
||||
[Cmd]
|
||||
[Priority(2)]
|
||||
public async Task BetStats(GamblingGame game)
|
||||
=> await BetStats(ctx.User, game);
|
||||
|
||||
[Cmd]
|
||||
[Priority(1)]
|
||||
public async Task BetStats([Leftover] IUser user)
|
||||
=> await BetStats(user, null);
|
||||
|
||||
[Cmd]
|
||||
[Priority(0)]
|
||||
public async Task BetStats(IUser user, GamblingGame? game)
|
||||
{
|
||||
var stats = await _gamblingTxTracker.GetUserStatsAsync(user.Id, game);
|
||||
|
||||
if (stats.Count == 0)
|
||||
stats = new()
|
||||
{
|
||||
new()
|
||||
{
|
||||
TotalBet = 1
|
||||
}
|
||||
};
|
||||
|
||||
var eb = _sender.CreateEmbed()
|
||||
.WithOkColor()
|
||||
.WithAuthor(user)
|
||||
.AddField("Total Won", N(stats.Sum(x => x.PaidOut)), true)
|
||||
.AddField("Biggest Win", N(stats.Max(x => x.MaxWin)), true)
|
||||
.AddField("Biggest Bet", N(stats.Max(x => x.MaxBet)), true)
|
||||
.AddField("# Bets", stats.Sum(x => x.WinCount + x.LoseCount), true)
|
||||
.AddField("Payout",
|
||||
(stats.Sum(x => x.PaidOut) / stats.Sum(x => x.TotalBet)).ToString("P2", Culture),
|
||||
true);
|
||||
if (game == null)
|
||||
{
|
||||
var favGame = stats.MaxBy(x => x.WinCount + x.LoseCount);
|
||||
eb.AddField("Favorite Game",
|
||||
favGame.Game + "\n" + Format.Italics((favGame.WinCount + favGame.LoseCount) + " plays"),
|
||||
true);
|
||||
}
|
||||
else
|
||||
{
|
||||
eb.WithDescription(game.ToString())
|
||||
.AddField("# Wins", stats.Sum(x => x.WinCount), true);
|
||||
}
|
||||
|
||||
await Response()
|
||||
.Embed(eb)
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async Task GamblingStats()
|
||||
{
|
||||
var stats = await _gamblingTxTracker.GetAllAsync();
|
||||
|
||||
|
@ -167,57 +225,8 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
return;
|
||||
}
|
||||
|
||||
if (Config.Timely.RequirePassword)
|
||||
if (Config.Timely.HasButton)
|
||||
{
|
||||
// var password = _service.GeneratePassword();
|
||||
//
|
||||
// var img = new Image<Rgba32>(100, 40);
|
||||
//
|
||||
// var font = _fonts.NotoSans.CreateFont(30);
|
||||
// var outlinePen = new SolidPen(Color.Black, 1f);
|
||||
// var strikeoutRun = new RichTextRun
|
||||
// {
|
||||
// Start = 0,
|
||||
// End = password.GetGraphemeCount(),
|
||||
// Font = font,
|
||||
// StrikeoutPen = new SolidPen(Color.White, 3),
|
||||
// TextDecorations = TextDecorations.Strikeout
|
||||
// };
|
||||
// // draw password on the image
|
||||
// img.Mutate(x =>
|
||||
// {
|
||||
// x.DrawText(new RichTextOptions(font)
|
||||
// {
|
||||
// HorizontalAlignment = HorizontalAlignment.Center,
|
||||
// VerticalAlignment = VerticalAlignment.Center,
|
||||
// FallbackFontFamilies = _fonts.FallBackFonts,
|
||||
// Origin = new(50, 20),
|
||||
// TextRuns = [strikeoutRun]
|
||||
// },
|
||||
// password,
|
||||
// Brushes.Solid(Color.White),
|
||||
// outlinePen);
|
||||
// });
|
||||
// using var stream = await img.ToStreamAsync();
|
||||
// var captcha = await Response()
|
||||
// .Embed(_sender.CreateEmbed()
|
||||
// .WithOkColor()
|
||||
// .WithImageUrl("attachment://timely.png"))
|
||||
// .File(stream, "timely.png")
|
||||
// .SendAsync();
|
||||
// try
|
||||
// {
|
||||
// var userInput = await GetUserInputAsync(ctx.User.Id, ctx.Channel.Id);
|
||||
// if (userInput?.ToLowerInvariant() != password?.ToLowerInvariant())
|
||||
// {
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
// finally
|
||||
// {
|
||||
// _ = captcha.DeleteAsync();
|
||||
// }
|
||||
|
||||
var interaction = CreateTimelyInteraction();
|
||||
var msg = await Response().Pending(strs.timely_button).Interaction(interaction).SendAsync();
|
||||
await msg.DeleteAsync();
|
||||
|
@ -249,6 +258,19 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
|
||||
|
||||
var val = Config.Timely.Amount;
|
||||
|
||||
var guildUsers = await (Config.BoostBonus
|
||||
.GuildIds
|
||||
?? new())
|
||||
.Select(x => ((IGuild)_client.GetGuild(x))?.GetUserAsync(ctx.User.Id))
|
||||
.WhenAll();
|
||||
|
||||
var boostGuildUser = guildUsers.FirstOrDefault(x => x?.PremiumSince is not null);
|
||||
var booster = boostGuildUser is not null;
|
||||
|
||||
if (booster)
|
||||
val += Config.BoostBonus.BaseTimelyBonus;
|
||||
|
||||
var patron = await _ps.GetPatronAsync(ctx.User.Id);
|
||||
|
||||
var percentBonus = (_ps.PercentBonus(patron) / 100f);
|
||||
|
@ -259,6 +281,15 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
|
||||
await _cs.AddAsync(ctx.User.Id, val, new("timely", "claim"));
|
||||
|
||||
if (booster)
|
||||
{
|
||||
var msg = GetText(strs.timely(N(val), period))
|
||||
+ "\n\n"
|
||||
+ $"*+{N(Config.BoostBonus.BaseTimelyBonus)} bonus for boosting {boostGuildUser.Guild}!*";
|
||||
|
||||
await Response().Confirm(msg).Interaction(inter).SendAsync();
|
||||
}
|
||||
else
|
||||
await Response().Confirm(strs.timely(N(val), period)).Interaction(inter).SendAsync();
|
||||
}
|
||||
|
||||
|
@ -370,7 +401,8 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
}
|
||||
|
||||
var embed = _sender.CreateEmbed()
|
||||
.WithTitle(GetText(strs.transactions(((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString()
|
||||
.WithTitle(GetText(strs.transactions(
|
||||
((SocketGuild)ctx.Guild)?.GetUser(userId)?.ToString()
|
||||
?? $"{userId}")))
|
||||
.WithOkColor();
|
||||
|
||||
|
@ -627,7 +659,9 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
}
|
||||
else
|
||||
{
|
||||
await Response().Error(strs.take_fail(N(amount), Format.Bold(user.ToString()), CurrencySign)).SendAsync();
|
||||
await Response()
|
||||
.Error(strs.take_fail(N(amount), Format.Bold(user.ToString()), CurrencySign))
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -648,7 +682,9 @@ public partial class Gambling : GamblingModule<GamblingService>
|
|||
}
|
||||
else
|
||||
{
|
||||
await Response().Error(strs.take_fail(N(amount), Format.Code(usrId.ToString()), CurrencySign)).SendAsync();
|
||||
await Response()
|
||||
.Error(strs.take_fail(N(amount), Format.Code(usrId.ToString()), CurrencySign))
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ namespace EllieBot.Modules.Gambling.Common;
|
|||
public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
||||
{
|
||||
[Comment("""DO NOT CHANGE""")]
|
||||
public int Version { get; set; } = 9;
|
||||
public int Version { get; set; } = 10;
|
||||
|
||||
[Comment("""Currency settings""")]
|
||||
public CurrencyConfig Currency { get; set; }
|
||||
|
@ -67,6 +67,11 @@ public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
|||
[Comment("""Slot config""")]
|
||||
public SlotsConfig Slots { get; set; }
|
||||
|
||||
[Comment("""
|
||||
Bonus config for server boosts
|
||||
""")]
|
||||
public BoostBonusConfig BoostBonus { get; set; }
|
||||
|
||||
public GamblingConfig()
|
||||
{
|
||||
BetRoll = new();
|
||||
|
@ -79,6 +84,7 @@ public sealed partial class GamblingConfig : ICloneable<GamblingConfig>
|
|||
Slots = new();
|
||||
LuckyLadder = new();
|
||||
BotCuts = new();
|
||||
BoostBonus = new();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -104,7 +110,7 @@ public partial class TimelyConfig
|
|||
How much currency will the users get every time they run .timely command
|
||||
setting to 0 or less will disable this feature
|
||||
""")]
|
||||
public int Amount { get; set; } = 0;
|
||||
public long Amount { get; set; } = 0;
|
||||
|
||||
[Comment("""
|
||||
How often (in hours) can users claim currency with .timely command
|
||||
|
@ -115,7 +121,7 @@ public partial class TimelyConfig
|
|||
[Comment("""
|
||||
Whether the users are required to type a password when they do timely.
|
||||
""")]
|
||||
public bool RequirePassword { get; set; } = true;
|
||||
public bool HasButton { get; set; } = true;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
|
@ -414,3 +420,17 @@ public sealed partial class BotCutConfig
|
|||
""")]
|
||||
public decimal ShopSaleCut { get; set; } = 0.1m;
|
||||
}
|
||||
|
||||
[Cloneable]
|
||||
public sealed partial class BoostBonusConfig
|
||||
{
|
||||
[Comment("Users will receive a bonus if they boost any of these servers")]
|
||||
public List<ulong> GuildIds { get; set; } =
|
||||
[
|
||||
117523346618318850
|
||||
];
|
||||
|
||||
[Comment("This bonus will be added before any other multiplier is applied to the .timely command")]
|
||||
|
||||
public long BaseTimelyBonus { get; set; } = 50;
|
||||
}
|
|
@ -144,8 +144,8 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
|
|||
ConfigPrinters.ToString,
|
||||
val => val >= 0);
|
||||
|
||||
AddParsedProp("timely.pass",
|
||||
gs => gs.Timely.RequirePassword,
|
||||
AddParsedProp("timely.btn",
|
||||
gs => gs.Timely.HasButton,
|
||||
bool.TryParse,
|
||||
ConfigPrinters.ToString);
|
||||
|
||||
|
@ -189,11 +189,11 @@ public sealed class GamblingConfigService : ConfigServiceBase<GamblingConfig>
|
|||
});
|
||||
}
|
||||
|
||||
if (data.Version < 9)
|
||||
if (data.Version < 10)
|
||||
{
|
||||
ModifyConfig(c =>
|
||||
{
|
||||
c.Version = 9;
|
||||
c.Version = 10;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
var won = (long)result.Won;
|
||||
if (won > 0)
|
||||
{
|
||||
await _cs.AddAsync(userId, won, new("lula", "win"));
|
||||
await _cs.AddAsync(userId, won, new("lula", result.Multiplier >= 1 ? "win" : "lose"));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -155,7 +155,7 @@ public sealed class NewGamblingService : IGamblingService, IEService
|
|||
var won = (long)result.Won;
|
||||
if (won > 0)
|
||||
{
|
||||
await _cs.AddAsync(userId, won, new("slot", "won"));
|
||||
await _cs.AddAsync(userId, won, new("slot", "win"));
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
|
@ -4,6 +4,6 @@ namespace EllieBot.Services;
|
|||
|
||||
public interface ITxTracker
|
||||
{
|
||||
Task TrackAdd(long amount, TxData? txData);
|
||||
Task TrackRemove(long amount, TxData? txData);
|
||||
Task TrackAdd(ulong userId, long amount, TxData? txData);
|
||||
Task TrackRemove(ulong userId, long amount, TxData? txData);
|
||||
}
|
|
@ -77,7 +77,7 @@ public sealed class CurrencyService : ICurrencyService, IEService
|
|||
{
|
||||
var wallet = await GetWalletAsync(userId);
|
||||
await wallet.Add(amount, txData);
|
||||
await _txTracker.TrackAdd(amount, txData);
|
||||
await _txTracker.TrackAdd(userId, amount, txData);
|
||||
}
|
||||
|
||||
public async Task AddAsync(
|
||||
|
@ -97,7 +97,7 @@ public sealed class CurrencyService : ICurrencyService, IEService
|
|||
var wallet = await GetWalletAsync(userId);
|
||||
var result = await wallet.Take(amount, txData);
|
||||
if (result)
|
||||
await _txTracker.TrackRemove(amount, txData);
|
||||
await _txTracker.TrackRemove(userId, amount, txData);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
using LinqToDB;
|
||||
using LinqToDB.Data;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using EllieBot.Common.ModuleBehaviors;
|
||||
using EllieBot.Services.Currency;
|
||||
using EllieBot.Db.Models;
|
||||
using System.Collections.Concurrent;
|
||||
|
||||
namespace EllieBot.Services;
|
||||
|
||||
|
@ -10,15 +12,11 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
{
|
||||
private static readonly IReadOnlySet<string> _gamblingTypes = new HashSet<string>(new[]
|
||||
{
|
||||
"lula",
|
||||
"betroll",
|
||||
"betflip",
|
||||
"blackjack",
|
||||
"betdraw",
|
||||
"slot",
|
||||
"lula", "betroll", "betflip", "blackjack", "betdraw", "slot",
|
||||
});
|
||||
|
||||
private ConcurrentDictionary<string, (decimal Bet, decimal PaidOut)> _stats = new();
|
||||
private NonBlocking.ConcurrentDictionary<string, (decimal Bet, decimal PaidOut)> globalStats = new();
|
||||
private ConcurrentBag<UserBetStats> userStats = new();
|
||||
|
||||
private readonly DbService _db;
|
||||
|
||||
|
@ -28,19 +26,22 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
}
|
||||
|
||||
public async Task OnReadyAsync()
|
||||
=> await Task.WhenAll(RunUserStatsCollector(), RunBetStatsCollector());
|
||||
|
||||
public async Task RunBetStatsCollector()
|
||||
{
|
||||
using var timer = new PeriodicTimer(TimeSpan.FromHours(1));
|
||||
while (await timer.WaitForNextTickAsync())
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
await using var trans = await ctx.Database.BeginTransactionAsync();
|
||||
|
||||
try
|
||||
{
|
||||
var keys = _stats.Keys;
|
||||
// update betstats
|
||||
var keys = globalStats.Keys;
|
||||
foreach (var key in keys)
|
||||
{
|
||||
if (_stats.TryRemove(key, out var stat))
|
||||
if (globalStats.TryRemove(key, out var stat))
|
||||
{
|
||||
await ctx.GetTable<GamblingStats>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
|
@ -49,11 +50,13 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
Bet = stat.Bet,
|
||||
PaidOut = stat.PaidOut,
|
||||
DateAdded = DateTime.UtcNow
|
||||
}, old => new()
|
||||
},
|
||||
old => new()
|
||||
{
|
||||
Bet = old.Bet + stat.Bet,
|
||||
PaidOut = old.PaidOut + stat.PaidOut,
|
||||
}, () => new()
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
Feature = key
|
||||
});
|
||||
|
@ -62,49 +65,244 @@ public sealed class GamblingTxTracker : ITxTracker, IEService, IReadyExecutor
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "An error occurred in gambling tx tracker");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await trans.CommitAsync();
|
||||
Log.Error(ex, "An error occurred in betstats gambling tx tracker");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task TrackAdd(long amount, TxData? txData)
|
||||
private async Task RunUserStatsCollector()
|
||||
{
|
||||
var timer = new PeriodicTimer(TimeSpan.FromSeconds(5));
|
||||
while (await timer.WaitForNextTickAsync())
|
||||
{
|
||||
try
|
||||
{
|
||||
if (userStats.Count == 0)
|
||||
continue;
|
||||
|
||||
var users = new List<UserBetStats>(userStats.Count + 5);
|
||||
|
||||
while (userStats.TryTake(out var s))
|
||||
users.Add(s);
|
||||
|
||||
if (users.Count == 0)
|
||||
continue;
|
||||
|
||||
foreach (var (k, x) in users.GroupBy(x => (x.UserId, x.Game))
|
||||
.ToDictionary(x => x.Key,
|
||||
x => x.Aggregate((a, b) => new()
|
||||
{
|
||||
WinCount = a.WinCount + b.WinCount,
|
||||
LoseCount = a.LoseCount + b.LoseCount,
|
||||
TotalBet = a.TotalBet + b.TotalBet,
|
||||
PaidOut = a.PaidOut + b.PaidOut,
|
||||
MaxBet = Math.Max(a.MaxBet, b.MaxBet),
|
||||
MaxWin = Math.Max(a.MaxWin, b.MaxWin),
|
||||
})))
|
||||
{
|
||||
// bulk upsert in the future
|
||||
await using var uow = _db.GetDbContext();
|
||||
await uow.GetTable<UserBetStats>()
|
||||
.InsertOrUpdateAsync(() => new()
|
||||
{
|
||||
UserId = k.UserId,
|
||||
Game = k.Game,
|
||||
WinCount = x.WinCount,
|
||||
LoseCount = Math.Max(0, x.LoseCount),
|
||||
TotalBet = x.TotalBet,
|
||||
PaidOut = x.PaidOut,
|
||||
MaxBet = x.MaxBet,
|
||||
MaxWin = x.MaxWin
|
||||
},
|
||||
o => new()
|
||||
{
|
||||
WinCount = o.WinCount + x.WinCount,
|
||||
LoseCount = Math.Max(0, o.LoseCount + x.LoseCount),
|
||||
TotalBet = o.TotalBet + x.TotalBet,
|
||||
PaidOut = o.PaidOut + x.PaidOut,
|
||||
MaxBet = Math.Max(o.MaxBet, x.MaxBet),
|
||||
MaxWin = Math.Max(o.MaxWin, x.MaxWin),
|
||||
},
|
||||
() => new()
|
||||
{
|
||||
UserId = k.UserId,
|
||||
Game = k.Game
|
||||
});
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "An error occurred in UserBetStats gambling tx tracker");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Task TrackAdd(ulong userId, long amount, TxData? txData)
|
||||
{
|
||||
if (txData is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (_gamblingTypes.Contains(txData.Type))
|
||||
{
|
||||
_stats.AddOrUpdate(txData.Type,
|
||||
globalStats.AddOrUpdate(txData.Type,
|
||||
_ => (0, amount),
|
||||
(_, old) => (old.Bet, old.PaidOut + amount));
|
||||
}
|
||||
|
||||
var mType = GetGameType(txData.Type);
|
||||
|
||||
if (mType is not { } type)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (txData.Type == "lula")
|
||||
{
|
||||
if (txData.Extra == "lose")
|
||||
{
|
||||
userStats.Add(new()
|
||||
{
|
||||
UserId = userId,
|
||||
Game = type,
|
||||
WinCount = 0,
|
||||
LoseCount = 0,
|
||||
TotalBet = 0,
|
||||
PaidOut = amount,
|
||||
MaxBet = 0,
|
||||
MaxWin = amount,
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
else if (txData.Type == "animalrace")
|
||||
{
|
||||
if (txData.Extra == "refund")
|
||||
{
|
||||
userStats.Add(new()
|
||||
{
|
||||
UserId = userId,
|
||||
Game = type,
|
||||
WinCount = 0,
|
||||
LoseCount = -1,
|
||||
TotalBet = -amount,
|
||||
PaidOut = 0,
|
||||
MaxBet = 0,
|
||||
MaxWin = 0,
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
userStats.Add(new UserBetStats()
|
||||
{
|
||||
UserId = userId,
|
||||
Game = type,
|
||||
WinCount = 1,
|
||||
LoseCount = -1,
|
||||
TotalBet = 0,
|
||||
PaidOut = amount,
|
||||
MaxBet = 0,
|
||||
MaxWin = amount,
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task TrackRemove(long amount, TxData? txData)
|
||||
public Task TrackRemove(ulong userId, long amount, TxData? txData)
|
||||
{
|
||||
if (txData is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
if (_gamblingTypes.Contains(txData.Type))
|
||||
{
|
||||
_stats.AddOrUpdate(txData.Type,
|
||||
globalStats.AddOrUpdate(txData.Type,
|
||||
_ => (amount, 0),
|
||||
(_, old) => (old.Bet + amount, old.PaidOut));
|
||||
}
|
||||
|
||||
var mType = GetGameType(txData.Type);
|
||||
|
||||
if (mType is not { } type)
|
||||
return Task.CompletedTask;
|
||||
|
||||
userStats.Add(new UserBetStats()
|
||||
{
|
||||
UserId = userId,
|
||||
Game = type,
|
||||
WinCount = 0,
|
||||
LoseCount = 1,
|
||||
TotalBet = amount,
|
||||
PaidOut = 0,
|
||||
MaxBet = amount,
|
||||
MaxWin = 0
|
||||
});
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static GamblingGame? GetGameType(string game)
|
||||
=> game switch
|
||||
{
|
||||
"lula" => GamblingGame.Lula,
|
||||
"betroll" => GamblingGame.Betroll,
|
||||
"betflip" => GamblingGame.Betflip,
|
||||
"blackjack" => GamblingGame.Blackjack,
|
||||
"betdraw" => GamblingGame.Betdraw,
|
||||
"slot" => GamblingGame.Slots,
|
||||
"animalrace" => GamblingGame.Race,
|
||||
_ => null
|
||||
};
|
||||
|
||||
public async Task<IReadOnlyCollection<GamblingStats>> GetAllAsync()
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
return await ctx.Set<GamblingStats>()
|
||||
.ToListAsyncEF();
|
||||
}
|
||||
|
||||
public async Task<List<UserBetStats>> GetUserStatsAsync(ulong userId, GamblingGame? game = null)
|
||||
{
|
||||
await using var ctx = _db.GetDbContext();
|
||||
|
||||
|
||||
if (game is null)
|
||||
return await ctx
|
||||
.GetTable<UserBetStats>()
|
||||
.Where(x => x.UserId == userId)
|
||||
.ToListAsync();
|
||||
|
||||
return await ctx
|
||||
.GetTable<UserBetStats>()
|
||||
.Where(x => x.UserId == userId && x.Game == game)
|
||||
.ToListAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UserBetStats
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public ulong UserId { get; set; }
|
||||
public GamblingGame Game { get; set; }
|
||||
public long WinCount { get; set; }
|
||||
public long LoseCount { get; set; }
|
||||
public decimal TotalBet { get; set; }
|
||||
public decimal PaidOut { get; set; }
|
||||
public long MaxWin { get; set; }
|
||||
public long MaxBet { get; set; }
|
||||
}
|
||||
|
||||
public enum GamblingGame
|
||||
{
|
||||
Betflip = 0,
|
||||
Bf = 0,
|
||||
Betroll = 1,
|
||||
Br = 1,
|
||||
Betdraw = 2,
|
||||
Bd = 2,
|
||||
Slots = 3,
|
||||
Slot = 3,
|
||||
Blackjack = 4,
|
||||
Bj = 4,
|
||||
Lula = 5,
|
||||
Race = 6,
|
||||
AnimalRace = 6
|
||||
}
|
|
@ -848,6 +848,10 @@ eventstart:
|
|||
- eventstart
|
||||
betstats:
|
||||
- betstats
|
||||
- bs
|
||||
gamblestats:
|
||||
- gamblestats
|
||||
- gs
|
||||
bettest:
|
||||
- bettest
|
||||
slot:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# DO NOT CHANGE
|
||||
version: 9
|
||||
version: 10
|
||||
# Currency settings
|
||||
currency:
|
||||
# What is the emoji/character which represents the currency
|
||||
|
@ -57,7 +57,7 @@ timely:
|
|||
# setting to 0 or less will disable this feature
|
||||
cooldown: 12
|
||||
# Whether the users are required to type a password when they do timely.
|
||||
requirePassword: true
|
||||
hasButton: true
|
||||
# How much will each user's owned currency decay over time.
|
||||
decay:
|
||||
# Percentage of user's current currency which will be deducted every 24h.
|
||||
|
@ -273,3 +273,10 @@ voteReward: 100
|
|||
slots:
|
||||
# Hex value of the color which the numbers on the slot image will have.
|
||||
currencyFontColor: ff0000
|
||||
# Bonus config for server boosts
|
||||
boostBonus:
|
||||
# Users will receive a bonus if they boost any of these servers
|
||||
guildIds:
|
||||
- 117523346618318850
|
||||
# This bonus will be added before any other multiplier is applied to the .timely command
|
||||
baseTimelyBonus: 50
|
||||
|
|
8
src/EllieBot/migrate.ps1
Normal file
8
src/EllieBot/migrate.ps1
Normal file
|
@ -0,0 +1,8 @@
|
|||
if ($args.Length -eq 0) {
|
||||
Write-Host "Please provide a migration name." -ForegroundColor Red
|
||||
}
|
||||
else {
|
||||
$migrationName = $args[0]
|
||||
dotnet ef migrations add $migrationName -c SqliteContext -p EllieBot.csproj
|
||||
dotnet ef migrations add $migrationName -c PostgreSqlContext -p EllieBot.csproj
|
||||
}
|
Loading…
Reference in a new issue