Beispiel #1
0
        public async Task RepairCardsAsync(ulong oldId, ulong newId)
        {
            var response = await _shClient.GetCharacterInfoAsync(newId);

            if (!response.IsSuccessStatusCode())
            {
                await "New character ID is invalid!".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return;
            }

            var exe = new Executable($"api-repair oc{oldId} c{newId}", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var cards = db.Cards.Where(x => x.Character == oldId);
                    foreach (var card in cards)
                    {
                        card.Character = newId;
                    }

                    db.SaveChanges();

                    QueryCacheManager.ExpireTag(new string[] { "users" });
                }
            }));

            await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

            await "Success".ToResponse(200).ExecuteResultAsync(ControllerContext);
        }
Beispiel #2
0
        private void SpawnUserPacket(SocketUser user)
        {
            var exe = new Executable($"packet u{user.Id}", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var botUser = db.GetUserOrCreateAsync(user.Id).Result;
                    if (botUser.IsBlacklisted)
                    {
                        return;
                    }

                    botUser.GameDeck.BoosterPacks.Add(new BoosterPack
                    {
                        CardCnt   = 2,
                        MinRarity = Rarity.E,
                        IsCardFromPackTradable = true,
                        Name = "Pakiet kart za aktywność",
                        CardSourceFromPack = CardSource.Activity
                    });
                    db.SaveChanges();
                }
            }));

            _executor.TryAdd(exe, TimeSpan.FromSeconds(1));
        }
Beispiel #3
0
        public async Task ToggleCardStatusAsync(ulong wid)
        {
            var currUser = ControllerContext.HttpContext.User;

            if (currUser.HasClaim(x => x.Type == "DiscordId"))
            {
                if (ulong.TryParse(currUser.Claims.First(x => x.Type == "DiscordId").Value, out var discordId))
                {
                    using (var db = new Database.UserContext(_config))
                    {
                        var botUserCh = await db.GetCachedFullUserAsync(discordId);

                        if (botUserCh == null)
                        {
                            await "User not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                            return;
                        }

                        var thisCardCh = botUserCh.GameDeck.Cards.FirstOrDefault(x => x.Id == wid);
                        if (thisCardCh == null)
                        {
                            await "Card not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                            return;
                        }

                        if (thisCardCh.InCage)
                        {
                            await "Card is in cage!".ToResponse(403).ExecuteResultAsync(ControllerContext);
                            return;
                        }

                        if (!thisCardCh.Active && botUserCh.GameDeck.Cards.Where(x => x.Active).Count() >= 3)
                        {
                            await "Limit of active cards triggered!".ToResponse(403).ExecuteResultAsync(ControllerContext);
                            return;
                        }
                    }

                    var exe = new Executable($"api-deck u{discordId}", new Task(() =>
                    {
                        using (var db = new Database.UserContext(_config))
                        {
                            var botUser     = db.GetUserOrCreateAsync(discordId).Result;
                            var thisCard    = botUser.GameDeck.Cards.FirstOrDefault(x => x.Id == wid);
                            thisCard.Active = !thisCard.Active;

                            db.SaveChanges();

                            QueryCacheManager.ExpireTag(new string[] { $"user-{botUser.Id}", "users" });
                        }
                    }));

                    await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                    await "Card status toggled".ToResponse(200).ExecuteResultAsync(ControllerContext);
                    return;
                }
            }
            await "The appropriate claim was not found".ToResponse(403).ExecuteResultAsync(ControllerContext);
        }
Beispiel #4
0
        public async Task ModifyPointsTCAsync(ulong id, [FromBody, Required] long value)
        {
            using (var db = new Database.UserContext(_config))
            {
                var user = db.Users.FirstOrDefault(x => x.Shinden == id);
                if (user == null)
                {
                    await "User not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                    return;
                }

                var exe = new Executable($"api-tc su{id}", new Task(() =>
                {
                    using (var dbs = new Database.UserContext(_config))
                    {
                        user        = dbs.Users.FirstOrDefault(x => x.Shinden == id);
                        user.TcCnt += value;

                        dbs.SaveChanges();

                        QueryCacheManager.ExpireTag(new string[] { $"user-{user.Id}", "users" });
                    }
                }));

                await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                await "TC added!".ToResponse(200).ExecuteResultAsync(ControllerContext);
            }
        }
