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); } }
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()); } }
private async Task UpdateCacheExperienceAsync(ExperienceAdded experience) { var key = GetContextKey((ulong)experience.GuildId, (ulong)experience.UserId); await cache.UpsertAsync(key, experience.Experience, TimeSpan.FromMinutes(5)); }