add: added timely boost bonus to gambling.yml

change: .betstats renamed to .gamblestats/.gs
add: added .betstats, .betstats <game> and .betstats <user> <game?> command which shows you your stats for gambling commands
This commit is contained in:
Kwoth
2024-11-04 10:42:05 +00:00
parent 619ddba4f8
commit c39c9061fd
20 changed files with 7565 additions and 193 deletions

View File

@@ -1,3 +0,0 @@
dotnet ef migrations remove -c SqliteContext -f -p src/NadekoBot/NadekoBot.csproj
dotnet ef migrations remove -c PostgreSqlContext -f -p src/NadekoBot/NadekoBot.csproj

View File

@@ -62,6 +62,7 @@ public abstract class NadekoContext : 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 NadekoContext : 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>()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,48 @@
using Microsoft.EntityFrameworkCore.Migrations;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace NadekoBot.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");
}
}
}

View File

@@ -3227,6 +3227,57 @@ namespace NadekoBot.Migrations.PostgreSql
b.ToTable("greetsettings", (string)null);
});
modelBuilder.Entity("NadekoBot.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("NadekoBot.Db.Models.AntiAltSetting", b =>
{
b.HasOne("NadekoBot.Db.Models.GuildConfig", null)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.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");
}
}
}

View File

