I already know how to set someone to auto-follow a record based on specific criteria (record created, modified, etc) by inserting records into the EntitySubscription object.

What I am trying to accomplish is a process in which, for a specific internal object, anyone who is @Mentioned on a chatter text post that is related to that object type will automatically become a follower of the record that they were mentioned in.

I can query for the information I need from the FeedItem object with [SELECT Id,ParentId,Body FROM FeedItem WHERE Type = 'TextPost'], but the body looks like this:

@Person One @Peron Two @Person Number Three can one of you provide me with a specific account that you are referring to?

Issue: I don't use regex often, but figured it would be useful here, however my problem is that there isn't really any clear 'line in the sand' in the Body of the FeedItem for me to tell the regex when to start/stop and guarantee that I've captured the full name of the user, and without the full name of the user I can't properly query for their User Id and insert their EntitySubscription record(s).

In my example above you'll note that I can't just rely on the two words that immediately follow an @ symbol, because there are some users who have a multi part name (Morgan Del Ray, as an example). I was hoping that the @Mentions would be formatted as @[Mention] so that I could use the [ ] as my limiters, but alas it is not.

Question: Is there any way I can guarantee this functionality will capture the full name using an advanced form of regex? Or is there perhaps another object that actually stores the Id references of the users that were tagged in a post? Somehow Salesforce manages to turn the @Mention tag into a link to the User, but I don't see that in the FeedItem object so I'm not sure where (or if) I can reference that data directly.


I'll just repost the code I used for a similar requirement, without including any of the additional commentary I wrote here. I can't really speak to how well the ConnectAPI approaches work nor their speed. But I know this approach works because I have implemented it in a live environment.

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
            for (Id userId : mention.getUserIds())
                // do stuff

    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;
| improve this answer | |

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