Esempio n. 1
0
        public async Task CheckAsync(IDiscordMessage e)
        {
            if (e.Author.IsBot)
            {
                return;
            }

            if (experienceLock.CurrentCount == 0)
            {
                return;
            }

            try
            {
                using var scope = app.Services.CreateScope();
                var services = scope.ServiceProvider;

                if (e is IDiscordGuildMessage guildMessage)
                {
                    var key = GetContextKey(guildMessage.GuildId, e.Author.Id);
                    if (lastTimeExpGranted
                        .GetOrAdd(e.Author.Id, DateTime.Now)
                        .AddMinutes(1) < DateTime.Now)
                    {
                        var bonusExp  = MikiRandom.Next(1, 4);
                        var expObject = new ExperienceAdded
                        {
                            UserId     = (long)e.Author.Id,
                            GuildId    = (long)guildMessage.GuildId,
                            Experience = bonusExp,
                            Name       = e.Author.Username,
                        };

                        int currentLocalExp = await cache.GetAsync <int>(key);

                        if (currentLocalExp == 0)
                        {
                            var dbContext  = services.GetService <DbContext>();
                            var expProfile = await GetOrCreateExperienceProfileAsync(
                                dbContext, e.Author as IDiscordGuildUser);

                            await UpdateCacheExperienceAsync(expObject);

                            currentLocalExp = expProfile.Experience;
                        }

                        currentLocalExp += bonusExp;
                        experienceQueue.AddOrUpdate(e.Author.Id, expObject, (_, experience) =>
                        {
                            experience.Experience += expObject.Experience;
                            return(experience);
                        });

                        int level = User.CalculateLevel(currentLocalExp);
                        if (User.CalculateLevel(currentLocalExp - bonusExp) != level)
                        {
                            await LevelUpLocalAsync(e, level)
                            .ConfigureAwait(false);
                        }

                        lastTimeExpGranted.AddOrUpdate(
                            e.Author.Id, DateTime.Now, (x, d) => DateTime.Now);
                        await UpdateCacheExperienceAsync(expObject);
                    }
                }

                if (DateTime.Now >= this.lastDbSync + new TimeSpan(0, 1, 0))
                {
                    try
                    {
                        await experienceLock.WaitAsync();

                        Log.Message($"Applying Experience for {this.experienceQueue.Count} users");
                        this.lastDbSync = DateTime.Now;
                        var context = services.GetService <DbContext>();

                        await UpdateGlobalDatabaseAsync(context);
                        await UpdateLocalDatabaseAsync(context);
                        await UpdateGuildDatabaseAsync(context);

                        await context.SaveChangesAsync();
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex.Message + "\n" + ex.StackTrace);
                        sentryClient.CaptureException(ex);
                    }
                    finally
                    {
                        this.experienceQueue.Clear();
                        experienceLock.Release();
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex);
                sentryClient.CaptureException(ex);
            }
        }
Esempio n. 2
0
        public async Task CheckAsync(IDiscordMessage e)
        {
            if (e.Author.IsBot)
            {
                return;
            }

            if (isSyncing)
            {
                return;
            }

            try
            {
                if (await e.GetChannelAsync() is IDiscordGuildChannel channel)
                {
                    string key = GetContextKey(channel.GuildId, e.Author.Id);

                    if (lastTimeExpGranted.GetOrAdd(e.Author.Id, DateTime.Now).AddMinutes(1) < DateTime.Now)
                    {
                        int currentExp = 0;
                        if (!await Global.RedisClient.ExistsAsync(key))
                        {
                            using (var context = new MikiContext())
                            {
                                LocalExperience user = await LocalExperience.GetAsync(
                                    context,
                                    (long)channel.GuildId,
                                    e.Author
                                    );

                                await Global.RedisClient.AddAsync(key, user.Experience);

                                currentExp = user.Experience;
                            }
                        }
                        else
                        {
                            currentExp = await Global.RedisClient.GetAsync <int>(key);
                        }

                        var bonusExp = MikiRandom.Next(1, 4);
                        currentExp += bonusExp;

                        if (!experienceQueue.ContainsKey(e.Author.Id))
                        {
                            var expObject = new ExperienceAdded()
                            {
                                UserId     = e.Author.Id.ToDbLong(),
                                GuildId    = channel.GuildId.ToDbLong(),
                                Experience = bonusExp,
                                Name       = e.Author.Username,
                            };

                            experienceQueue.AddOrUpdate(e.Author.Id, expObject, (u, eo) =>
                            {
                                eo.Experience += expObject.Experience;
                                return(eo);
                            });
                        }
                        else
                        {
                            experienceQueue[e.Author.Id].Experience += bonusExp;
                        }

                        int level = User.CalculateLevel(currentExp);

                        if (User.CalculateLevel(currentExp - bonusExp) != level)
                        {
                            await LevelUpLocalAsync(e, level);
                        }

                        lastTimeExpGranted.AddOrUpdate(e.Author.Id, DateTime.Now, (x, d) => DateTime.Now);

                        await Global.RedisClient.AddAsync(key, currentExp);
                    }
                }

                if (DateTime.Now >= lastDbSync + new TimeSpan(0, 1, 0))
                {
                    isSyncing = true;
                    Log.Message($"Applying Experience for {experienceQueue.Count} users");
                    lastDbSync = DateTime.Now;

                    try
                    {
                        await UpdateGlobalDatabase();
                        await UpdateLocalDatabase();
                        await UpdateGuildDatabase();
                    }
                    catch (Exception ex)
                    {
                        Log.Error(ex.Message + "\n" + ex.StackTrace);
                    }
                    finally
                    {
                        experienceQueue.Clear();
                        isSyncing = false;
                    }
                    Log.Message($"Done Applying!");
                }
            }
            catch (Exception ex)
            {
                Log.Error(ex.ToString());
            }
        }
Esempio n. 3
0
 private async Task UpdateCacheExperienceAsync(ExperienceAdded experience)
 {
     var key = GetContextKey((ulong)experience.GuildId, (ulong)experience.UserId);
     await cache.UpsertAsync(key, experience.Experience, TimeSpan.FromMinutes(5));
 }