Beispiel #5
0
        public IExecutable GetExecutableGMwK(FightHistory history, List <PlayerInfo> players)
        {
            return(new Executable("GMwK", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    bool isWinner = history.Winner != null;
                    foreach (var p in players)
                    {
                        var u = db.GetUserOrCreateAsync(p.User.Id).Result;
                        var stat = new CardPvPStats
                        {
                            Type = FightType.BattleRoyale,
                            Result = isWinner ? FightResult.Lose : FightResult.Draw
                        };

                        if (isWinner)
                        {
                            if (u.Id == history.Winner.User.Id)
                            {
                                stat.Result = FightResult.Win;
                            }
                        }

                        u.GameDeck.PvPStats.Add(stat);
                    }

                    db.SaveChanges();
                }
            })));
        }
Beispiel #6
0
        private Executable GetSafariExe(EmbedBuilder embed, IUserMessage msg, Card newCard,
                                        SafariImage pokeImage, ICharacterInfo character, ITextChannel trashChannel, IUser winner)
        {
            return(new Executable("safari", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var botUser = db.GetUserOrCreateAsync(winner.Id).Result;

                    newCard.FirstIdOwner = winner.Id;
                    newCard.Affection += botUser.GameDeck.AffectionFromKarma();
                    botUser.GameDeck.RemoveCharacterFromWishList(newCard.Character);

                    botUser.GameDeck.Cards.Add(newCard);
                    db.SaveChanges();

                    QueryCacheManager.ExpireTag(new string[] { $"user-{botUser.Id}", "users" });

                    using (var dba = new Database.AnalyticsContext(_config))
                    {
                        dba.UsersData.Add(new Database.Models.Analytics.UserAnalytics
                        {
                            Value = 1,
                            UserId = winner.Id,
                            MeasureDate = DateTime.Now,
                            GuildId = trashChannel?.Guild?.Id ?? 0,
                            Type = Database.Models.Analytics.UserAnalyticsEventType.Card
                        });
                        dba.SaveChanges();
                    }
                }

                _ = Task.Run(async() =>
                {
                    try
                    {
                        embed.ImageUrl = await _waifu.GetSafariViewAsync(pokeImage, newCard, trashChannel);
                        embed.Description = $"{winner.Mention} zdobył na polowaniu i wsadził do klatki:\n"
                                            + $"{newCard.GetString(false, false, true)}\n({newCard.Title})";
                        await msg.ModifyAsync(x => x.Embed = embed.Build());

                        var privEmb = new EmbedBuilder()
                        {
                            Color = EMType.Info.Color(),
                            Description = $"Na [polowaniu]({msg.GetJumpUrl()}) zdobyłeś: {newCard.GetString(false, false, true)}"
                        };

                        var priv = await winner.GetOrCreateDMChannelAsync();
                        if (priv != null)
                        {
                            await priv.SendMessageAsync("", false, privEmb.Build());
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Log($"In Safari: {ex}");
                    }
                });
            })));
        }
Beispiel #7
0
        private async Task UserLeftAsync(SocketGuildUser user)
        {
            if (user.IsBot || user.IsWebhook)
            {
                return;
            }

            if (!_config.Get().BlacklistedGuilds.Any(x => x == user.Guild.Id))
            {
                using (var db = new Database.GuildConfigContext(_config))
                {
                    var config = await db.GetCachedGuildFullConfigAsync(user.Guild.Id);

                    if (config?.GoodbyeMessage == null)
                    {
                        return;
                    }
                    if (config.GoodbyeMessage == "off")
                    {
                        return;
                    }

                    await SendMessageAsync(ReplaceTags(user, config.GoodbyeMessage), user.Guild.GetTextChannel(config.GreetingChannel));
                }
            }

            var thisUser = _client.Guilds.FirstOrDefault(x => x.Id == user.Id);

            if (thisUser != null)
            {
                return;
            }

            var moveTask = new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var duser = db.GetUserOrCreateAsync(user.Id).Result;
                    var fakeu = db.GetUserOrCreateAsync(1).Result;

                    foreach (var card in duser.GameDeck.Cards)
                    {
                        card.InCage = false;
                        card.TagList.Clear();
                        card.LastIdOwner = user.Id;
                        fakeu.GameDeck.Cards.Add(card);
                    }

                    duser.GameDeck.Cards.Clear();
                    db.Users.Remove(duser);

                    db.SaveChanges();

                    QueryCacheManager.ExpireTag(new string[] { "users" });
                }
            });

            await _executor.TryAdd(new Executable("delete user", moveTask), TimeSpan.FromSeconds(1));
        }
