public async Task CollectStats() { var stopwatch = new Stopwatch(); stopwatch.Start(); // Aggregate guild/channel stats var guildCount = 0; var channelCount = 0; // No LINQ today, sorry await foreach (var guild in _cache.GetAllGuilds()) { guildCount++; foreach (var channel in _cache.GetGuildChannels(guild.Id)) { if (DiscordUtils.IsValidGuildChannel(channel)) { channelCount++; } } } _metrics.Measure.Gauge.SetValue(BotMetrics.Guilds, guildCount); _metrics.Measure.Gauge.SetValue(BotMetrics.Channels, channelCount); // Aggregate DB stats var counts = await _db.Execute(c => c.QueryFirstAsync <Counts>("select (select count(*) from systems) as systems, (select count(*) from members) as members, (select count(*) from switches) as switches, (select count(*) from messages) as messages, (select count(*) from groups) as groups")); _metrics.Measure.Gauge.SetValue(CoreMetrics.SystemCount, counts.Systems); _metrics.Measure.Gauge.SetValue(CoreMetrics.MemberCount, counts.Members); _metrics.Measure.Gauge.SetValue(CoreMetrics.SwitchCount, counts.Switches); _metrics.Measure.Gauge.SetValue(CoreMetrics.MessageCount, counts.Messages); _metrics.Measure.Gauge.SetValue(CoreMetrics.GroupCount, counts.Groups); // Process info var process = Process.GetCurrentProcess(); _metrics.Measure.Gauge.SetValue(CoreMetrics.ProcessPhysicalMemory, process.WorkingSet64); _metrics.Measure.Gauge.SetValue(CoreMetrics.ProcessVirtualMemory, process.VirtualMemorySize64); _metrics.Measure.Gauge.SetValue(CoreMetrics.ProcessPrivateMemory, process.PrivateMemorySize64); _metrics.Measure.Gauge.SetValue(CoreMetrics.ProcessThreads, process.Threads.Count); _metrics.Measure.Gauge.SetValue(CoreMetrics.ProcessHandles, process.HandleCount); _metrics.Measure.Gauge.SetValue(CoreMetrics.CpuUsage, await _cpu.EstimateCpuUsage()); // Database info _metrics.Measure.Gauge.SetValue(CoreMetrics.DatabaseConnections, _countHolder.ConnectionCount); // Other shiz _metrics.Measure.Gauge.SetValue(BotMetrics.WebhookCacheSize, _webhookCache.CacheSize); stopwatch.Stop(); _logger.Debug("Updated metrics in {Time}", stopwatch.ElapsedDuration()); }
public static Task <Channel> MatchChannel(this Context ctx) { if (!MentionUtils.TryParseChannel(ctx.PeekArgument(), out var id)) { return(Task.FromResult <Channel>(null)); } if (!ctx.Cache.TryGetChannel(id, out var channel)) { return(Task.FromResult <Channel>(null)); } if (!DiscordUtils.IsValidGuildChannel(channel)) { return(Task.FromResult <Channel>(null)); } ctx.PopArgument(); return(Task.FromResult(channel)); }
private bool ShouldProxy(Channel channel, Message msg, MessageContext ctx) { // Make sure author has a system if (ctx.SystemId == null) { return(false); } // Make sure channel is a guild text channel and this is a normal message if (!DiscordUtils.IsValidGuildChannel(channel)) { return(false); } if (msg.Type != Message.MessageType.Default && msg.Type != Message.MessageType.Reply) { return(false); } // Make sure author is a normal user if (msg.Author.System == true || msg.Author.Bot || msg.WebhookId != null) { return(false); } // Make sure proxying is enabled here if (!ctx.ProxyEnabled || ctx.InBlacklist) { return(false); } // Make sure we have either an attachment or message content var isMessageBlank = msg.Content == null || msg.Content.Trim().Length == 0; if (isMessageBlank && msg.Attachments.Length == 0) { return(false); } // All good! return(true); }
public async Task Handle(Shard shard, MessageUpdateEvent evt) { if (evt.Author.Value?.Id == _client.User?.Id) { return; } // Edit message events sometimes arrive with missing data; double-check it's all there if (!evt.Content.HasValue || !evt.Author.HasValue || !evt.Member.HasValue) { return; } var channel = _cache.GetChannel(evt.ChannelId); if (!DiscordUtils.IsValidGuildChannel(channel)) { return; } var guild = _cache.GetGuild(channel.GuildId !.Value); var lastMessage = _lastMessageCache.GetLastMessage(evt.ChannelId); // Only react to the last message in the channel if (lastMessage?.Id != evt.Id) { return; } // Just run the normal message handling code, with a flag to disable autoproxying MessageContext ctx; await using (var conn = await _db.Obtain()) using (_metrics.Measure.Timer.Time(BotMetrics.MessageContextQueryTime)) ctx = await _repo.GetMessageContext(conn, evt.Author.Value !.Id, channel.GuildId !.Value, evt.ChannelId); var equivalentEvt = await GetMessageCreateEvent(evt, lastMessage, channel); var botPermissions = _bot.PermissionsIn(channel.Id); await _proxy.HandleIncomingMessage(shard, equivalentEvt, ctx, allowAutoproxy : false, guild : guild, channel : channel, botPermissions : botPermissions); }
private async ValueTask TryHandleProxyMessageReactions(MessageReactionAddEvent evt) { // Sometimes we get events from users that aren't in the user cache // We just ignore all of those for now, should be quite rare... if (!_cache.TryGetUser(evt.UserId, out var user)) { return; } var channel = _cache.GetChannel(evt.ChannelId); // check if it's a command message first // since this can happen in DMs as well if (evt.Emoji.Name == "\u274c") { await using var conn = await _db.Obtain(); var commandMsg = await _commandMessageService.GetCommandMessage(conn, evt.MessageId); if (commandMsg != null) { await HandleCommandDeleteReaction(evt, commandMsg); return; } } // Proxied messages only exist in guild text channels, so skip checking if we're elsewhere if (!DiscordUtils.IsValidGuildChannel(channel)) { return; } // Ignore reactions from bots (we can't DM them anyway) if (user.Bot) { return; } switch (evt.Emoji.Name) { // Message deletion case "\u274C": // Red X { await using var conn = await _db.Obtain(); var msg = await _repo.GetMessage(conn, evt.MessageId); if (msg != null) { await HandleProxyDeleteReaction(evt, msg); } break; } case "\u2753": // Red question mark case "\u2754": // White question mark { await using var conn = await _db.Obtain(); var msg = await _repo.GetMessage(conn, evt.MessageId); if (msg != null) { await HandleQueryReaction(evt, msg); } break; } case "\U0001F514": // Bell case "\U0001F6CE": // Bellhop bell case "\U0001F3D3": // Ping pong paddle (lol) case "\u23F0": // Alarm clock case "\u2757": // Exclamation mark { await using var conn = await _db.Obtain(); var msg = await _repo.GetMessage(conn, evt.MessageId); if (msg != null) { await HandlePingReaction(evt, msg); } break; } } }