Currency level up rewards (.xpcr) Bot owner only.

This commit is contained in:
Master Kwoth 2017-11-15 14:01:40 +01:00
parent 461dfd553f
commit 43ed332f84
7 changed files with 2170 additions and 37 deletions

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,45 @@
using Microsoft.EntityFrameworkCore.Migrations;
using System;
using System.Collections.Generic;
namespace NadekoBot.Migrations
{
public partial class currencylevelupreward : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "XpCurrencyReward",
columns: table => new
{
Id = table.Column<int>(type: "INTEGER", nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Amount = table.Column<int>(type: "INTEGER", nullable: false),
DateAdded = table.Column<DateTime>(type: "TEXT", nullable: true),
Level = table.Column<int>(type: "INTEGER", nullable: false),
XpSettingsId = table.Column<int>(type: "INTEGER", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_XpCurrencyReward", x => x.Id);
table.ForeignKey(
name: "FK_XpCurrencyReward_XpSettings_XpSettingsId",
column: x => x.XpSettingsId,
principalTable: "XpSettings",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_XpCurrencyReward_XpSettingsId",
table: "XpCurrencyReward",
column: "XpSettingsId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "XpCurrencyReward");
}
}
}

View File

@ -1551,6 +1551,26 @@ namespace NadekoBot.Migrations
b.ToTable("WarningPunishment");
});
modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpCurrencyReward", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("Amount");
b.Property<DateTime?>("DateAdded");
b.Property<int>("Level");
b.Property<int>("XpSettingsId");
b.HasKey("Id");
b.HasIndex("XpSettingsId");
b.ToTable("XpCurrencyReward");
});
modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpRoleReward", b =>
{
b.Property<int>("Id")
@ -1972,6 +1992,14 @@ namespace NadekoBot.Migrations
.HasForeignKey("GuildConfigId");
});
modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpCurrencyReward", b =>
{
b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings", "XpSettings")
.WithMany("CurrencyRewards")
.HasForeignKey("XpSettingsId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("NadekoBot.Core.Services.Database.Models.XpRoleReward", b =>
{
b.HasOne("NadekoBot.Core.Services.Database.Models.XpSettings", "XpSettings")

View File

@ -36,6 +36,8 @@ namespace NadekoBot.Modules.Xp.Services
private readonly NadekoStrings _strings;
private readonly IDataCache _cache;
private readonly FontProvider _fonts;
private readonly IBotCredentials _creds;
private readonly CurrencyService _cs;
public const int XP_REQUIRED_LVL_1 = 36;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedRoles
@ -60,7 +62,7 @@ namespace NadekoBot.Modules.Xp.Services
public XpService(CommandHandler cmd, IBotConfigProvider bc,
NadekoBot bot, DbService db, NadekoStrings strings, IDataCache cache,
FontProvider fonts)
FontProvider fonts, IBotCredentials creds, CurrencyService cs)
{
_db = db;
_cmd = cmd;
@ -70,6 +72,8 @@ namespace NadekoBot.Modules.Xp.Services
_strings = strings;
_cache = cache;
_fonts = fonts;
_creds = creds;
_cs = cs;
//load settings
var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null);
@ -105,6 +109,7 @@ namespace NadekoBot.Modules.Xp.Services
{
var toNotify = new List<(IMessageChannel MessageChannel, IUser User, int Level, XpNotificationType NotifyType, NotifOf NotifOf)>();
var roleRewards = new Dictionary<ulong, List<XpRoleReward>>();
var curRewards = new Dictionary<ulong, List<XpCurrencyReward>>();
var toAddTo = new List<UserCacheItem>();
while (_addMessageXp.TryDequeue(out var usr))
@ -120,14 +125,13 @@ namespace NadekoBot.Modules.Xp.Services
{
var xp = item.Select(x => bc.BotConfig.XpPerMessage).Sum();
//1. Mass query discord users and userxpstats and get them from local dict
//2. (better but much harder) Move everything to the database, and get old and new xp
// amounts for every user (in order to give rewards)
var usr = uow.Xp.GetOrCreateUser(item.Key.GuildId, item.Key.User.Id);
var du = uow.DiscordUsers.GetOrCreate(item.Key.User);
if (du.LastXpGain + TimeSpan.FromMinutes(_bc.BotConfig.XpMinutesTimeout) > DateTime.UtcNow)
continue;
du.LastXpGain = DateTime.UtcNow;
var globalXp = du.TotalXp;
var oldGlobalLevelData = new LevelStats(globalXp);
var newGlobalLevelData = new LevelStats(globalXp + xp);
@ -156,21 +160,34 @@ namespace NadekoBot.Modules.Xp.Services
toNotify.Add((first.Channel, first.User, newGuildLevelData.Level, usr.NotifyOnLevelUp, NotifOf.Server));
//give role
if (!roleRewards.TryGetValue(usr.GuildId, out var rewards))
if (!roleRewards.TryGetValue(usr.GuildId, out var rrews))
{
rewards = uow.GuildConfigs.XpSettingsFor(usr.GuildId).RoleRewards.ToList();
roleRewards.Add(usr.GuildId, rewards);
rrews = uow.GuildConfigs.XpSettingsFor(usr.GuildId).RoleRewards.ToList();
roleRewards.Add(usr.GuildId, rrews);
}
var rew = rewards.FirstOrDefault(x => x.Level == newGuildLevelData.Level);
if (rew != null)
if (!curRewards.TryGetValue(usr.GuildId, out var crews))
{
var role = first.User.Guild.GetRole(rew.RoleId);
crews = uow.GuildConfigs.XpSettingsFor(usr.GuildId).CurrencyRewards.ToList();
curRewards.Add(usr.GuildId, crews);
}
var rrew = rrews.FirstOrDefault(x => x.Level == newGuildLevelData.Level);
if (rrew != null)
{
var role = first.User.Guild.GetRole(rrew.RoleId);
if (role != null)
{
var __ = first.User.AddRoleAsync(role);
}
}
//get currency reward for this level
var crew = crews.FirstOrDefault(x => x.Level == newGuildLevelData.Level);
if (crew != null)
{
//give the user the reward if it exists
await _cs.AddAsync(item.Key.User.Id, "Level-up Reward", crew.Amount, uow);
}
}
}
@ -429,7 +446,13 @@ namespace NadekoBot.Modules.Xp.Services
private bool SetUserRewarded(ulong userId)
{
return _rewardedUsers.Add(userId);
var r = _cache.Redis.GetDatabase();
var key = $"{_creds.RedisKey()}_user_xp_gain_{userId}";
return r.StringSet(key,
true,
TimeSpan.FromMinutes(_bc.BotConfig.XpMinutesTimeout),
StackExchange.Redis.When.NotExists);
}
public FullUserStats GetUserStats(IGuildUser user)

View File

@ -17,11 +17,13 @@ namespace NadekoBot.Modules.Xp
{
private readonly DiscordSocketClient _client;
private readonly DbService _db;
private readonly IBotConfigProvider _bc;
public Xp(DiscordSocketClient client,DbService db)
public Xp(DiscordSocketClient client,DbService db, IBotConfigProvider bc)
{
_client = client;
_db = db;
_bc = bc;
}
[NadekoCommand, Usage, Description, Aliases]
@ -45,34 +47,39 @@ namespace NadekoBot.Modules.Xp
[NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)]
public Task XpRoleRewards(int page = 1)
public Task XpLevelUpRewards(int page = 1)
{
page--;
if (page < 0 || page > 100)
return Task.CompletedTask;
var roles = _service.GetRoleRewards(Context.Guild.Id)
.OrderBy(x => x.Level)
.Skip(page * 9)
.Take(9);
var embed = new EmbedBuilder()
.WithTitle(GetText("level_up_rewards"))
.WithOkColor();
if (!roles.Any())
return Context.Channel.EmbedAsync(embed.WithDescription(GetText("no_role_rewards")));
var rewards = _service.GetRoleRewards(Context.Guild.Id)
.OrderBy(x => x.Level)
.Select(x =>
{
var str = Context.Guild.GetRole(x.RoleId)?.ToString();
if (str != null)
str = GetText("role_reward", Format.Bold(str));
return (x.Level, RoleStr: str);
})
.Where(x => x.RoleStr != null)
.Concat(_service.GetCurrencyRewards(Context.Guild.Id)
.OrderBy(x => x.Level)
.Select(x => (x.Level, Format.Bold(x.Amount + _bc.BotConfig.CurrencySign))))
.GroupBy(x => x.Level)
.OrderBy(x => x.Key)
.Skip(page * 9)
.Take(9)
.ForEach(x => embed.AddField(GetText("level_x", x.Key), string.Join("\n", x.Select(y => y.Item2))));
foreach (var rolerew in roles)
{
var role = Context.Guild.GetRole(rolerew.RoleId);
if (!rewards.Any())
return Context.Channel.EmbedAsync(embed.WithDescription(GetText("no_level_up_rewards")));
if (role == null)
continue;
embed.AddField(GetText("level_x", Format.Bold(rolerew.Level.ToString())), role.ToString());
}
return Context.Channel.EmbedAsync(embed);
}
@ -104,7 +111,7 @@ namespace NadekoBot.Modules.Xp
if (amount == 0)
await ReplyConfirmLocalized("cur_reward_cleared", level).ConfigureAwait(false);
else
await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount.ToString())).ConfigureAwait(false);
await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount + _bc.BotConfig.CurrencySign)).ConfigureAwait(false);
}
public enum NotifyPlace