Beispiel #8
0
        public async Task GiveUserAPacksAsync(ulong id, [FromBody] List <Models.CardBoosterPack> boosterPacks)
        {
            if (boosterPacks?.Count < 1)
            {
                await "Model is Invalid".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return;
            }

            var packs = new List <BoosterPack>();

            foreach (var pack in boosterPacks)
            {
                var rPack = pack.ToRealPack();
                if (rPack != null)
                {
                    packs.Add(rPack);
                }
            }

            if (packs.Count < 1)
            {
                await "Data is Invalid".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return;
            }

            using (var db = new Database.UserContext(_config))
            {
                var user = await db.GetCachedFullUserAsync(id);

                if (user == null)
                {
                    await "User not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                    return;
                }

                var exe = new Executable($"api-packet u{id}", new Task(() =>
                {
                    using (var dbs = new Database.UserContext(_config))
                    {
                        var botUser = dbs.GetUserOrCreateAsync(id).Result;

                        foreach (var pack in packs)
                        {
                            botUser.GameDeck.BoosterPacks.Add(pack);
                        }

                        dbs.SaveChanges();

                        QueryCacheManager.ExpireTag(new string[] { $"user-{botUser.Id}", "users" });
                    }
                }));

                await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                await "Boosterpack added!".ToResponse(200).ExecuteResultAsync(ControllerContext);
            }
        }
Beispiel #9
0
        public async Task GenerateCharacterCardAsync(ulong id)
        {
            var response = await _shClient.GetCharacterInfoAsync(id);

            if (!response.IsSuccessStatusCode())
            {
                await "Character not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                return;
            }

            if (!response.Body.HasImage)
            {
                await "There is no character image!".ToResponse(405).ExecuteResultAsync(ControllerContext);
                return;
            }

            var exe = new Executable($"update cards-{id}", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var userRelease = new List <string>()
                    {
                        "users"
                    };
                    var cards = db.Cards.Where(x => x.Character == id);

                    foreach (var card in cards)
                    {
                        card.Image = response.Body.PictureUrl;

                        try
                        {
                            _waifu.DeleteCardImageIfExist(card);
                            _ = _waifu.GenerateAndSaveCardAsync(card).Result;
                        }
                        catch (Exception) { }

                        userRelease.Add($"user-{card.GameDeckId}");
                    }

                    db.SaveChanges();

                    QueryCacheManager.ExpireTag(userRelease.ToArray());
                }
            }));

            await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

            await "Started!".ToResponse(200).ExecuteResultAsync(ControllerContext);
        }
Beispiel #10
0
        public async Task UpdateCardInfoAsync(ulong id, [FromBody] Models.CharacterCardInfoUpdate newData)
        {
            var exe = new Executable($"update cards-{id} img", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var userRelease = new List <string>()
                    {
                        "users"
                    };
                    var cards = db.Cards.Where(x => x.Character == id);

                    foreach (var card in cards)
                    {
                        if (newData?.ImageUrl != null)
                        {
                            card.Image = newData.ImageUrl;
                        }

                        if (newData?.CharacterName != null)
                        {
                            card.Name = newData.CharacterName;
                        }

                        if (newData?.CardSeriesTitle != null)
                        {
                            card.Title = newData.CardSeriesTitle;
                        }

                        try
                        {
                            _waifu.DeleteCardImageIfExist(card);
                            _ = _waifu.GenerateAndSaveCardAsync(card).Result;
                        }
                        catch (Exception) { }

                        userRelease.Add($"user-{card.GameDeckId}");
                    }

                    db.SaveChanges();

                    QueryCacheManager.ExpireTag(userRelease.ToArray());
                }
            }));

            await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

            await "Started!".ToResponse(200).ExecuteResultAsync(ControllerContext);
        }
