Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ Before you begin, make sure you have:

### Implementing a Unified Friends List

The Discord friend list is ultimately constructed from two entities: Relationships, and Users. You can query Relationships API to find everyone a user is a friend with, and the Users API to find the necessary extra information for rendering the list, such as whether they are online or not.
The Discord friend list is ultimately constructed from two entities: Relationships, and Users. You can query
Relationships API to find everyone a user is a friend with, and the Users API to find the necessary extra information
for rendering the list, such as whether they are online or not.
Comment on lines +28 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this doesn't produce a visible change. Do we want to newline like this in the .mdx file? If yes I'll update mine to do the same! Makes it easier to read in the file but maybe slightly more annoying to edit unless it knows how to format the code after editing

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally prefer it, since it's easier to read in an editor, and it's less likely to merge conflict if the edits are spread over multiple lines - it's also likely my IDE formatter changed it.

But I also am not enforcing it as something that everyone need do 😄


### Relationships

[Relationships](/docs/discord-social-sdk/development-guides/managing-relationships) are how Discord models friends, friend requests, and more. All relationships for the current user are loaded when the Client connects. Each relationship has a target user id, and a type, such as `Friend`, `PendingOutgoing`, or `Blocked`. The set of all relationships can be queried with [`Client::GetRelationships`].
[Relationships](/docs/discord-social-sdk/development-guides/managing-relationships) are how Discord models friends,
friend requests, and more. All relationships for the current user are loaded when the Client connects. Each
relationship has a target user id, and a type, such as `Friend`, `PendingOutgoing`, or `Blocked`.

To allow users to manage their relationships in your game, you should provide a way to accept or reject friend requests, block users, and manage pending requests. See [Development Guide: Managing Relationships in Your Game](/docs/discord-social-sdk/development-guides/managing-relationships) for implementation details.
To allow users to manage their relationships in your game, you should provide a way to accept or reject friend
requests, block users, and manage pending requests. See [Development Guide: Managing Relationships in Your Game](/docs/discord-social-sdk/development-guides/managing-relationships) for implementation details.

### Users

Expand All @@ -50,13 +55,144 @@ The SDK will only display activities associated with the current game, meaning y

See our [Design Guidelines: Status & Rich Presence](/docs/discord-social-sdk/design-guidelines/status-rich-presence) for best practices on displaying presence information.

Let's combine to create a unified friends list.
There are two ways in which you can create a unified friends list in your game:

1. Using the SDK Unified Friends List helper functions, which automatically group and sort
relationships and users for you.
2. Directly retrieving relationships and users from the SDK, and sorting manually.

## Approach 1: Using SDK Unified Friends List Helper Functions

:::info
This approach is recommended as it significantly reduces the amount of code you need to write and maintain compared to
manually fetching and organizing relationships, while ensuring your friends list follows Discord's best practices.
:::

The Discord Social SDK provides built-in helper functions that automatically group and sort your friends list according
to Discord's [recommended design guidelines](/docs/discord-social-sdk/design-guidelines/unified-friends-list).
This approach is generally simpler and more maintainable than manually fetching and organizing relationships.

The SDK automatically organizes friends into the three groups we find via [`RelationshipGroupType`]:
- `OnlinePlayingGame`: Friends who are online and currently playing your game
- `OnlineElsewhere`: Friends who are online but not playing your game
- `Offline`: Friends who are offline

### Step 1: Display the Unified Friends List

The [`Client::GetRelationshipsByGroup`] method returns a pre-sorted list of relationships for a specific group type.
This eliminates the need to manually filter, categorize, and sort friends yourself. The SDK handles all the logic
for determining which group each friend belongs to based on their online status and game activity, and
automatically sorts users within each group (for example, users who have played your game are moved to the top of
the OnlineElsewhere group).

Let's create a function that uses the SDK helper functions to display a properly organized friends list:

```cpp
void DisplayUnifiedFriendsList(const std::shared_ptr<discordpp::Client> &client) {
// Get friends playing the game
const auto onlineInGame = client->GetRelationshipsByGroup(
discordpp::RelationshipGroupType::OnlinePlayingGame
);

// Get friends online elsewhere
const auto onlineElsewhere = client->GetRelationshipsByGroup(
discordpp::RelationshipGroupType::OnlineElsewhere
);

// Get offline friends
const auto offline = client->GetRelationshipsByGroup(
discordpp::RelationshipGroupType::Offline
);

// Display "Online - GameTitle" Friends
std::cout << "\n=== Online - GameTitle (" << onlineInGame.size() << ") ===\n";
for (const auto& relationship : onlineInGame) {
auto user = relationship.User();
if (user) {
std::string displayStr = "🟣 " + user->DisplayName();

// Add Discord friend indicator
if (relationship.DiscordRelationshipType() == discordpp::RelationshipType::Friend) {
displayStr += " 👾";
}

// Add game friend indicator
if (relationship.GameRelationshipType() == discordpp::RelationshipType::Friend) {
displayStr += " 🎮";
}

std::cout << displayStr << "\n";
}
}

// Display "Online - Elsewhere" Friends
std::cout << "\n=== Online - Elsewhere (" << onlineElsewhere.size() << ") ===\n";
for (const auto& relationship : onlineElsewhere) {
auto user = relationship.User();
if (user) {
std::string displayStr = "🟢 " + user->DisplayName();

// Add Discord friend indicator
if (relationship.DiscordRelationshipType() == discordpp::RelationshipType::Friend) {
displayStr += " 👾";
}

// Add game friend indicator
if (relationship.GameRelationshipType() == discordpp::RelationshipType::Friend) {
displayStr += " 🎮";
}

std::cout << displayStr << "\n";
}
}

// Display "Offline" Friends
std::cout << "\n=== Offline (" << offline.size() << ") ===\n";
for (const auto& relationship : offline) {
auto user = relationship.User();
if (user) {
std::string displayStr = "⚫ " + user->DisplayName();

// Add Discord friend indicator
if (relationship.DiscordRelationshipType() == discordpp::RelationshipType::Friend) {
displayStr += " 👾";
}

// Add game friend indicator
if (relationship.GameRelationshipType() == discordpp::RelationshipType::Friend) {
displayStr += " 🎮";
}

std::cout << displayStr << "\n";
}
}
}
```