View File

@ -845,9 +845,10 @@
"xp_role_reward_added": "Users who reach level {0} will receive {1} role.",
"xp_cur_reward_cleared": "Reaching level {0} will no longer reward any {1}.",
"xp_cur_reward_added": "Users who reach level {0} will receive {1}.",
"xp_role_rewards": "Role Rewards",
"xp_level_up_rewards": "Level Up Rewards",
"xp_level_x": "Level {0}",
"xp_no_role_rewards": "No role reward on this page.",
"xp_role_reward": "{0} role",
"xp_no_level_up_rewards": "No level up reward on this page.",
"xp_server_leaderboard": "Server XP Leaderboard",
"xp_global_leaderboard": "Global XP Leaderboard",
"xp_modified": "Modified server XP of the user {0} by {1}",

View File

@ -2815,11 +2815,11 @@
"{0}xpn server channel"
]
},
"xprolerewards": {
"Cmd": "xprolerewards xprrs",
"Desc": "Shows currently set role rewards.",
"xpleveluprewards": {
"Cmd": "xplvluprewards xprews xpcrs xprrs xprolerewards xpcurrewards",
"Desc": "Shows currently set level up rewards.",
"Usage": [
"{0}xprrs"
"{0}xprews"
]
},
"xprolereward": {
@ -2829,6 +2829,13 @@
"{0}xprr 3 Social"
]
},
"xpcurrencyreward": {
"Cmd": "xpcurreward xpcr",
"Desc": "Sets a currency reward on a specified level. Provide no amount in order to remove the reward.",
"Usage": [
"{0}xpcr 3 50"
]
},
"xpleaderboard": {
"Cmd": "xpleaderboard xplb",
"Desc": "Shows current server's xp leaderboard.",