Beispiel #11
0
 private Task CreateUserTask(SocketGuildUser user)
 {
     return(new Task(() =>
     {
         using (var db = new Database.UserContext(_config))
         {
             if (!db.Users.Any(x => x.Id == user.Id))
             {
                 var bUser = new Database.Models.User().Default(user.Id);
                 db.Users.Add(bUser);
                 db.SaveChanges();
             }
         }
     }));
 }
Beispiel #12
0
        public async Task ModifyPointsTCAsync(ulong id, [FromBody, Required] long value)
        {
            using (var db = new Database.UserContext(_config))
            {
                var user = db.Users.FirstOrDefault(x => x.Shinden == id);
                if (user == null)
                {
                    await "User not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                    return;
                }

                var exe = new Executable($"api-tc su{id} ({value})", new Task(() =>
                {
                    using (var dbc = new Database.AnalyticsContext(_config))
                    {
                        dbc.TransferData.Add(new Database.Models.Analytics.TransferAnalytics()
                        {
                            Value     = value,
                            DiscordId = user.Id,
                            Date      = DateTime.Now,
                            ShindenId = user.Shinden,
                            Source    = Database.Models.Analytics.TransferSource.ByShindenId,
                        });

                        dbc.SaveChanges();
                    }

                    using (var dbs = new Database.UserContext(_config))
                    {
                        user        = dbs.Users.FirstOrDefault(x => x.Shinden == id);
                        user.TcCnt += value;

                        dbs.SaveChanges();

                        QueryCacheManager.ExpireTag(new string[] { $"user-{user.Id}", "users" });
                    }
                }));

                await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                await "TC added!".ToResponse(200).ExecuteResultAsync(ControllerContext);
            }
        }
Beispiel #13
0
        public async Task GiveUserAPackAsync([FromBody] Models.CardBoosterPack boosterPack)
        {
            if (boosterPack == null)
            {
                await "Model is Invalid".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return;
            }

            var pack = boosterPack.ToRealPack();

            if (pack == null)
            {
                await "Data is Invalid".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return;
            }

            var currUser = ControllerContext.HttpContext.User;

            if (currUser.HasClaim(x => x.Type == "DiscordId"))
            {
                if (ulong.TryParse(currUser.Claims.First(x => x.Type == "DiscordId").Value, out var discordId))
                {
                    var exe = new Executable($"api-packet u{discordId}", new Task(() =>
                    {
                        using (var db = new Database.UserContext(_config))
                        {
                            var botUser = db.GetUserOrCreateAsync(discordId).Result;
                            botUser.GameDeck.BoosterPacks.Add(pack);

                            db.SaveChanges();

                            QueryCacheManager.ExpireTag(new string[] { $"user-{botUser.Id}", "users" });
                        }
                    }));

                    await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                    await "Booster pack added!".ToResponse(200).ExecuteResultAsync(ControllerContext);
                    return;
                }
            }
            await "The appropriate claim was not found".ToResponse(403).ExecuteResultAsync(ControllerContext);
        }
