Comments

Overview

Comments support voting, ranking, threading, images, URL previews, mentions and notifications.

Adding Comments

// Adding a comment to an activity
await client.addComment({
  id: "comment_123", // id is optional, but must be unique. will be auto-generated if not provided
  comment: "So great!",
  object_id: "activity_123",
  object_type: "activity",
  custom: {
    sentiment: "positive",
  },
});

// Adding a reply to a comment
await client.addComment({
  comment: "I agree!",
  parent_id: "comment_456",
});

// Adding a comment without triggering push notifications
await client.addComment({
  comment: "Silent comment",
  object_id: "activity_123",
  object_type: "activity",
  skip_push: true,
});

Overview of the comment model

CommentResponse

NameTypeDescriptionConstraints
attachmentsAttachment[]--
confidence_scorenumberConfidence score of the commentRequired
controversy_scorenumberControversy score of the comment-
created_atnumberWhen the comment was createdRequired
customobjectCustom data for the comment-
deleted_atnumberWhen the comment was deleted-
downvote_countintegerNumber of downvotes for this commentRequired
idstringUnique identifier for the commentRequired
latest_reactionsFeedsReactionResponse[]Recent reactions to the comment-
mentioned_usersUserResponse[]Users mentioned in the commentRequired
moderationModerationV2Response--
object_idstringID of the object this comment is associated withRequired
object_typestringType of the object this comment is associated withRequired
own_reactionsFeedsReactionResponse[]Current user's reactions to this activityRequired
parent_idstringID of parent comment for nested replies-
reaction_countintegerNumber of reactions to this commentRequired
reaction_groupsobjectGrouped reactions by type-
reply_countintegerNumber of replies to this commentRequired
scoreintegerScore of the comment based on reactionsRequired
statusstringStatus of the comment (e.g., active, deleted)Required
textstringText content of the comment-
updated_atnumberWhen the comment was last updatedRequired
upvote_countintegerNumber of upvotes for this commentRequired
userUserResponseUser who created the commentRequired

Updating Comments

// Update a comment
await client.updateComment({
  id: "comment_123",
  comment: "Updated comment",
  custom: {
    edited: true,
  },
});

Removing Comments

client.deleteComment({
  id: "comment_123",
});

Reading Comments

You’ll also want to show/return these comments. The most important is when reading the feed.

await feed.getOrCreate();

const activity = feed.state.getLatestValue().activities?.[0]!;
// Supported values for sort: first, last, top, controversial, best
// Loads the activity comments (first or next page) and stores them in feed state
await feed.loadNextPageActivityComments(activity, { sort: 'best' });

// To read comments without storing them in feed state
const response = client.getComments({
  object_type: "activity",
  object_id: "123",
  limit: 10,
  sort: "best",
});

Sort options

The following sort options are supported when reading comments:

  • last: newest comment returned first
  • first: oldest comment returned first
  • top: highest score returned first - computed from upvote - downvote reaction types
  • controversial: controversial comment returned first - mixed reactions (upvote and downvote) and lots of comments
  • best: highest Wilson score returned first - Wilson score balances reaction score (upvote - downvote) with number of reactions (a comment with lower reaction score but more sum reactions is returned before a comment with higher score, but few sum reactions)

Search for Comments

You can also query the comments, the following examples show

  • how to search across all comments by text
  • query all comments of a given user
// Search in comment texts
await client.queryComments({
  filter: { comment_text: { $q: "oat" } },
});

// Comments of a user
await client.queryComments({
  filter: {
    user_id: jane.id,
  },
  limit: 20,
});

Comment Queryable Built-In Fields