@@ -43,7 +43,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("AntiAltSetting", (string)null);
b.ToTable("AntiAltSetting");
});
modelBuilder.Entity("NadekoBot.Db.Models.AntiRaidSetting", b =>
@@ -75,7 +75,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("AntiRaidSetting", (string)null);
b.ToTable("AntiRaidSetting");
});
modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamIgnore", b =>
@@ -97,7 +97,7 @@ namespace NadekoBot.Migrations
b.HasIndex("AntiSpamSettingId");
b.ToTable("AntiSpamIgnore", (string)null);
b.ToTable("AntiSpamIgnore");
});
modelBuilder.Entity("NadekoBot.Db.Models.AntiSpamSetting", b =>
@@ -129,7 +129,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("AntiSpamSetting", (string)null);
b.ToTable("AntiSpamSetting");
});
modelBuilder.Entity("NadekoBot.Db.Models.ArchivedTodoListModel", b =>
@@ -146,7 +146,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("TodosArchive", (string)null);
b.ToTable("TodosArchive");
});
modelBuilder.Entity("NadekoBot.Db.Models.AutoCommand", b =>
@@ -184,7 +184,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("AutoCommands", (string)null);
b.ToTable("AutoCommands");
});
modelBuilder.Entity("NadekoBot.Db.Models.AutoPublishChannel", b =>
@@ -207,7 +207,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("AutoPublishChannel", (string)null);
b.ToTable("AutoPublishChannel");
});
modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateChannel", b =>
@@ -235,7 +235,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId");
b.ToTable("AutoTranslateChannels", (string)null);
b.ToTable("AutoTranslateChannels");
});
modelBuilder.Entity("NadekoBot.Db.Models.AutoTranslateUser", b =>
@@ -263,7 +263,7 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("ChannelId", "UserId");
b.ToTable("AutoTranslateUsers", (string)null);
b.ToTable("AutoTranslateUsers");
});
modelBuilder.Entity("NadekoBot.Db.Models.BanTemplate", b =>
@@ -289,7 +289,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("BanTemplates", (string)null);
b.ToTable("BanTemplates");
});
modelBuilder.Entity("NadekoBot.Db.Models.BankUser", b =>
@@ -312,7 +312,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId")
.IsUnique();
b.ToTable("BankUsers", (string)null);
b.ToTable("BankUsers");
});
modelBuilder.Entity("NadekoBot.Db.Models.BlacklistEntry", b =>
@@ -332,7 +332,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("Blacklist", (string)null);
b.ToTable("Blacklist");
});
modelBuilder.Entity("NadekoBot.Db.Models.ClubApplicants", b =>
@@ -347,7 +347,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("ClubApplicants", (string)null);
b.ToTable("ClubApplicants");
});
modelBuilder.Entity("NadekoBot.Db.Models.ClubBans", b =>
@@ -362,7 +362,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("ClubBans", (string)null);
b.ToTable("ClubBans");
});
modelBuilder.Entity("NadekoBot.Db.Models.ClubInfo", b =>
@@ -398,7 +398,7 @@ namespace NadekoBot.Migrations
b.HasIndex("OwnerId")
.IsUnique();
b.ToTable("Clubs", (string)null);
b.ToTable("Clubs");
});
modelBuilder.Entity("NadekoBot.Db.Models.CommandAlias", b =>
@@ -423,7 +423,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("CommandAlias", (string)null);
b.ToTable("CommandAlias");
});
modelBuilder.Entity("NadekoBot.Db.Models.CommandCooldown", b =>
@@ -448,7 +448,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("CommandCooldown", (string)null);
b.ToTable("CommandCooldown");
});
modelBuilder.Entity("NadekoBot.Db.Models.CurrencyTransaction", b =>
@@ -486,7 +486,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("CurrencyTransactions", (string)null);
b.ToTable("CurrencyTransactions");
});
modelBuilder.Entity("NadekoBot.Db.Models.DelMsgOnCmdChannel", b =>
@@ -511,7 +511,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("DelMsgOnCmdChannel", (string)null);
b.ToTable("DelMsgOnCmdChannel");
});
modelBuilder.Entity("NadekoBot.Db.Models.DiscordPermOverride", b =>
@@ -537,7 +537,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "Command")
.IsUnique();
b.ToTable("DiscordPermOverrides", (string)null);
b.ToTable("DiscordPermOverrides");
});
modelBuilder.Entity("NadekoBot.Db.Models.DiscordUser", b =>
@@ -595,7 +595,7 @@ namespace NadekoBot.Migrations
b.HasIndex("Username");
b.ToTable("DiscordUser", (string)null);
b.ToTable("DiscordUser");
});
modelBuilder.Entity("NadekoBot.Db.Models.ExcludedItem", b =>
@@ -620,7 +620,7 @@ namespace NadekoBot.Migrations
b.HasIndex("XpSettingsId");
b.ToTable("ExcludedItem", (string)null);
b.ToTable("ExcludedItem");
});
modelBuilder.Entity("NadekoBot.Db.Models.FeedSub", b =>
@@ -649,7 +649,7 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("GuildConfigId", "Url");
b.ToTable("FeedSub", (string)null);
b.ToTable("FeedSub");
});
modelBuilder.Entity("NadekoBot.Db.Models.FilterChannelId", b =>
@@ -671,7 +671,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilterChannelId", (string)null);
b.ToTable("FilterChannelId");
});
modelBuilder.Entity("NadekoBot.Db.Models.FilterLinksChannelId", b =>
@@ -693,7 +693,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilterLinksChannelId", (string)null);
b.ToTable("FilterLinksChannelId");
});
modelBuilder.Entity("NadekoBot.Db.Models.FilterWordsChannelId", b =>
@@ -715,7 +715,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilterWordsChannelId", (string)null);
b.ToTable("FilterWordsChannelId");
});
modelBuilder.Entity("NadekoBot.Db.Models.FilteredWord", b =>
@@ -737,7 +737,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FilteredWord", (string)null);
b.ToTable("FilteredWord");
});
modelBuilder.Entity("NadekoBot.Db.Models.FlagTranslateChannel", b =>
@@ -760,7 +760,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "ChannelId")
.IsUnique();
b.ToTable("FlagTranslateChannel", (string)null);
b.ToTable("FlagTranslateChannel");
});
modelBuilder.Entity("NadekoBot.Db.Models.FollowedStream", b =>
@@ -794,7 +794,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("FollowedStream", (string)null);
b.ToTable("FollowedStream");
});
modelBuilder.Entity("NadekoBot.Db.Models.GCChannelId", b =>
@@ -816,7 +816,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("GCChannelId", (string)null);
b.ToTable("GCChannelId");
});
modelBuilder.Entity("NadekoBot.Db.Models.GamblingStats", b =>
@@ -842,7 +842,7 @@ namespace NadekoBot.Migrations
b.HasIndex("Feature")
.IsUnique();
b.ToTable("GamblingStats", (string)null);
b.ToTable("GamblingStats");
});
modelBuilder.Entity("NadekoBot.Db.Models.GiveawayModel", b =>
@@ -868,7 +868,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("GiveawayModel", (string)null);
b.ToTable("GiveawayModel");
});
modelBuilder.Entity("NadekoBot.Db.Models.GiveawayUser", b =>
@@ -891,7 +891,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GiveawayId", "UserId")
.IsUnique();
b.ToTable("GiveawayUser", (string)null);
b.ToTable("GiveawayUser");
});
modelBuilder.Entity("NadekoBot.Db.Models.GroupName", b =>
@@ -917,7 +917,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId", "Number")
.IsUnique();
b.ToTable("GroupName", (string)null);
b.ToTable("GroupName");
});
modelBuilder.Entity("NadekoBot.Db.Models.GuildConfig", b =>
@@ -1010,7 +1010,7 @@ namespace NadekoBot.Migrations
b.HasIndex("WarnExpireHours");
b.ToTable("GuildConfigs", (string)null);
b.ToTable("GuildConfigs");
});
modelBuilder.Entity("NadekoBot.Db.Models.HoneypotChannel", b =>
@@ -1024,7 +1024,7 @@ namespace NadekoBot.Migrations
b.HasKey("GuildId");
b.ToTable("HoneyPotChannels", (string)null);
b.ToTable("HoneyPotChannels");
});
modelBuilder.Entity("NadekoBot.Db.Models.IgnoredLogItem", b =>
@@ -1050,7 +1050,7 @@ namespace NadekoBot.Migrations
b.HasIndex("LogSettingId", "LogItemId", "ItemType")
.IsUnique();
b.ToTable("IgnoredLogChannels", (string)null);
b.ToTable("IgnoredLogChannels");
});
modelBuilder.Entity("NadekoBot.Db.Models.ImageOnlyChannel", b =>
@@ -1076,7 +1076,7 @@ namespace NadekoBot.Migrations
b.HasIndex("ChannelId")
.IsUnique();
b.ToTable("ImageOnlyChannels", (string)null);
b.ToTable("ImageOnlyChannels");
});
modelBuilder.Entity("NadekoBot.Db.Models.LogSetting", b =>
@@ -1150,7 +1150,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("LogSettings", (string)null);
b.ToTable("LogSettings");
});
modelBuilder.Entity("NadekoBot.Db.Models.MusicPlayerSettings", b =>
@@ -1187,7 +1187,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId")
.IsUnique();
b.ToTable("MusicPlayerSettings", (string)null);
b.ToTable("MusicPlayerSettings");
});
modelBuilder.Entity("NadekoBot.Db.Models.MusicPlaylist", b =>
@@ -1210,7 +1210,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("MusicPlaylists", (string)null);
b.ToTable("MusicPlaylists");
});
modelBuilder.Entity("NadekoBot.Db.Models.MutedUserId", b =>
@@ -1232,7 +1232,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("MutedUserId", (string)null);
b.ToTable("MutedUserId");
});
modelBuilder.Entity("NadekoBot.Db.Models.NCPixel", b =>
@@ -1264,7 +1264,7 @@ namespace NadekoBot.Migrations
b.HasIndex("OwnerId");
b.ToTable("NCPixel", (string)null);
b.ToTable("NCPixel");
});
modelBuilder.Entity("NadekoBot.Db.Models.NadekoExpression", b =>
@@ -1302,7 +1302,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("Expressions", (string)null);
b.ToTable("Expressions");
});
modelBuilder.Entity("NadekoBot.Db.Models.PatronUser", b =>
@@ -1328,7 +1328,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UniquePlatformUserId")
.IsUnique();
b.ToTable("Patrons", (string)null);
b.ToTable("Patrons");
});
modelBuilder.Entity("NadekoBot.Db.Models.Permissionv2", b =>
@@ -1368,7 +1368,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("Permissions", (string)null);
b.ToTable("Permissions");
});
modelBuilder.Entity("NadekoBot.Db.Models.PlantedCurrency", b =>
@@ -1405,7 +1405,7 @@ namespace NadekoBot.Migrations
b.HasIndex("MessageId")
.IsUnique();
b.ToTable("PlantedCurrency", (string)null);
b.ToTable("PlantedCurrency");
});
modelBuilder.Entity("NadekoBot.Db.Models.PlaylistSong", b =>
@@ -1439,7 +1439,7 @@ namespace NadekoBot.Migrations
b.HasIndex("MusicPlaylistId");
b.ToTable("PlaylistSong", (string)null);
b.ToTable("PlaylistSong");
});
modelBuilder.Entity("NadekoBot.Db.Models.Quote", b =>
@@ -1475,7 +1475,7 @@ namespace NadekoBot.Migrations
b.HasIndex("Keyword");
b.ToTable("Quotes", (string)null);
b.ToTable("Quotes");
});
modelBuilder.Entity("NadekoBot.Db.Models.ReactionRoleV2", b =>
@@ -1516,7 +1516,7 @@ namespace NadekoBot.Migrations
b.HasIndex("MessageId", "Emote")
.IsUnique();
b.ToTable("ReactionRoles", (string)null);
b.ToTable("ReactionRoles");
});
modelBuilder.Entity("NadekoBot.Db.Models.Reminder", b =>
@@ -1553,7 +1553,7 @@ namespace NadekoBot.Migrations
b.HasIndex("When");
b.ToTable("Reminders", (string)null);
b.ToTable("Reminders");
});
modelBuilder.Entity("NadekoBot.Db.Models.Repeater", b =>
@@ -1588,7 +1588,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("Repeaters", (string)null);
b.ToTable("Repeaters");
});
modelBuilder.Entity("NadekoBot.Db.Models.RewardedUser", b =>
@@ -1617,7 +1617,7 @@ namespace NadekoBot.Migrations
b.HasIndex("PlatformUserId")
.IsUnique();
b.ToTable("RewardedUsers", (string)null);
b.ToTable("RewardedUsers");
});
modelBuilder.Entity("NadekoBot.Db.Models.RotatingPlayingStatus", b =>
@@ -1637,7 +1637,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("RotatingStatus", (string)null);
b.ToTable("RotatingStatus");
});
modelBuilder.Entity("NadekoBot.Db.Models.SelfAssignedRole", b =>
@@ -1668,7 +1668,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "RoleId")
.IsUnique();
b.ToTable("SelfAssignableRoles", (string)null);
b.ToTable("SelfAssignableRoles");
});
modelBuilder.Entity("NadekoBot.Db.Models.ShopEntry", b =>
@@ -1714,7 +1714,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("ShopEntry", (string)null);
b.ToTable("ShopEntry");
});
modelBuilder.Entity("NadekoBot.Db.Models.ShopEntryItem", b =>
@@ -1736,7 +1736,7 @@ namespace NadekoBot.Migrations
b.HasIndex("ShopEntryId");
b.ToTable("ShopEntryItem", (string)null);
b.ToTable("ShopEntryItem");
});
modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredRole", b =>
@@ -1758,7 +1758,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("SlowmodeIgnoredRole", (string)null);
b.ToTable("SlowmodeIgnoredRole");
});
modelBuilder.Entity("NadekoBot.Db.Models.SlowmodeIgnoredUser", b =>
@@ -1780,7 +1780,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("SlowmodeIgnoredUser", (string)null);
b.ToTable("SlowmodeIgnoredUser");
});
modelBuilder.Entity("NadekoBot.Db.Models.StickyRole", b =>
@@ -1806,7 +1806,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "UserId")
.IsUnique();
b.ToTable("StickyRoles", (string)null);
b.ToTable("StickyRoles");
});
modelBuilder.Entity("NadekoBot.Db.Models.StreamOnlineMessage", b =>
@@ -1832,7 +1832,7 @@ namespace NadekoBot.Migrations
b.HasKey("Id");
b.ToTable("StreamOnlineMessages", (string)null);
b.ToTable("StreamOnlineMessages");
});
modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleBlacklistedUser", b =>
@@ -1857,7 +1857,7 @@ namespace NadekoBot.Migrations
b.HasIndex("StreamRoleSettingsId");
b.ToTable("StreamRoleBlacklistedUser", (string)null);
b.ToTable("StreamRoleBlacklistedUser");
});
modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleSettings", b =>
@@ -1889,7 +1889,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("StreamRoleSettings", (string)null);
b.ToTable("StreamRoleSettings");
});
modelBuilder.Entity("NadekoBot.Db.Models.StreamRoleWhitelistedUser", b =>
@@ -1914,7 +1914,7 @@ namespace NadekoBot.Migrations
b.HasIndex("StreamRoleSettingsId");
b.ToTable("StreamRoleWhitelistedUser", (string)null);
b.ToTable("StreamRoleWhitelistedUser");
});
modelBuilder.Entity("NadekoBot.Db.Models.TodoModel", b =>
@@ -1944,7 +1944,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("Todos", (string)null);
b.ToTable("Todos");
});
modelBuilder.Entity("NadekoBot.Db.Models.UnbanTimer", b =>
@@ -1969,7 +1969,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("UnbanTimer", (string)null);
b.ToTable("UnbanTimer");
});
modelBuilder.Entity("NadekoBot.Db.Models.UnmuteTimer", b =>
@@ -1994,7 +1994,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("UnmuteTimer", (string)null);
b.ToTable("UnmuteTimer");
});
modelBuilder.Entity("NadekoBot.Db.Models.UnroleTimer", b =>
@@ -2022,7 +2022,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("UnroleTimer", (string)null);
b.ToTable("UnroleTimer");
});
modelBuilder.Entity("NadekoBot.Db.Models.UserXpStats", b =>
@@ -2062,7 +2062,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId", "GuildId")
.IsUnique();
b.ToTable("UserXpStats", (string)null);
b.ToTable("UserXpStats");
});
modelBuilder.Entity("NadekoBot.Db.Models.VcRoleInfo", b =>
@@ -2087,7 +2087,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId");
b.ToTable("VcRoleInfo", (string)null);
b.ToTable("VcRoleInfo");
});
modelBuilder.Entity("NadekoBot.Db.Models.WaifuInfo", b =>
@@ -2122,7 +2122,7 @@ namespace NadekoBot.Migrations
b.HasIndex("WaifuId")
.IsUnique();
b.ToTable("WaifuInfo", (string)null);
b.ToTable("WaifuInfo");
});
modelBuilder.Entity("NadekoBot.Db.Models.WaifuItem", b =>
@@ -2147,7 +2147,7 @@ namespace NadekoBot.Migrations
b.HasIndex("WaifuInfoId");
b.ToTable("WaifuItem", (string)null);
b.ToTable("WaifuItem");
});
modelBuilder.Entity("NadekoBot.Db.Models.WaifuUpdate", b =>
@@ -2179,7 +2179,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("WaifuUpdates", (string)null);
b.ToTable("WaifuUpdates");
});
modelBuilder.Entity("NadekoBot.Db.Models.Warning", b =>
@@ -2222,7 +2222,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId");
b.ToTable("Warnings", (string)null);
b.ToTable("Warnings");
});
modelBuilder.Entity("NadekoBot.Db.Models.WarningPunishment", b =>
@@ -2253,7 +2253,7 @@ namespace NadekoBot.Migrations
b.HasAlternateKey("GuildId", "Count");
b.ToTable("WarningPunishment", (string)null);
b.ToTable("WarningPunishment");
});
modelBuilder.Entity("NadekoBot.Db.Models.XpCurrencyReward", b =>
@@ -2278,7 +2278,7 @@ namespace NadekoBot.Migrations
b.HasIndex("XpSettingsId");
b.ToTable("XpCurrencyReward", (string)null);
b.ToTable("XpCurrencyReward");
});
modelBuilder.Entity("NadekoBot.Db.Models.XpRoleReward", b =>
@@ -2307,7 +2307,7 @@ namespace NadekoBot.Migrations
b.HasIndex("XpSettingsId", "Level")
.IsUnique();
b.ToTable("XpRoleReward", (string)null);
b.ToTable("XpRoleReward");
});
modelBuilder.Entity("NadekoBot.Db.Models.XpSettings", b =>
@@ -2330,7 +2330,7 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildConfigId")
.IsUnique();
b.ToTable("XpSettings", (string)null);
b.ToTable("XpSettings");
});
modelBuilder.Entity("NadekoBot.Db.Models.XpShopOwnedItem", b =>
@@ -2360,7 +2360,7 @@ namespace NadekoBot.Migrations
b.HasIndex("UserId", "ItemType", "ItemKey")
.IsUnique();
b.ToTable("XpShopOwnedItem", (string)null);
b.ToTable("XpShopOwnedItem");
});
modelBuilder.Entity("NadekoBot.Services.GreetSettings", b =>
@@ -2396,7 +2396,45 @@ namespace NadekoBot.Migrations
b.HasIndex("GuildId", "GreetType")
.IsUnique();
b.ToTable("GreetSettings", (string)null);
b.ToTable("GreetSettings");
});
modelBuilder.Entity("NadekoBot.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("NadekoBot.Db.Models.AntiAltSetting", b =>

View File

@@ -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();
}
}