Beispiel #14
0
        private Executable GetSafariExe(EmbedBuilder embed, IUserMessage msg, Card newCard,
                                        SafariImage pokeImage, ICharacterInfo character, ITextChannel trashChannel, IUser winner)
        {
            return(new Executable("safari", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var botUser = db.GetUserOrCreateAsync(winner.Id).Result;
                    botUser.GameDeck.Cards.Add(newCard);
                    db.SaveChanges();

                    QueryCacheManager.ExpireTag(new string[] { $"user-{botUser.Id}", "users" });
                }

                _ = Task.Run(async() =>
                {
                    try
                    {
                        embed.ImageUrl = await _waifu.GetSafariViewAsync(pokeImage, character, newCard, trashChannel);
                        embed.Description = $"{winner.Mention} zdobył na polowaniu i wsadził do klatki:\n"
                                            + $"{newCard.GetString(false, false, true)}\n({newCard.Title})";
                        await msg.ModifyAsync(x => x.Embed = embed.Build());

                        var privEmb = new EmbedBuilder()
                        {
                            Color = EMType.Info.Color(),
                            Description = $"Na [polowaniu]({msg.GetJumpUrl()}) zdobyłeś: {newCard.GetString(false, false, true)}"
                        };

                        var priv = await winner.GetOrCreateDMChannelAsync();
                        if (priv != null)
                        {
                            await priv.SendMessageAsync("", false, privEmb.Build());
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.Log($"In Safari: {ex}");
                    }
                });
            })));
        }
Beispiel #15
0
        private void SpawnUserPacket(SocketUser user)
        {
            var exe = new Executable($"packet u{user.Id}", new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var botUser = db.GetUserOrCreateAsync(user.Id).Result;
                    if (botUser.IsBlacklisted)
                    {
                        return;
                    }

                    botUser.GameDeck.BoosterPacks.Add(new BoosterPack
                    {
                        CardCnt   = 2,
                        MinRarity = Rarity.E,
                        IsCardFromPackTradable = true,
                        Name = "Pakiet kart za aktywność",
                        CardSourceFromPack = CardSource.Activity
                    });
                    db.SaveChanges();
                }
            }));

            _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

            var gUser = user as SocketGuildUser;

            using (var db = new Database.AnalyticsContext(_config))
            {
                db.UsersData.Add(new Database.Models.Analytics.UserAnalytics
                {
                    Value       = 1,
                    UserId      = user.Id,
                    MeasureDate = DateTime.Now,
                    GuildId     = gUser?.Guild?.Id ?? 0,
                    Type        = Database.Models.Analytics.UserAnalyticsEventType.Pack
                });
                db.SaveChanges();
            }
        }
Beispiel #16
0
        public async Task RegisterUserAsync([FromBody, Required] UserRegistration id)
        {
            if (id == null)
            {
                var body = new System.IO.StreamReader(ControllerContext.HttpContext.Request.Body);
                body.BaseStream.Seek(0, System.IO.SeekOrigin.Begin);
                var requestBody = body.ReadToEnd();

                _logger.Log(requestBody);

                await "Model is Invalid!".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return;
            }

            var user = _client.GetUser(id.DiscordUserId);

            if (user == null)
            {
                await "User not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                return;
            }

            using (var db = new Database.UserContext(_config))
            {
                var botUser = db.Users.FirstOrDefault(x => x.Id == id.DiscordUserId);
                if (botUser != null)
                {
                    if (botUser.Shinden != 0)
                    {
                        await "User already connected!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                        return;
                    }
                }

                var response = await _shClient.Search.UserAsync(id.Username);

                if (!response.IsSuccessStatusCode())
                {
                    await "Can't connect to shinden!".ToResponse(403).ExecuteResultAsync(ControllerContext);
                    return;
                }

                var sUser = (await _shClient.User.GetAsync(response.Body.First())).Body;
                if (sUser.ForumId.Value != id.ForumUserId)
                {
                    await "Something went wrong!".ToResponse(500).ExecuteResultAsync(ControllerContext);
                    return;
                }

                var exe = new Executable($"api-register u{id.DiscordUserId}", new Task(() =>
                {
                    using (var dbs = new Database.UserContext(_config))
                    {
                        botUser         = dbs.GetUserOrCreateAsync(id.DiscordUserId).Result;
                        botUser.Shinden = sUser.Id;

                        dbs.SaveChanges();

                        QueryCacheManager.ExpireTag(new string[] { $"user-{user.Id}", "users" });
                    }
                }));

                await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                await "User connected!".ToResponse(200).ExecuteResultAsync(ControllerContext);
            }
        }
