private void StoreMessage(MessageCreateEvent mce) { byte flags = 0; if (mce.IsAction) { flags |= ADOMessage.IS_ACTION; } Wrapper.RunCommand( @"INSERT INTO `sqc_messages` (" + @"`msg_id`, `msg_channel_id`, `msg_sender_id`, `msg_sender_name`, `msg_sender_colour`, `msg_sender_rank`" + @", `msg_sender_nick`, `msg_sender_perms`, `msg_text`, `msg_flags`, `msg_created`" + @") VALUES (" + @"@id, @channelId, @senderId, @senderName, @senderColour, @senderRank, @senderNick, @senderPerms" + @", @text, @flags, " + Wrapper.FromUnixTime(@"@created") + @");", Wrapper.CreateParam(@"id", mce.MessageId), Wrapper.CreateParam(@"channelId", mce.ChannelId), Wrapper.CreateParam(@"senderId", mce.UserId), Wrapper.CreateParam(@"senderName", mce.UserName), Wrapper.CreateParam(@"senderColour", mce.UserColour.Raw), Wrapper.CreateParam(@"senderRank", mce.UserRank), Wrapper.CreateParam(@"senderNick", mce.UserNickName), Wrapper.CreateParam(@"senderPerms", mce.UserPermissions), Wrapper.CreateParam(@"text", mce.Text), Wrapper.CreateParam(@"flags", flags), Wrapper.CreateParam(@"created", mce.DateTime.ToUnixTimeSeconds()) ); }
private async Task <MessageCreateEvent> GetMessageCreateEvent(MessageUpdateEvent evt, CachedMessage lastMessage, Channel channel) { var referencedMessage = await GetReferencedMessage(evt.ChannelId, lastMessage.ReferencedMessage); var messageReference = lastMessage.ReferencedMessage != null ? new Message.Reference(channel.GuildId, evt.ChannelId, lastMessage.ReferencedMessage.Value) : null; var messageType = lastMessage.ReferencedMessage != null ? Message.MessageType.Reply : Message.MessageType.Default; // TODO: is this missing anything? var equivalentEvt = new MessageCreateEvent { Id = evt.Id, ChannelId = evt.ChannelId, GuildId = channel.GuildId, Author = evt.Author.Value, Member = evt.Member.Value, Content = evt.Content.Value, Attachments = evt.Attachments.Value ?? Array.Empty <Message.Attachment>(), MessageReference = messageReference, ReferencedMessage = referencedMessage, Type = messageType, }; return(equivalentEvt); }
public async Task <MessageCreateEvent> SendMessageAsync(long userId, string text, QuickReply quickReply) { MessageCreateEvent messageCreateEvent = new MessageCreateEvent() { Timestamp = DateTime.UtcNow, Data = new MessageCreateData() { Target = new Target() { RecipientId = userId }, Data = new MessageData() { Text = text, QuickReply = quickReply } } }; Event <MessageCreateEvent> eventContainer = new Event <MessageCreateEvent>() { Data = messageCreateEvent }; return((await PostAsync <Event <MessageCreateEvent> >(eventContainer, ApiUri + "events/new.json")).Data); }
public async Task <bool> HandleIncomingMessage(MessageCreateEvent message, MessageContext ctx, Guild guild, Channel channel, bool allowAutoproxy, PermissionSet botPermissions) { if (!ShouldProxy(channel, message, ctx)) { return(false); } var autoproxySettings = await _repo.GetAutoproxySettings(ctx.SystemId.Value, guild.Id, null); if (autoproxySettings.AutoproxyMode == AutoproxyMode.Latch && IsUnlatch(message)) { // "unlatch" await _repo.UpdateAutoproxy(ctx.SystemId.Value, guild.Id, null, new() { AutoproxyMember = null }); return(false); } var rootChannel = await _cache.GetRootChannel(message.ChannelId); List <ProxyMember> members; // Fetch members and try to match to a specific member using (_metrics.Measure.Timer.Time(BotMetrics.ProxyMembersQueryTime)) members = (await _repo.GetProxyMembers(message.Author.Id, message.GuildId !.Value)).ToList(); if (!_matcher.TryMatch(ctx, autoproxySettings, members, out var match, message.Content, message.Attachments.Length > 0, allowAutoproxy)) { return(false); } // this is hopefully temporary, so not putting it into a separate method if (message.Content != null && message.Content.Length > 2000) { throw new PKError("PluralKit cannot proxy messages over 2000 characters in length."); } // Permission check after proxy match so we don't get spammed when not actually proxying if (!CheckBotPermissionsOrError(botPermissions, rootChannel.Id)) { return(false); } // this method throws, so no need to wrap it in an if statement CheckProxyNameBoundsOrError(match.Member.ProxyName(ctx)); // Check if the sender account can mention everyone/here + embed links // we need to "mirror" these permissions when proxying to prevent exploits var senderPermissions = PermissionExtensions.PermissionsFor(guild, rootChannel, message); var allowEveryone = senderPermissions.HasFlag(PermissionSet.MentionEveryone); var allowEmbeds = senderPermissions.HasFlag(PermissionSet.EmbedLinks); // Everything's in order, we can execute the proxy! await ExecuteProxy(message, ctx, autoproxySettings, match, allowEveryone, allowEmbeds); return(true); }
public MemoryMessageUser(MessageCreateEvent mce) { UserId = mce.User.UserId; UserName = mce.User.UserName; Colour = mce.User.Colour; Rank = mce.User.Rank; NickName = mce.User.NickName; Permissions = mce.User.Permissions; }
private void StoreMessage(MessageCreateEvent mce) { lock (Sync) { MemoryMessageChannel channel = Channels.FirstOrDefault(c => mce.ChannelId.Equals(mce.ChannelId)); if (channel == null) { return; // This is basically an invalid state } Messages.Add(new MemoryMessage(channel, mce)); } }
public MemoryMessage(MemoryMessageChannel channel, MessageCreateEvent mce) { if (mce == null) { throw new ArgumentNullException(nameof(mce)); } MessageId = mce.MessageId; Channel = channel ?? throw new ArgumentNullException(nameof(channel)); Sender = new MemoryMessageUser(mce); Text = mce.Text; IsAction = mce.IsAction; Created = mce.DateTime; }
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 (channel.Type != Channel.ChannelType.GuildText) { return; } var guild = _cache.GetGuild(channel.GuildId !.Value); // Only react to the last message in the channel if (_lastMessageCache.GetLastMessage(evt.ChannelId) != 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); // TODO: is this missing anything? var equivalentEvt = new MessageCreateEvent { Id = evt.Id, ChannelId = evt.ChannelId, GuildId = channel.GuildId, Author = evt.Author.Value, Member = evt.Member.Value, Content = evt.Content.Value, Attachments = evt.Attachments.Value ?? Array.Empty <Message.Attachment>() }; var botPermissions = _bot.PermissionsIn(channel.Id); await _proxy.HandleIncomingMessage(shard, equivalentEvt, ctx, allowAutoproxy : false, guild : guild, channel : channel, botPermissions : botPermissions); }
public Context(ILifetimeScope provider, Shard shard, Guild?guild, Channel channel, MessageCreateEvent message, int commandParseOffset, PKSystem senderSystem, MessageContext messageContext) { _message = message; _shard = shard; _guild = guild; _channel = channel; _senderSystem = senderSystem; _messageContext = messageContext; _cache = provider.Resolve <IDiscordCache>(); _db = provider.Resolve <IDatabase>(); _repo = provider.Resolve <ModelRepository>(); _metrics = provider.Resolve <IMetrics>(); _provider = provider; _commandMessageService = provider.Resolve <CommandMessageService>(); _parameters = new Parameters(message.Content?.Substring(commandParseOffset)); _rest = provider.Resolve <DiscordApiClient>(); _cluster = provider.Resolve <Cluster>(); }
public async Task <bool> HandleIncomingMessage(Shard shard, MessageCreateEvent message, MessageContext ctx, Guild guild, Channel channel, bool allowAutoproxy, PermissionSet botPermissions) { if (!ShouldProxy(channel, message, ctx)) { return(false); } // Fetch members and try to match to a specific member await using var conn = await _db.Obtain(); List <ProxyMember> members; using (_metrics.Measure.Timer.Time(BotMetrics.ProxyMembersQueryTime)) members = (await _repo.GetProxyMembers(conn, message.Author.Id, message.GuildId !.Value)).ToList(); if (!_matcher.TryMatch(ctx, members, out var match, message.Content, message.Attachments.Length > 0, allowAutoproxy)) { return(false); } // Permission check after proxy match so we don't get spammed when not actually proxying if (!await CheckBotPermissionsOrError(botPermissions, message.ChannelId)) { return(false); } // this method throws, so no need to wrap it in an if statement CheckProxyNameBoundsOrError(match.Member.ProxyName(ctx)); // Check if the sender account can mention everyone/here + embed links // we need to "mirror" these permissions when proxying to prevent exploits var senderPermissions = PermissionExtensions.PermissionsFor(guild, channel, message); var allowEveryone = senderPermissions.HasFlag(PermissionSet.MentionEveryone); var allowEmbeds = senderPermissions.HasFlag(PermissionSet.EmbedLinks); // Everything's in order, we can execute the proxy! await ExecuteProxy(shard, conn, message, ctx, match, allowEveryone, allowEmbeds); return(true); }
public Context(ILifetimeScope provider, int shardId, Guild?guild, Channel channel, MessageCreateEvent message, int commandParseOffset, PKSystem senderSystem, SystemConfig config, MessageContext messageContext) { Message = (Message)message; ShardId = shardId; Guild = guild; Channel = channel; System = senderSystem; Config = config; MessageContext = messageContext; Cache = provider.Resolve <IDiscordCache>(); Database = provider.Resolve <IDatabase>(); Repository = provider.Resolve <ModelRepository>(); _metrics = provider.Resolve <IMetrics>(); _provider = provider; _commandMessageService = provider.Resolve <CommandMessageService>(); CommandPrefix = message.Content?.Substring(0, commandParseOffset); Parameters = new Parameters(message.Content?.Substring(commandParseOffset)); Rest = provider.Resolve <DiscordApiClient>(); Cluster = provider.Resolve <Cluster>(); }
protected virtual void OnMessageCreateEvent(MessageInitializer messageinitializer) { MessageCreateEvent?.Invoke(messageinitializer); }
public static PermissionSet PermissionsFor(Guild guild, Channel channel, MessageCreateEvent msg) => PermissionsFor(guild, channel, msg.Author.Id, msg.Member?.Roles);
public static PermissionSet PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) => PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member?.Roles);
public static Task <PermissionSet> PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) => PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member, message.WebhookId != null);