3

There are many questions out the about how to add @mentions to a chatter post, but this question is the other way around:

How do I read @mentions from a FeedItem in the trigger context?

I need to be able to reliably get the Ids of any User record (and maybe Group record in the future) which is @mentioned. The idea is that we want to use Apex Sharing to bridge the gap if someone gets @mentioned but doesn't yet have access to the record.

5

So I'd love to see someone else find a better way to do it, but I have discovered one working option: serialization. When looking at a serialized FeedItem in my debug logs, I saw something like:

..."RawBody": "<p>Sample text... {@005000000000000AAA}</p>"...

However, I wasn't able to acceess this data via normal means. When I look at the Body, it would look like:

<p>Sample text... @FirstName LastName</p>

Which is more of a pain to parse from an expression standpoint and also requires an additional query. Yuck. Anyway, here's a simple proof of concept how to get the @mentions from trigger FeedItem records:

public with sharing class FeedItemService
{
    public static final String USER_PREFIX = SObjectType.User.getKeyPrefix();
    public static final String EXPRESSION = '\\{@(' + USER_PREFIX +'[0-9a-zA-Z]{15})\\}';
    public static Pattern RAW_MENTION = Pattern.compile(EXPRESSION);

    public static void parse(List<FeedItem> feedItems)
    {
        for (Mention mention : (List<Mention>)JSON.deserialize(
            JSON.serialize(feedItems), List<Mention>.class
        )){
            system.debug(mention);
            // or do something more interesting
        }
    }

    public class Mention
    {
        final String rawBody;
        final Id parentId;
        Set<Id> getUserIds()
        {
            Set<Id> userIds = new Set<Id>();
            Matcher m = RAW_MENTION.matcher(rawBody);
            while (m.find()) userIds.add(m.group(1));
            return userIds;
        }
    }
}

I do some additional filtering before parsing any records to at least make sure the Body field contains an @ character, since serialization tends to be an expensive process.

| improve this answer | |
  • 1
    I'm really impressed that you noticed that the RawBody is serialized and can be used to extract the mentioned IDs. One enhancement you could make is to also parse CollaborationGroup IDs, since Chatter groups can also be mentioned. I'm going to post an alternate solution, but I suspect that yours is more performant. – alouie Nov 4 '16 at 23:51
5

I suspect that Adrian's solution is the more performant one, but here's a solution that doesn't use the undocumented rawBody serialization trick. It uses the ConnectApi Apex namespace, because @mentions in Chatter are only supported in ConnectApi or the Chatter REST API.

In your FeedItem trigger, re-fetch the feed items using ConnectApi.ChatterFeeds.getFeedElementBatch and then inspect the ConnectApi.FeedBody as shown in ConnectApiHelper:

trigger MyTrigger on FeedItem (after insert) {
    String communityId = Network.getNetworkId();
    List<String> feedItemIds = new List<String>();
    for (FeedItem f : trigger.new) {
        feedItemIds.add(f.id);
    }

    // Re-fetch the feed items passed into the trigger
    ConnectApi.BatchResult[] results = ConnectApi.ChatterFeeds.getFeedElementBatch(communityId, feedItemIds);

    for (ConnectApi.BatchResult result : results) {
        if (result.isSuccess()) {
            Object theResult = result.getResult();
            if (theResult instanceof ConnectApi.FeedItem) {
                ConnectApi.FeedItem item = (ConnectApi.FeedItem) theResult;

                for (ConnectApi.MessageSegment segment : item.body.messageSegments) {
                    if (segment instanceof ConnectApi.MentionSegment) {
                        ConnectApi.MentionSegment theMention = (ConnectApi.MentionSegment) segment;
                        String mentionedId = theMention.record.id;
                        // Do what you need to do with mentionedId...
                        System.debug('Mentioned ID: ' + mentionedId);
                    }
                }
            }
        }
    }
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.