nametypedescriptionsupported operationsexample
idstring or list of stringsThe ID of the comment$in, $eq{ id: { $in: [ 'comment_123', 'comment_456' ] } }
user_idstring or list of stringsThe ID of the user who created the comment$in, $eq{ user_id: { $eq: 'user_123' } }
object_typestring or list of stringsThe type of object being commented on$eq, $ne, $in, $nin{ object_type: { $in: [ 'activity', 'post' ] } }
object_idstring or list of stringsThe ID of the object being commented on$in, $eq{ object_id: { $eq: 'activity_123' } }
parent_idstring or list of stringsThe parent comment ID for replies$in, $eq{ parent_id: { $eq: 'comment_parent_123' } }
comment_textstringThe text content of the comment$q{ comment_text: { $q: 'search terms' } }
statusstring or list of stringsThe status of the comment$eq, $ne, $in{ status: { $in: [ 'approved', 'pending' ] } }
reply_countnumberThe number of replies to this comment$gt, $gte, $lt, $lte{ reply_count: { $gte: 5 } }
upvote_countnumberThe number of upvotes on the comment$gt, $gte, $lt, $lte{ upvote_count: { $gte: 10 } }
downvote_countnumberThe number of downvotes on the comment$gt, $gte, $lt, $lte{ downvote_count: { $lt: 5 } }
scorenumberThe overall score of the comment$gt, $gte, $lt, $lte{ score: { $gte: 0 } }
confidence_scorenumberThe confidence score of the comment$gt, $gte, $lt, $lte{ confidence_score: { $gte: 0.5 } }
controversy_scorenumberThe controversy score of the comment$gt, $gte, $lt, $lte{ controversy_score: { $lt: 0.8 } }
created_atstring, must be formatted as an RFC3339 timestampThe time the comment was created$eq, $gt, $gte, $lt, $lte{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }

Comment sort options

All fields support 1 and -1 directions.

Comment Reactions

When adding reactions and the enforce_unique flag is set to true, the existing reaction of a user will be overridden with the new reaction. Use this flag if you want to ensure users have a single reaction per each comment/activity. The default value is false, in which case users can have multiple reactions.

// Add a reaction to a comment
const response = await client.addCommentReaction({
  id: "comment_123",
  type: "like",
  // Optionally override existing reaction
  enforce_unique: true,
});

await client.deleteCommentReaction({
  id: "comment_123",
  type: "like",
});

Overview of the reaction model

FeedsReactionResponse
NameTypeDescriptionConstraints
activity_idstringID of the activity that was reacted toRequired
comment_idstringID of the comment that was reacted to-
created_atnumberWhen the reaction was createdRequired
customobjectCustom data for the reaction-
typestringType of reactionRequired
updated_atnumberWhen the reaction was last updatedRequired
userUserResponseUser who created the reactionRequired

Comment Threading

await feed.getOrCreate();

// To store comments in feed state you can use the loadNextPageActivityComments and loadNextPageCommentReplies
const activity = feed.state.getLatestValue().activities?.[0]!;
await feed.loadNextPageActivityComments(activity, { limit: 20 });

const commentState =
  feed.state.getLatestValue()?.comments_by_entity_id[activity.id];
const parentComment = commentState?.comments?.[0]!;
const firstPageOfReplies =
  feed.state.getLatestValue()?.comments_by_entity_id[parentComment?.id];

// Load next page of replies (or first, if replies aren't yet initialized)
feed.loadNextPageCommentReplies(parentComment);

// To read comments without storing them in state use getComments and getCommentReplies
const response = client.getComments({
    object_id: 'activity_123',
    object_type: 'activity',
    // Depth of the threaded comments
    depth: 3,
    limit: 20,
});

// Get replies of a specific parent comment
const response = client.getCommentReplies({
    id: '<parent id>',
});

Reading comment replies supports the same sort parameters as reading comments does.

Restricting comment replies

Set who can add comments

When creating an activity it’s possible to set who can add comments. Possible options:

  • Everyone (this is the default setting)
  • Only people I follow
  • Nobody

The activity author is always allowed to add comments regardless of the reply settings.

const response = await feed.addActivity({
  type: "post",
  text: "apple stock will go up",
  restrict_replies: "people_i_follow", // Options: "everyone", "people_i_follow", "nobody"
});

Show/hide comment input

If a user isn’t allowed to add comments, it’s a good idea to hide the comment input.

When everyone/nobody can comment this is straightforward. However if only people the activity author follows can comment, we have to check if there are any feeds owned by the current user that is followed by the activity author, the code snippet below shows how to check this:

const activity: ActivityResponse = /* fetch a single activity or read a feed */;

// Lists follow relationships where
// - target feed is owned by current user
// - source feed is owned by activity author
const feed = client.feed(
  activity.current_feed.group_id,
  activity.current_feed.id,
);
console.log(feed.currentState.own_followings);

own_followings is only set when reading a feed/activity from client-side, for server-side requests it will be empty.

  • When fetching a single activity, own_followings is set by default
  • When reading a feed, you have to explicitly enable fetching own_followings:
feed.getOrCreate({ enrichment_options: { enrich_own_followings: true } });