### Step 2: Set Up Automatic Updates

To keep your friends list up-to-date automatically, use the [`Client::SetRelationshipGroupsUpdatedCallback`]. This
callback is triggered whenever any change occurs that might affect the friends list grouping, such as a friend going
online or offline, or when a relationship changes, such as when you accept a friend request, or block a user.

```cpp
// Set up the unified friends list update callback
client->SetRelationshipGroupsUpdatedCallback([&client](const uint64_t userId) {
std::cout << "👥 Friends list updated for user: " << userId << std::endl;
DisplayUnifiedFriendsList(client);
});
```

---

## Step 1: Fetch Relationships
## Approach 2: Manually Fetching Relationships and Users

In this section we'll show a more manual method which gives you more control over how the friends list is displayed in your game.

### Step 1: Fetch Relationships

First, let's create a function to see what kind of relationships and information we have to work with:
First, let's create a function that utilises [`Client::GetRelationships`] to query all the relationships and
user information we for our account:

```cpp
void DisplayFriendsList(discordpp::Client& client) {
Expand Down Expand Up @@ -122,7 +258,7 @@ This will output the raw relationship data to the console. You can use this info

---

## Step 2: Organize Relationships
### Step 2: Organize Relationships

Based on our design guidelines for a [Unified Friends List](/docs/discord-social-sdk/design-guidelines/unified-friends-list), you should separate the player's friends list into three sections: `Online - GameTitle`, `Online - Elsewhere`, and `Offline`.

Expand Down Expand Up @@ -219,7 +355,7 @@ void DisplayFriendsList(std::shared_ptr<discordpp::Client> client) {

If we build and run our application, we should now see a list of friends separated into three categories: `Online - GameTitle`, `Online - Elsewhere`, and `Offline`.

## Step 3: Monitor Changes to Users
### Step 3: Monitor Changes to Users

To monitor for user changes, we're going using the [`Client::SetUserUpdatedCallback`] function.

Expand All @@ -242,7 +378,7 @@ user list, or similar operations.
:::
---

## Step 4: Monitor Changes in Relationships
### Step 4: Monitor Changes in Relationships

Let us setup two callbacks to handle relationship updates.

Expand All @@ -251,7 +387,7 @@ These examples rebuild the friends list from scratch every time a relationship c
recommend maintaining a collection of [`UserHandle`] objects and adding and removing them appropriately.
:::

### Relationship Created Callback
#### Relationship Created Callback

This can happen when a user sends or accepts a friend invite, or blocks a user.

Expand All @@ -266,7 +402,7 @@ client->SetRelationshipCreatedCallback([&client](uint64_t userId, bool isDiscord
});
```

### Relationship Deleted Callback
#### Relationship Deleted Callback

This can happen when a user rejects a friend request or removes a friend.

Expand Down Expand Up @@ -303,11 +439,15 @@ Now that you have a unified friends list, you can build on your social features

## Change Log

| Date | Changes |
|----------------|-----------------|
| March 17, 2025 | Initial release |
| Date | Changes |
|----------------|------------------------|
| March 17, 2025 | Initial release |
| July 17, 2025 | Add UFL helper methods |

{/* Autogenerated Reference Links */}
[`Client::GetRelationships`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ad481849835cd570f0e03adafcf90125d
[`Client::GetRelationshipsByGroup`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a9f7898d3f3d1ec92b06c662df70746d5
[`Client::SetRelationshipGroupsUpdatedCallback`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#af12441ef091298f968075b7190851098
[`Client::SetUserUpdatedCallback`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a3559f375165acedc6d6677ef599b3a4a
[`RelationshipGroupType`]: https://discord.com/developers/docs/social-sdk/namespacediscordpp.html#a503ed2f7b0bfbd435321a0e8b1dfba35
[`UserHandle`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1UserHandle.html#a587bcc838e42dc5c56f840a350070707