View File

@@ -11,7 +11,7 @@ namespace NadekoBot.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;
}

View File

@@ -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;
});
}
}

View File

@@ -37,7 +37,7 @@ public sealed class NewGamblingService : IGamblingService, INService
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, INService
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;

View File

@@ -4,6 +4,6 @@ namespace NadekoBot.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);
}

View File

@@ -77,7 +77,7 @@ public sealed class CurrencyService : ICurrencyService, INService
{
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, INService
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;
}

View File

@@ -1,8 +1,10 @@
using LinqToDB;
using LinqToDB.Data;
using LinqToDB.EntityFrameworkCore;
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Services.Currency;
using NadekoBot.Db.Models;
using System.Collections.Concurrent;
namespace NadekoBot.Services;
@@ -10,15 +12,11 @@ public sealed class GamblingTxTracker : ITxTracker, INService, 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, INService, 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, INService, 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, INService, 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
}

View File

@@ -848,6 +848,10 @@ eventstart:
- eventstart
betstats:
- betstats
- bs
gamblestats:
- gamblestats
- gs
bettest:
- bettest
slot:

View File

@@ -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

View File

@@ -3,7 +3,7 @@ if ($args.Length -eq 0) {
}
else {
$migrationName = $args[0]
dotnet ef migrations add $migrationName -c SqliteContext -p src/NadekoBot/NadekoBot.csproj
dotnet ef migrations add $migrationName -c PostgreSqlContext -p src/NadekoBot/NadekoBot.csproj
dotnet ef migrations add $migrationName -c SqliteContext -p NadekoBot.csproj
dotnet ef migrations add $migrationName -c PostgreSqlContext -p NadekoBot.csproj
}

View File

@@ -0,0 +1,3 @@
dotnet ef migrations remove -c SqliteContext -f -p NadekoBot.csproj
dotnet ef migrations remove -c PostgreSqlContext -f -p NadekoBot.csproj