Exemplo n.º 1
0
        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())
                );
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
        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);
        }
Exemplo n.º 4
0
    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);
    }
Exemplo n.º 5
0
 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;
 }
Exemplo n.º 6
0
 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));
     }
 }
Exemplo n.º 7
0
 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;
 }
Exemplo n.º 8
0
        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);
        }
Exemplo n.º 9
0
 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>();
 }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
 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>();
 }
Exemplo n.º 12
0
 protected virtual void OnMessageCreateEvent(MessageInitializer messageinitializer)
 {
     MessageCreateEvent?.Invoke(messageinitializer);
 }
Exemplo n.º 13
0
 public static PermissionSet PermissionsFor(Guild guild, Channel channel, MessageCreateEvent msg) =>
 PermissionsFor(guild, channel, msg.Author.Id, msg.Member?.Roles);
Exemplo n.º 14
0
 public static PermissionSet PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) =>
 PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member?.Roles);
Exemplo n.º 15
0
 public static Task <PermissionSet> PermissionsFor(this IDiscordCache cache, MessageCreateEvent message) =>
 PermissionsFor(cache, message.ChannelId, message.Author.Id, message.Member, message.WebhookId != null);