Beispiel #17
0
        public async Task <UserWithToken> GiveShindenUserAPacksAsync(ulong id, [FromBody] List <Models.CardBoosterPack> boosterPacks)
        {
            if (boosterPacks?.Count < 1)
            {
                await "Model is Invalid".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return(null);
            }

            var packs = new List <BoosterPack>();

            foreach (var pack in boosterPacks)
            {
                var rPack = pack.ToRealPack();
                if (rPack != null)
                {
                    packs.Add(rPack);
                }
            }

            if (packs.Count < 1)
            {
                await "Data is Invalid".ToResponse(500).ExecuteResultAsync(ControllerContext);
                return(null);
            }

            using (var db = new Database.UserContext(_config))
            {
                var user = await db.GetCachedFullUserByShindenIdAsync(id);

                if (user == null)
                {
                    await "User not found!".ToResponse(404).ExecuteResultAsync(ControllerContext);
                    return(null);
                }

                var discordId = user.Id;
                var exe       = new Executable($"api-packet u{discordId}", new Task(() =>
                {
                    using (var dbs = new Database.UserContext(_config))
                    {
                        var botUser = dbs.GetUserOrCreateAsync(discordId).Result;

                        foreach (var pack in packs)
                        {
                            botUser.GameDeck.BoosterPacks.Add(pack);
                        }

                        dbs.SaveChanges();

                        QueryCacheManager.ExpireTag(new string[] { $"user-{botUser.Id}", "users" });
                    }
                }));

                await _executor.TryAdd(exe, TimeSpan.FromSeconds(1));

                TokenData tokenData = null;
                var       currUser  = ControllerContext.HttpContext.User;
                if (currUser.HasClaim(x => x.Type == ClaimTypes.Webpage))
                {
                    tokenData = UserTokenBuilder.BuildUserToken(_config, user);
                }

                return(new UserWithToken()
                {
                    Expire = tokenData?.Expire,
                    Token = tokenData?.Token,
                    User = user,
                });
            }
        }
Beispiel #18
0
        private Task CreateTask(SocketGuildUser user, ISocketMessageChannel channel, long exp, ulong messages, ulong commands, ulong characters)
        {
            return(new Task(() =>
            {
                using (var db = new Database.UserContext(_config))
                {
                    var usr = db.GetUserOrCreateAsync(user.Id).Result;
                    if (usr == null)
                    {
                        return;
                    }

                    if ((DateTime.Now - usr.MeasureDate.AddMonths(1)).TotalSeconds > 1)
                    {
                        usr.MeasureDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
                        usr.MessagesCntAtDate = usr.MessagesCnt;
                        usr.CharacterCntFromDate = characters;
                    }
                    else
                    {
                        usr.CharacterCntFromDate += characters;
                    }

                    usr.ExpCnt += exp;
                    usr.MessagesCnt += messages;
                    usr.CommandsCnt += commands;

                    var newLevel = CalculateLevel(usr.ExpCnt);
                    if (newLevel != usr.Level)
                    {
                        usr.Level = newLevel;
                        _ = Task.Run(async() => { await NotifyAboutLevelAsync(user, channel, newLevel); });
                    }

                    _ = Task.Run(async() =>
                    {
                        using (var dbc = new Database.GuildConfigContext(_config))
                        {
                            var config = await dbc.GetCachedGuildFullConfigAsync(user.Guild.Id);
                            if (config == null)
                            {
                                return;
                            }

                            foreach (var lvlRole in config.RolesPerLevel)
                            {
                                var role = user.Guild.GetRole(lvlRole.Role);
                                if (role == null)
                                {
                                    continue;
                                }

                                bool hasRole = user.Roles.Any(x => x.Id == role.Id);
                                if (newLevel >= (long)lvlRole.Level)
                                {
                                    if (!hasRole)
                                    {
                                        await user.AddRoleAsync(role);
                                    }
                                }
                                else if (hasRole)
                                {
                                    await user.RemoveRoleAsync(role);
                                }
                            }
                        }
                    });

                    db.SaveChanges();
                }
            }));
        }