Merge branch 'wip' into 1.9
This commit is contained in:
commit
1be9bed764
2022
NadekoBot.Core/Migrations/20171115040313_currency level up reward.Designer.cs
generated
Normal file
2022
NadekoBot.Core/Migrations/20171115040313_currency level up reward.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,6 +258,50 @@ namespace NadekoBot.Modules.Xp.Services
|
||||
}, token);
|
||||
}
|
||||
|
||||
public void SetCurrencyReward(ulong guildId, int level, int amount)
|
||||
{
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
var settings = uow.GuildConfigs.XpSettingsFor(guildId);
|
||||
|
||||
if (amount <= 0)
|
||||
{
|
||||
var toRemove = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level);
|
||||
if (toRemove != null)
|
||||
{
|
||||
uow._context.Remove(toRemove);
|
||||
settings.CurrencyRewards.Remove(toRemove);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var rew = settings.CurrencyRewards.FirstOrDefault(x => x.Level == level);
|
||||
|
||||
if (rew != null)
|
||||
rew.Amount = amount;
|
||||
else
|
||||
settings.CurrencyRewards.Add(new XpCurrencyReward()
|
||||
{
|
||||
Level = level,
|
||||
Amount = amount,
|
||||
});
|
||||
}
|
||||
|
||||
uow.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<XpCurrencyReward> GetCurrencyRewards(ulong id)
|
||||
{
|
||||
using (var uow = _db.UnitOfWork)
|
||||
{
|
||||
return uow.GuildConfigs.XpSettingsFor(id)
|
||||
.CurrencyRewards
|
||||
.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<XpRoleReward> GetRoleRewards(ulong id)
|
||||
{
|
||||
using (var uow = _db.UnitOfWork)
|
||||
@ -385,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)
|
||||
|
@ -17,40 +17,18 @@ 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]
|
||||
//[RequireContext(ContextType.Guild)]
|
||||
//[OwnerOnly]
|
||||
//public async Task Populate()
|
||||
//{
|
||||
// var rng = new NadekoRandom();
|
||||
// using (var uow = _db.UnitOfWork)
|
||||
// {
|
||||
// for (var i = 0ul; i < 1000000; i++)
|
||||
// {
|
||||
// uow.DiscordUsers.Add(new DiscordUser()
|
||||
// {
|
||||
// AvatarId = i.ToString(),
|
||||
// Discriminator = "1234",
|
||||
// UserId = i,
|
||||
// Username = i.ToString(),
|
||||
// Club = null,
|
||||
// });
|
||||
// var xp = uow.Xp.GetOrCreateUser(Context.Guild.Id, i);
|
||||
// xp.Xp = rng.Next(100, 100000);
|
||||
// }
|
||||
// uow.Complete();
|
||||
// }
|
||||
//}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
//todo add ratelimit attribute
|
||||
//[Ratelimit(30)]
|
||||
public async Task Experience([Remainder]IUser user = null)
|
||||
{
|
||||
@ -69,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("role_rewards"))
|
||||
.WithTitle(GetText("level_up_rewards"))
|
||||
.WithOkColor();
|
||||
|
||||
if (!roles.Any())
|
||||
return Context.Channel.EmbedAsync(embed.WithDescription(GetText("no_role_rewards")));
|
||||
|
||||
foreach (var rolerew in roles)
|
||||
var rewards = _service.GetRoleRewards(Context.Guild.Id)
|
||||
.OrderBy(x => x.Level)
|
||||
.Select(x =>
|
||||
{
|
||||
var role = Context.Guild.GetRole(rolerew.RoleId);
|
||||
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))));
|
||||
|
||||
if (role == null)
|
||||
continue;
|
||||
if (!rewards.Any())
|
||||
return Context.Channel.EmbedAsync(embed.WithDescription(GetText("no_level_up_rewards")));
|
||||
|
||||
embed.AddField(GetText("level_x", Format.Bold(rolerew.Level.ToString())), role.ToString());
|
||||
}
|
||||
return Context.Channel.EmbedAsync(embed);
|
||||
}
|
||||
|
||||
@ -116,6 +99,22 @@ namespace NadekoBot.Modules.Xp
|
||||
await ReplyConfirmLocalized("role_reward_added", level, Format.Bold(role.ToString())).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
[NadekoCommand, Usage, Description, Aliases]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[OwnerOnly]
|
||||
public async Task XpCurrencyReward(int level, int amount=0)
|
||||
{
|
||||
if (level < 1 || amount < 0)
|
||||
return;
|
||||
|
||||
_service.SetCurrencyReward(Context.Guild.Id, level, amount);
|
||||
|
||||
if (amount == 0)
|
||||
await ReplyConfirmLocalized("cur_reward_cleared", level, _bc.BotConfig.CurrencySign).ConfigureAwait(false);
|
||||
else
|
||||
await ReplyConfirmLocalized("cur_reward_added", level, Format.Bold(amount + _bc.BotConfig.CurrencySign)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
public enum NotifyPlace
|
||||
{
|
||||
Server = 0,
|
||||
|
@ -8,6 +8,7 @@ namespace NadekoBot.Core.Services.Database.Models
|
||||
public GuildConfig GuildConfig { get; set; }
|
||||
|
||||
public HashSet<XpRoleReward> RoleRewards { get; set; } = new HashSet<XpRoleReward>();
|
||||
public HashSet<XpCurrencyReward> CurrencyRewards { get; set; } = new HashSet<XpCurrencyReward>();
|
||||
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>();
|
||||
@ -35,6 +36,25 @@ namespace NadekoBot.Core.Services.Database.Models
|
||||
}
|
||||
}
|
||||
|
||||
public class XpCurrencyReward : DbEntity
|
||||
{
|
||||
public int XpSettingsId { get; set; }
|
||||
public XpSettings XpSettings { get; set; }
|
||||
|
||||
public int Level { get; set; }
|
||||
public int Amount { get; set; }
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Level.GetHashCode() ^ XpSettingsId.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return obj is XpCurrencyReward xrr && xrr.Level == Level && xrr.XpSettingsId == XpSettingsId;
|
||||
}
|
||||
}
|
||||
|
||||
public class ExcludedItem : DbEntity
|
||||
{
|
||||
public ulong ItemId { get; set; }
|
||||
|
@ -200,6 +200,8 @@ namespace NadekoBot.Core.Services.Database.Repositories.Impl
|
||||
set => set.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.RoleRewards)
|
||||
.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.CurrencyRewards)
|
||||
.Include(x => x.XpSettings)
|
||||
.ThenInclude(x => x.ExclusionList));
|
||||
|
||||
if (gc.XpSettings == null)
|
||||
|
@ -21,7 +21,7 @@ namespace NadekoBot.Core.Services.Impl
|
||||
private readonly IBotCredentials _creds;
|
||||
private readonly DateTime _started;
|
||||
|
||||
public const string BotVersion = "2.4.4";
|
||||
public const string BotVersion = "2.5.0";
|
||||
|
||||
public string Author => "Kwoth#2560";
|
||||
public string Library => "Discord.Net";
|
||||
|
@ -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}",
|
||||
|
@ -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.",
|
||||
|
Loading…
Reference in New Issue
Block a user