Started work on the xp system
This commit is contained in:
parent
e5609a0708
commit
088d95340f
@ -17,6 +17,8 @@
|
|||||||
CurrencyDropAmountMax,
|
CurrencyDropAmountMax,
|
||||||
MinimumBetAmount,
|
MinimumBetAmount,
|
||||||
TriviaCurrencyReward,
|
TriviaCurrencyReward,
|
||||||
|
XpPerMessage,
|
||||||
|
XpMinutesTimeout,
|
||||||
|
|
||||||
//ErrorColor, //after i fix the nadekobot.cs static variables
|
//ErrorColor, //after i fix the nadekobot.cs static variables
|
||||||
//OkColor
|
//OkColor
|
||||||
|
1825
src/NadekoBot/Migrations/20170821085106_xp-stuff.Designer.cs
generated
Normal file
1825
src/NadekoBot/Migrations/20170821085106_xp-stuff.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
153
src/NadekoBot/Migrations/20170821085106_xp-stuff.cs
Normal file
153
src/NadekoBot/Migrations/20170821085106_xp-stuff.cs
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
namespace NadekoBot.Migrations
|
||||||
|
{
|
||||||
|
public partial class xpstuff : Migration
|
||||||
|
{
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "XpMinutesTimeout",
|
||||||
|
table: "BotConfig",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "XpPerMessage",
|
||||||
|
table: "BotConfig",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: 0);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "UserXpStats",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
DateAdded = table.Column<DateTime>(nullable: true),
|
||||||
|
GuildId = table.Column<ulong>(nullable: false),
|
||||||
|
NotifyOnLevelUp = table.Column<bool>(nullable: false),
|
||||||
|
UserId = table.Column<ulong>(nullable: false),
|
||||||
|
Xp = table.Column<int>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_UserXpStats", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "XpSettings",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
DateAdded = table.Column<DateTime>(nullable: true),
|
||||||
|
GuildConfigId = table.Column<int>(nullable: false),
|
||||||
|
NotifyMessage = table.Column<string>(nullable: true),
|
||||||
|
ServerExcluded = table.Column<bool>(nullable: false),
|
||||||
|
XpRoleRewardExclusive = table.Column<bool>(nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_XpSettings", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_XpSettings_GuildConfigs_GuildConfigId",
|
||||||
|
column: x => x.GuildConfigId,
|
||||||
|
principalTable: "GuildConfigs",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ExcludedItem",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
DateAdded = table.Column<DateTime>(nullable: true),
|
||||||
|
ItemId = table.Column<ulong>(nullable: false),
|
||||||
|
ItemType = table.Column<int>(nullable: false),
|
||||||
|
XpSettingsId = table.Column<int>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ExcludedItem", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ExcludedItem_XpSettings_XpSettingsId",
|
||||||
|
column: x => x.XpSettingsId,
|
||||||
|
principalTable: "XpSettings",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "XpRoleReward",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
DateAdded = table.Column<DateTime>(nullable: true),
|
||||||
|
Level = table.Column<int>(nullable: false),
|
||||||
|
RoleId = table.Column<ulong>(nullable: false),
|
||||||
|
XpSettingsId = table.Column<int>(nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_XpRoleReward", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_XpRoleReward_XpSettings_XpSettingsId",
|
||||||
|
column: x => x.XpSettingsId,
|
||||||
|
principalTable: "XpSettings",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ExcludedItem_XpSettingsId",
|
||||||
|
table: "ExcludedItem",
|
||||||
|
column: "XpSettingsId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_UserXpStats_UserId_GuildId",
|
||||||
|
table: "UserXpStats",
|
||||||
|
columns: new[] { "UserId", "GuildId" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_XpRoleReward_XpSettingsId",
|
||||||
|
table: "XpRoleReward",
|
||||||
|
column: "XpSettingsId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_XpSettings_GuildConfigId",
|
||||||
|
table: "XpSettings",
|
||||||
|
column: "GuildConfigId",
|
||||||
|
unique: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ExcludedItem");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "UserXpStats");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "XpRoleReward");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "XpSettings");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "XpMinutesTimeout",
|
||||||
|
table: "BotConfig");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "XpPerMessage",
|
||||||
|
table: "BotConfig");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -183,6 +183,10 @@ namespace NadekoBot.Migrations
|
|||||||
|
|
||||||
b.Property<int>("TriviaCurrencyReward");
|
b.Property<int>("TriviaCurrencyReward");
|
||||||
|
|
||||||
|
b.Property<int>("XpMinutesTimeout");
|
||||||
|
|
||||||
|
b.Property<int>("XpPerMessage");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("BotConfig");
|
b.ToTable("BotConfig");
|
||||||
@ -445,6 +449,26 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("EightBallResponses");
|
b.ToTable("EightBallResponses");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded");
|
||||||
|
|
||||||
|
b.Property<ulong>("ItemId");
|
||||||
|
|
||||||
|
b.Property<int>("ItemType");
|
||||||
|
|
||||||
|
b.Property<int?>("XpSettingsId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("XpSettingsId");
|
||||||
|
|
||||||
|
b.ToTable("ExcludedItem");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -1252,6 +1276,29 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("PokeGame");
|
b.ToTable("PokeGame");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.UserXpStats", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded");
|
||||||
|
|
||||||
|
b.Property<ulong>("GuildId");
|
||||||
|
|
||||||
|
b.Property<bool>("NotifyOnLevelUp");
|
||||||
|
|
||||||
|
b.Property<ulong>("UserId");
|
||||||
|
|
||||||
|
b.Property<int>("Xp");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("UserId", "GuildId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("UserXpStats");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.VcRoleInfo", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@ -1393,6 +1440,49 @@ namespace NadekoBot.Migrations
|
|||||||
b.ToTable("WarningPunishment");
|
b.ToTable("WarningPunishment");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded");
|
||||||
|
|
||||||
|
b.Property<int>("Level");
|
||||||
|
|
||||||
|
b.Property<ulong>("RoleId");
|
||||||
|
|
||||||
|
b.Property<int?>("XpSettingsId");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("XpSettingsId");
|
||||||
|
|
||||||
|
b.ToTable("XpRoleReward");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd();
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DateAdded");
|
||||||
|
|
||||||
|
b.Property<int>("GuildConfigId");
|
||||||
|
|
||||||
|
b.Property<string>("NotifyMessage");
|
||||||
|
|
||||||
|
b.Property<bool>("ServerExcluded");
|
||||||
|
|
||||||
|
b.Property<bool>("XpRoleRewardExclusive");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("GuildConfigId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("XpSettings");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.AntiRaidSetting", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
||||||
@ -1470,6 +1560,13 @@ namespace NadekoBot.Migrations
|
|||||||
.HasForeignKey("BotConfigId");
|
.HasForeignKey("BotConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.ExcludedItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.XpSettings")
|
||||||
|
.WithMany("ExclusionList")
|
||||||
|
.HasForeignKey("XpSettingsId");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.FilterChannelId", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig")
|
||||||
@ -1707,6 +1804,21 @@ namespace NadekoBot.Migrations
|
|||||||
.WithMany("WarnPunishments")
|
.WithMany("WarnPunishments")
|
||||||
.HasForeignKey("GuildConfigId");
|
.HasForeignKey("GuildConfigId");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpRoleReward", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.XpSettings")
|
||||||
|
.WithMany("RoleRewards")
|
||||||
|
.HasForeignKey("XpSettingsId");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("NadekoBot.Services.Database.Models.XpSettings", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("NadekoBot.Services.Database.Models.GuildConfig", "GuildConfig")
|
||||||
|
.WithOne("XpSettings")
|
||||||
|
.HasForeignKey("NadekoBot.Services.Database.Models.XpSettings", "GuildConfigId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
public readonly ImmutableArray<string> EightBallResponses;
|
public readonly ImmutableArray<string> EightBallResponses;
|
||||||
|
|
||||||
private readonly Timer _t;
|
private readonly Timer _t;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly CommandHandler _cmd;
|
||||||
private readonly NadekoStrings _strings;
|
private readonly NadekoStrings _strings;
|
||||||
private readonly IImagesService _images;
|
private readonly IImagesService _images;
|
||||||
private readonly Logger _log;
|
private readonly Logger _log;
|
||||||
@ -38,11 +38,11 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
|
|
||||||
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
public List<TypingArticle> TypingArticles { get; } = new List<TypingArticle>();
|
||||||
|
|
||||||
public GamesService(DiscordSocketClient client, IBotConfigProvider bc, IEnumerable<GuildConfig> gcs,
|
public GamesService(CommandHandler cmd, IBotConfigProvider bc, IEnumerable<GuildConfig> gcs,
|
||||||
NadekoStrings strings, IImagesService images, CommandHandler cmdHandler)
|
NadekoStrings strings, IImagesService images, CommandHandler cmdHandler)
|
||||||
{
|
{
|
||||||
_bc = bc;
|
_bc = bc;
|
||||||
_client = client;
|
_cmd = cmd;
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
_images = images;
|
_images = images;
|
||||||
_cmdHandler = cmdHandler;
|
_cmdHandler = cmdHandler;
|
||||||
@ -59,7 +59,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
}, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1));
|
}, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1));
|
||||||
|
|
||||||
//plantpick
|
//plantpick
|
||||||
client.MessageReceived += PotentialFlowerGeneration;
|
_cmd.OnMessageNoTrigger += PotentialFlowerGeneration;
|
||||||
GenerationChannels = new ConcurrentHashSet<ulong>(gcs
|
GenerationChannels = new ConcurrentHashSet<ulong>(gcs
|
||||||
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
|
.SelectMany(c => c.GenerateCurrencyChannelIds.Select(obj => obj.ChannelId)));
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ namespace NadekoBot.Modules.Games.Services
|
|||||||
private string GetText(ITextChannel ch, string key, params object[] rep)
|
private string GetText(ITextChannel ch, string key, params object[] rep)
|
||||||
=> _strings.GetText(key, ch.GuildId, "Games".ToLowerInvariant(), rep);
|
=> _strings.GetText(key, ch.GuildId, "Games".ToLowerInvariant(), rep);
|
||||||
|
|
||||||
private Task PotentialFlowerGeneration(SocketMessage imsg)
|
private Task PotentialFlowerGeneration(IUserMessage imsg)
|
||||||
{
|
{
|
||||||
var msg = imsg as SocketUserMessage;
|
var msg = imsg as SocketUserMessage;
|
||||||
if (msg == null || msg.Author.IsBot)
|
if (msg == null || msg.Author.IsBot)
|
||||||
|
34
src/NadekoBot/Modules/Xp/Extensions/Extensions.cs
Normal file
34
src/NadekoBot/Modules/Xp/Extensions/Extensions.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using NadekoBot.Modules.Xp.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Xp.Extensions
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static (int Level, int LevelXp, int LevelRequiredXp) GetLevelData(this UserXpStats stats)
|
||||||
|
{
|
||||||
|
var baseXp = XpService.XP_REQUIRED_LVL_1;
|
||||||
|
|
||||||
|
var required = baseXp;
|
||||||
|
var totalXp = 0;
|
||||||
|
var lvl = 1;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
required = (int)(baseXp + baseXp / 4.0 * (lvl - 1));
|
||||||
|
|
||||||
|
if (required + totalXp > stats.Xp)
|
||||||
|
break;
|
||||||
|
|
||||||
|
totalXp += required;
|
||||||
|
lvl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (lvl - 1, stats.Xp - totalXp, required);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
src/NadekoBot/Modules/Xp/Services/UserCacheItem.cs
Normal file
18
src/NadekoBot/Modules/Xp/Services/UserCacheItem.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
namespace NadekoBot.Modules.Xp.Services
|
||||||
|
{
|
||||||
|
public class UserCacheItem
|
||||||
|
{
|
||||||
|
public ulong UserId { get; set; }
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return UserId.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is UserCacheItem uci && uci.UserId == UserId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
229
src/NadekoBot/Modules/Xp/Services/XpService.cs
Normal file
229
src/NadekoBot/Modules/Xp/Services/XpService.cs
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.WebSocket;
|
||||||
|
using NadekoBot.Common.Collections;
|
||||||
|
using NadekoBot.Services;
|
||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using NLog;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Xp.Services
|
||||||
|
{
|
||||||
|
public class XpService : INService
|
||||||
|
{
|
||||||
|
private readonly DbService _db;
|
||||||
|
private readonly CommandHandler _cmd;
|
||||||
|
private readonly IBotConfigProvider _bc;
|
||||||
|
private readonly Logger _log;
|
||||||
|
public const int XP_REQUIRED_LVL_1 = 36;
|
||||||
|
|
||||||
|
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedRoles
|
||||||
|
= new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>();
|
||||||
|
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedChannels
|
||||||
|
= new ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>>();
|
||||||
|
private readonly ConcurrentHashSet<ulong> _excludedServers = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
|
private readonly ConcurrentHashSet<ulong> _rewardedUsers = new ConcurrentHashSet<ulong>();
|
||||||
|
|
||||||
|
private readonly ConcurrentQueue<UserCacheItem> _addMessageXp = new ConcurrentQueue<UserCacheItem>();
|
||||||
|
|
||||||
|
private readonly Timer updateXpTimer;
|
||||||
|
private readonly Timer clearRewardedUsersTimer;
|
||||||
|
|
||||||
|
public XpService(CommandHandler cmd, IBotConfigProvider bc,
|
||||||
|
IEnumerable<GuildConfig> allGuildConfigs, DbService db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
_cmd = cmd;
|
||||||
|
_bc = bc;
|
||||||
|
_log = LogManager.GetCurrentClassLogger();
|
||||||
|
|
||||||
|
_cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger;
|
||||||
|
|
||||||
|
updateXpTimer = new Timer(_ =>
|
||||||
|
{
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
while (_addMessageXp.TryDequeue(out var usr))
|
||||||
|
{
|
||||||
|
var usrObj = uow.Xp.GetOrCreateUser(usr.GuildId, usr.UserId);
|
||||||
|
usrObj.Xp += _bc.BotConfig.XpPerMessage;
|
||||||
|
}
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
}, null, TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
|
||||||
|
|
||||||
|
clearRewardedUsersTimer = new Timer(_ =>
|
||||||
|
{
|
||||||
|
_rewardedUsers.Clear();
|
||||||
|
}, null, TimeSpan.FromSeconds(bc.BotConfig.XpMinutesTimeout), TimeSpan.FromSeconds(bc.BotConfig.XpMinutesTimeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task _cmd_OnMessageNoTrigger(IUserMessage arg)
|
||||||
|
{
|
||||||
|
if (!(arg.Author is SocketGuildUser user) || user.IsBot)
|
||||||
|
return Task.CompletedTask;
|
||||||
|
|
||||||
|
var _ = Task.Run(() =>
|
||||||
|
{
|
||||||
|
if (!SetUserRewarded(user.Id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_excludedChannels.TryGetValue(user.Guild.Id, out var chans) &&
|
||||||
|
chans.Contains(arg.Channel.Id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_excludedServers.Contains(user.Guild.Id))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_excludedRoles.TryGetValue(user.Guild.Id, out var roles) &&
|
||||||
|
user.Roles.Any(x => roles.Contains(x.Id)))
|
||||||
|
return;
|
||||||
|
|
||||||
|
_log.Info("Adding {0} xp to {1} on {2} server", _bc.BotConfig.XpPerMessage, user.ToString(), user.Guild.Name);
|
||||||
|
_addMessageXp.Enqueue(new UserCacheItem { GuildId = user.Guild.Id, UserId = user.Id });
|
||||||
|
});
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsServerExcluded(ulong id)
|
||||||
|
{
|
||||||
|
return _excludedServers.Contains(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ulong> GetExcludedRoles(ulong id)
|
||||||
|
{
|
||||||
|
if (_excludedRoles.TryGetValue(id, out var val))
|
||||||
|
return val.ToArray();
|
||||||
|
|
||||||
|
return Enumerable.Empty<ulong>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<ulong> GetExcludedChannels(ulong id)
|
||||||
|
{
|
||||||
|
if (_excludedChannels.TryGetValue(id, out var val))
|
||||||
|
return val.ToArray();
|
||||||
|
|
||||||
|
return Enumerable.Empty<ulong>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool SetUserRewarded(ulong userId)
|
||||||
|
{
|
||||||
|
return _rewardedUsers.Add(userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserXpStats GetUserStats(ulong guildId, ulong userId)
|
||||||
|
{
|
||||||
|
UserXpStats user;
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
user = uow.Xp.GetOrCreateUser(guildId, userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GenerateXpBar(int currentXp, int requiredXp)
|
||||||
|
{
|
||||||
|
//todo
|
||||||
|
return $"{currentXp}/{requiredXp}";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//todo exclude in database
|
||||||
|
public bool ToggleExcludeServer(ulong id)
|
||||||
|
{
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
var xpSetting = uow.GuildConfigs.XpSettingsFor(id);
|
||||||
|
if (_excludedServers.Add(id))
|
||||||
|
{
|
||||||
|
xpSetting.ServerExcluded = true;
|
||||||
|
uow.Complete();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_excludedServers.TryRemove(id);
|
||||||
|
xpSetting.ServerExcluded = false;
|
||||||
|
uow.Complete();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ToggleExcludeRole(ulong guildId, ulong rId)
|
||||||
|
{
|
||||||
|
var roles = _excludedRoles.GetOrAdd(guildId, _ => new ConcurrentHashSet<ulong>());
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
var xpSetting = uow.GuildConfigs.XpSettingsFor(guildId);
|
||||||
|
var excludeObj = new ExcludedItem
|
||||||
|
{
|
||||||
|
ItemId = rId,
|
||||||
|
ItemType = ExcludedItemType.Role,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (roles.Add(rId))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (xpSetting.ExclusionList.Add(excludeObj))
|
||||||
|
{
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
roles.TryRemove(rId);
|
||||||
|
|
||||||
|
if (xpSetting.ExclusionList.Remove(excludeObj))
|
||||||
|
{
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ToggleExcludeChannel(ulong guildId, ulong chId)
|
||||||
|
{
|
||||||
|
var channels = _excludedChannels.GetOrAdd(guildId, _ => new ConcurrentHashSet<ulong>());
|
||||||
|
using (var uow = _db.UnitOfWork)
|
||||||
|
{
|
||||||
|
var xpSetting = uow.GuildConfigs.XpSettingsFor(guildId);
|
||||||
|
var excludeObj = new ExcludedItem
|
||||||
|
{
|
||||||
|
ItemId = chId,
|
||||||
|
ItemType = ExcludedItemType.Channel,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (channels.Add(chId))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (xpSetting.ExclusionList.Add(excludeObj))
|
||||||
|
{
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
channels.TryRemove(chId);
|
||||||
|
|
||||||
|
if (xpSetting.ExclusionList.Remove(excludeObj))
|
||||||
|
{
|
||||||
|
uow.Complete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
105
src/NadekoBot/Modules/Xp/Xp.cs
Normal file
105
src/NadekoBot/Modules/Xp/Xp.cs
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
using Discord;
|
||||||
|
using Discord.Commands;
|
||||||
|
using NadekoBot.Common.Attributes;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using NadekoBot.Modules.Xp.Extensions;
|
||||||
|
using NadekoBot.Modules.Xp.Services;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NadekoBot.Modules.Xp
|
||||||
|
{
|
||||||
|
public partial class Xp : NadekoTopLevelModule<XpService>
|
||||||
|
{
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task Experience(IUser user = null)
|
||||||
|
{
|
||||||
|
user = user ?? Context.User;
|
||||||
|
await Task.Delay(64).ConfigureAwait(false); // wait a bit in case user got XP with this message
|
||||||
|
|
||||||
|
var stats = _service.GetUserStats(Context.Guild.Id, user.Id);
|
||||||
|
|
||||||
|
var levelData = stats.GetLevelData();
|
||||||
|
var xpBarStr = _service.GenerateXpBar(levelData.LevelXp, levelData.LevelRequiredXp);
|
||||||
|
|
||||||
|
await Context.Channel.EmbedAsync(new EmbedBuilder()
|
||||||
|
.WithTitle(user.ToString())
|
||||||
|
//.AddField(GetText("server_level"), stats.ServerLevel.ToString(), true)
|
||||||
|
.AddField(GetText("level"), levelData.Level.ToString(), true)
|
||||||
|
//.AddField(GetText("club"), stats.ClubName ?? "-", true)
|
||||||
|
.AddField(GetText("xp"), xpBarStr, false)
|
||||||
|
.WithOkColor())
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Server { Server };
|
||||||
|
|
||||||
|
//[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
//[RequireContext(ContextType.Guild)]
|
||||||
|
//[OwnerOnly]
|
||||||
|
//[Priority(1)]
|
||||||
|
//public async Task XpExclude(Server _, IGuild guild)
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
[RequireUserPermission(GuildPermission.Administrator)]
|
||||||
|
public async Task XpExclude(Server _)
|
||||||
|
{
|
||||||
|
var ex = _service.ToggleExcludeServer(Context.Guild.Id);
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized((ex ? "excluded" : "not_excluded"), Format.Bold(Context.Guild.ToString())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Role { Role };
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageRoles)]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task XpExclude(Role _, [Remainder] IRole role)
|
||||||
|
{
|
||||||
|
var ex = _service.ToggleExcludeRole(Context.Guild.Id, role.Id);
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized((ex ? "excluded" : "not_excluded"), Format.Bold(role.ToString())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Channel { Channel };
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireUserPermission(GuildPermission.ManageChannels)]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task XpExclude(Channel _, [Remainder] ITextChannel channel)
|
||||||
|
{
|
||||||
|
var ex = _service.ToggleExcludeChannel(Context.Guild.Id, channel.Id);
|
||||||
|
|
||||||
|
await ReplyConfirmLocalized((ex ? "excluded" : "not_excluded"), Format.Bold(channel.ToString())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
[NadekoCommand, Usage, Description, Aliases]
|
||||||
|
[RequireContext(ContextType.Guild)]
|
||||||
|
public async Task XpExclusionList()
|
||||||
|
{
|
||||||
|
var serverExcluded = _service.IsServerExcluded(Context.Guild.Id);
|
||||||
|
var roles = _service.GetExcludedRoles(Context.Guild.Id)
|
||||||
|
.Select(x => Context.Guild.GetRole(x)?.Name)
|
||||||
|
.Where(x => x != null);
|
||||||
|
|
||||||
|
var chans = (await Task.WhenAll(_service.GetExcludedChannels(Context.Guild.Id)
|
||||||
|
.Select(x => Context.Guild.GetChannelAsync(x)))
|
||||||
|
.ConfigureAwait(false))
|
||||||
|
.Where(x => x != null)
|
||||||
|
.Select(x => x.Name);
|
||||||
|
|
||||||
|
var embed = new EmbedBuilder()
|
||||||
|
.WithTitle(GetText("exclusion_list"))
|
||||||
|
.WithDescription((serverExcluded ? GetText("server_is_excluded") : GetText("server_is_not_excluded")))
|
||||||
|
.AddField(GetText("excluded_roles"), roles.Any() ? string.Join("\n", roles) : "-", false)
|
||||||
|
.AddField(GetText("excluded_channels"), chans.Any() ? string.Join("\n", chans) : "-", false)
|
||||||
|
.WithOkColor();
|
||||||
|
|
||||||
|
await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -91,4 +91,10 @@
|
|||||||
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="1.0.0" />
|
||||||
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" />
|
<DotNetCliToolReference Include="Microsoft.DotNet.Watcher.Tools" Version="1.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Update="Resources\CommandStrings.Designer.cs">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Compile>
|
||||||
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -3573,4 +3573,31 @@
|
|||||||
<data name="nsfwtagblacklist_desc" xml:space="preserve">
|
<data name="nsfwtagblacklist_desc" xml:space="preserve">
|
||||||
<value>Toggles whether the tag is blacklisted or not in nsfw searches. Provide no parameters to see the list of blacklisted tags.</value>
|
<value>Toggles whether the tag is blacklisted or not in nsfw searches. Provide no parameters to see the list of blacklisted tags.</value>
|
||||||
</data>
|
</data>
|
||||||
|
<data name="experience_cmd" xml:space="preserve">
|
||||||
|
<value>experience xp</value>
|
||||||
|
</data>
|
||||||
|
<data name="experience_usage" xml:space="preserve">
|
||||||
|
<value>`{0}xp`</value>
|
||||||
|
</data>
|
||||||
|
<data name="experience_desc" xml:space="preserve">
|
||||||
|
<value>Shows your xp stats. Specify the user to show that user's stats instead.</value>
|
||||||
|
</data>
|
||||||
|
<data name="xpexclusionlist_cmd" xml:space="preserve">
|
||||||
|
<value>xpexclusionlist xpexl</value>
|
||||||
|
</data>
|
||||||
|
<data name="xpexclusionlist_usage" xml:space="preserve">
|
||||||
|
<value>`{0}xpexl`</value>
|
||||||
|
</data>
|
||||||
|
<data name="xpexclusionlist_desc" xml:space="preserve">
|
||||||
|
<value>Shows the roles and channels excluded from the XP system on this server, as well as whether the whole server is excluded.</value>
|
||||||
|
</data>
|
||||||
|
<data name="xpexclude_cmd" xml:space="preserve">
|
||||||
|
<value>xpexclude xpex</value>
|
||||||
|
</data>
|
||||||
|
<data name="xpexclude_usage" xml:space="preserve">
|
||||||
|
<value>`{0}xpex User @b1nzy` `{0}xpex Server`</value>
|
||||||
|
</data>
|
||||||
|
<data name="xpexclude_desc" xml:space="preserve">
|
||||||
|
<value>Exclude a user or a role from the xp system, or whole current server.</value>
|
||||||
|
</data>
|
||||||
</root>
|
</root>
|
||||||
|
@ -24,6 +24,7 @@ namespace NadekoBot.Services.Database
|
|||||||
IWaifuRepository Waifus { get; }
|
IWaifuRepository Waifus { get; }
|
||||||
IDiscordUserRepository DiscordUsers { get; }
|
IDiscordUserRepository DiscordUsers { get; }
|
||||||
IWarningsRepository Warnings { get; }
|
IWarningsRepository Warnings { get; }
|
||||||
|
IXpRepository Xp { get; }
|
||||||
|
|
||||||
int Complete();
|
int Complete();
|
||||||
Task<int> CompleteAsync();
|
Task<int> CompleteAsync();
|
||||||
|
@ -68,6 +68,8 @@ Nadeko Support Server: https://discord.gg/nadekobot";
|
|||||||
public int PermissionVersion { get; set; }
|
public int PermissionVersion { get; set; }
|
||||||
public string DefaultPrefix { get; set; } = ".";
|
public string DefaultPrefix { get; set; } = ".";
|
||||||
public bool CustomReactionsStartWith { get; set; } = false;
|
public bool CustomReactionsStartWith { get; set; } = false;
|
||||||
|
public int XpPerMessage { get; set; } = 3;
|
||||||
|
public int XpMinutesTimeout { get; set; } = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BlockedCmdOrMdl : DbEntity
|
public class BlockedCmdOrMdl : DbEntity
|
||||||
|
@ -86,6 +86,8 @@ namespace NadekoBot.Services.Database.Models
|
|||||||
|
|
||||||
public StreamRoleSettings StreamRole { get; set; }
|
public StreamRoleSettings StreamRole { get; set; }
|
||||||
|
|
||||||
|
public XpSettings XpSettings { get; set; }
|
||||||
|
|
||||||
//public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>();
|
//public List<ProtectionIgnoredChannel> ProtectionIgnoredChannels { get; set; } = new List<ProtectionIgnoredChannel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/NadekoBot/Services/Database/Models/UserXpStats.cs
Normal file
10
src/NadekoBot/Services/Database/Models/UserXpStats.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace NadekoBot.Services.Database.Models
|
||||||
|
{
|
||||||
|
public class UserXpStats : DbEntity
|
||||||
|
{
|
||||||
|
public ulong UserId { get; set; }
|
||||||
|
public ulong GuildId { get; set; }
|
||||||
|
public int Xp { get; set; }
|
||||||
|
public bool NotifyOnLevelUp { get; set; }
|
||||||
|
}
|
||||||
|
}
|
50
src/NadekoBot/Services/Database/Models/XpSettings.cs
Normal file
50
src/NadekoBot/Services/Database/Models/XpSettings.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Database.Models
|
||||||
|
{
|
||||||
|
public class XpSettings : DbEntity
|
||||||
|
{
|
||||||
|
public int GuildConfigId { get; set; }
|
||||||
|
public GuildConfig GuildConfig { get; set; }
|
||||||
|
|
||||||
|
public HashSet<XpRoleReward> RoleRewards { get; set; } = new HashSet<XpRoleReward>();
|
||||||
|
public bool XpRoleRewardExclusive { get; set; }
|
||||||
|
public string NotifyMessage { get; set; } = "Congratulations {0}! You have reached level {1}!";
|
||||||
|
public HashSet<ExcludedItem> ExclusionList { get; set; } = new HashSet<ExcludedItem>();
|
||||||
|
public bool ServerExcluded { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ExcludedItemType { Channel, Role }
|
||||||
|
|
||||||
|
public class XpRoleReward : DbEntity
|
||||||
|
{
|
||||||
|
public int Level { get; set; }
|
||||||
|
public ulong RoleId { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Level.GetHashCode() ^ RoleId.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is XpRoleReward xrr && xrr.Level == Level && xrr.RoleId == RoleId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ExcludedItem : DbEntity
|
||||||
|
{
|
||||||
|
public ulong ItemId { get; set; }
|
||||||
|
public ExcludedItemType ItemType { get; set; }
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return ItemId.GetHashCode() ^ ItemType.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is ExcludedItem ei && ei.ItemId == ItemId && ei.ItemType == ItemType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,7 @@ namespace NadekoBot.Services.Database
|
|||||||
public DbSet<UserPokeTypes> PokeGame { get; set; }
|
public DbSet<UserPokeTypes> PokeGame { get; set; }
|
||||||
public DbSet<WaifuUpdate> WaifuUpdates { get; set; }
|
public DbSet<WaifuUpdate> WaifuUpdates { get; set; }
|
||||||
public DbSet<Warning> Warnings { get; set; }
|
public DbSet<Warning> Warnings { get; set; }
|
||||||
|
public DbSet<UserXpStats> UserXpStats { get; set; }
|
||||||
|
|
||||||
//logging
|
//logging
|
||||||
public DbSet<LogSetting> LogSettings { get; set; }
|
public DbSet<LogSetting> LogSettings { get; set; }
|
||||||
@ -292,6 +293,18 @@ namespace NadekoBot.Services.Database
|
|||||||
pr.HasIndex(x => x.UserId)
|
pr.HasIndex(x => x.UserId)
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
#region XpStatas
|
||||||
|
modelBuilder.Entity<UserXpStats>()
|
||||||
|
.HasIndex(x => new { x.UserId, x.GuildId })
|
||||||
|
.IsUnique();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region XpSettings
|
||||||
|
modelBuilder.Entity<XpSettings>()
|
||||||
|
.HasOne(x => x.GuildConfig)
|
||||||
|
.WithOne(x => x.XpSettings);
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,5 +16,6 @@ namespace NadekoBot.Services.Database.Repositories
|
|||||||
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
|
void SetCleverbotEnabled(ulong id, bool cleverbotEnabled);
|
||||||
IEnumerable<GuildConfig> Permissionsv2ForAll(List<long> include);
|
IEnumerable<GuildConfig> Permissionsv2ForAll(List<long> include);
|
||||||
GuildConfig GcWithPermissionsv2For(ulong guildId);
|
GuildConfig GcWithPermissionsv2For(ulong guildId);
|
||||||
|
XpSettings XpSettingsFor(ulong guildId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Database.Repositories
|
||||||
|
{
|
||||||
|
public interface IXpRepository : IRepository<UserXpStats>
|
||||||
|
{
|
||||||
|
UserXpStats GetOrCreateUser(ulong guildId, ulong userId);
|
||||||
|
}
|
||||||
|
}
|
@ -189,5 +189,19 @@ namespace NadekoBot.Services.Database.Repositories.Impl
|
|||||||
|
|
||||||
conf.CleverbotEnabled = cleverbotEnabled;
|
conf.CleverbotEnabled = cleverbotEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XpSettings XpSettingsFor(ulong guildId)
|
||||||
|
{
|
||||||
|
var gc = For(guildId,
|
||||||
|
set => set.Include(x => x.XpSettings)
|
||||||
|
.ThenInclude(x => x.RoleRewards)
|
||||||
|
.Include(x => x.XpSettings)
|
||||||
|
.ThenInclude(x => x.ExclusionList));
|
||||||
|
|
||||||
|
if (gc.XpSettings == null)
|
||||||
|
gc.XpSettings = new XpSettings();
|
||||||
|
|
||||||
|
return gc.XpSettings;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
using NadekoBot.Services.Database.Models;
|
||||||
|
using System.Linq;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace NadekoBot.Services.Database.Repositories.Impl
|
||||||
|
{
|
||||||
|
public class XpRepository : Repository<UserXpStats>, IXpRepository
|
||||||
|
{
|
||||||
|
public XpRepository(DbContext context) : base(context)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserXpStats GetOrCreateUser(ulong guildId, ulong userId)
|
||||||
|
{
|
||||||
|
var usr = _set.FirstOrDefault(x => x.UserId == userId);
|
||||||
|
|
||||||
|
if (usr == null)
|
||||||
|
{
|
||||||
|
_context.Add(usr = new UserXpStats()
|
||||||
|
{
|
||||||
|
Xp = 0,
|
||||||
|
UserId = userId,
|
||||||
|
NotifyOnLevelUp = false,
|
||||||
|
GuildId = guildId,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return usr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -57,6 +57,9 @@ namespace NadekoBot.Services.Database
|
|||||||
private IWarningsRepository _warnings;
|
private IWarningsRepository _warnings;
|
||||||
public IWarningsRepository Warnings => _warnings ?? (_warnings = new WarningsRepository(_context));
|
public IWarningsRepository Warnings => _warnings ?? (_warnings = new WarningsRepository(_context));
|
||||||
|
|
||||||
|
private IXpRepository _xp;
|
||||||
|
public IXpRepository Xp => _xp ?? (_xp = new XpRepository(_context));
|
||||||
|
|
||||||
public UnitOfWork(NadekoContext context)
|
public UnitOfWork(NadekoContext context)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
|
@ -122,6 +122,18 @@ namespace NadekoBot.Services.Impl
|
|||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
break;
|
break;
|
||||||
|
case BotConfigEditType.XpPerMessage:
|
||||||
|
if (int.TryParse(newValue, out var xp) && xp > 0)
|
||||||
|
bc.XpPerMessage = xp;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case BotConfigEditType.XpMinutesTimeout:
|
||||||
|
if (int.TryParse(newValue, out var min) && min > 0)
|
||||||
|
bc.XpMinutesTimeout = min;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -822,5 +822,16 @@
|
|||||||
"administration_prefix_current": "Prefix on this server is {0}",
|
"administration_prefix_current": "Prefix on this server is {0}",
|
||||||
"administration_prefix_new": "Changed prefix on this server from {0} to {1}",
|
"administration_prefix_new": "Changed prefix on this server from {0} to {1}",
|
||||||
"administration_defprefix_current": "Default bot prefix is {0}",
|
"administration_defprefix_current": "Default bot prefix is {0}",
|
||||||
"administration_defprefix_new": "Changed Default bot prefix from {0} to {1}"
|
"administration_defprefix_new": "Changed Default bot prefix from {0} to {1}",
|
||||||
|
"xp_server_level": "Server Level",
|
||||||
|
"xp_level": "Level",
|
||||||
|
"xp_club": "Club",
|
||||||
|
"xp_xp": "Experience",
|
||||||
|
"xp_excluded": "{0} has been excluded from the XP system on this server.",
|
||||||
|
"xp_not_excluded": "{0} is no longer excluded from the XP system on this server.",
|
||||||
|
"xp_exclusion_list": "Exclusion List",
|
||||||
|
"xp_server_is_excluded": "This server is excluded.",
|
||||||
|
"xp_server_is_not_excluded": "This server is not excluded.",
|
||||||
|
"xp_excluded_roles": "Excluded Roles",
|
||||||
|
"xp_excluded_channels": "Excluded Channels"
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user