Skip to main content
Documentation - Discord Docs

Search documentation

Type to search this documentation.

On this pageOverview

Creating a Unified Friends List

Build a unified friends list that combines Discord relationships with your application.

A unified friends list combines both Discord and game-specific relationships in one view. This guide will show you how to:

  • Fetch all relationship data
  • Filter and organize relationships
  • Display online status
  • Handle different relationship types

Before you begin, make sure you have:

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.

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 for implementation details.

Users are the Discord users that are part of the relationships. The SDK provides a way to fetch a user by their ID, and the user object contains information such as their username, display name, avatar, and more.

Presence is how Discord stores whether a user is currently online or not, as well as what activities they are currently doing (such as playing a game). The SDK gives you access to two types of status:

  • Online Status: Online, Offline, Idle, etc.
  • Rich Presence: Any activities associated with the current game (or application in Discord parlance).

See our Design Guidelines: Status & Rich Presence for best practices on displaying presence information.

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

Section titled “Approach 1: Using SDK Unified Friends List Helper Functions”

The Discord Social SDK provides built-in helper functions that automatically group and sort your friends list according to Discord's recommended design guidelines. 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

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:

C++
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";
        }
    }
}

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.

C++
// 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);
});

Approach 2: Manually Fetching Relationships and Users

Section titled “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.

First, let's create a function that utilises Client::GetRelationships to query all the relationships and user information we for our account:

C++
void DisplayFriendsList(discordpp::Client& client) {
    std::vector<std::string> relationships{};
    for (auto& relationship: client->GetRelationships()) {
        auto user = relationship.User();
        if (!user) {
            continue;
        }
    
        std::string str{};
        // Identifying information about the user:
        str += " DiscordName: " + user->DisplayName();
        str += " DiscordId: " + std::to_string(user->Id());
        // Provisional users don't have a Discord icon shown next to them:
        str += " IsProvisional: " + std::to_string(user->IsProvisional());
        // Whether the relationship is for a friend, a friend request, or because the user is blocked:
        // For a friends list you'll want to filter out blocked users
        // And likely display friend requests in a different section
        str += " DiscordRelationshipType: " + std::string(discordpp::EnumToString(relationship.DiscordRelationshipType()));
        str += " GameRelationshipType: " + std::string(discordpp::EnumToString(relationship.GameRelationshipType()));
        // Whether the user is online/offline/etc:
        str += " IsOnlineAnywhere: " + std::to_string(user->Status() != discordpp::StatusType::Offline);
        str += " IsOnlineInGame: " + std::to_string(user->GameActivity() != std::nullopt);
        relationships.push_back(str);
    }
    
    std::sort(relationships.begin(), relationships.end());
    for (auto str : relationships) {
        printf("%s\n", str.c_str());
    }
}

We will want to call this function when the client is ready, so let's add it to our ready callback:

C++
// Set up status callback to monitor client connection
client->SetStatusChangedCallback([client](discordpp::Client::Status status, discordpp::Client::Error error, int32_t errorDetail) {
    std::cout << "🔄 Status changed: " << discordpp::Client::StatusToString(status) << std::endl;

    if (status == discordpp::Client::Status::Ready) {
        std::cout << "✅ Client is ready! You can now call SDK functions.\n";
        std::cout << "👥 Friends Count: " << client->GetRelationships().size() << std::endl;
        
        SetRichPresence(client);
        DisplayFriendsList(client);

    } else if (error != discordpp::Client::Error::None) {
        std::cerr << "❌ Connection Error: " << discordpp::Client::ErrorToString(error) << " - Details: " << errorDetail << std::endl;
    }
});

This will output the raw relationship data to the console. You can use this information to filter, organize and build a friends list that fits your game's design aesthetic.


Based on our design guidelines for a Unified Friends List, you should separate the player's friends list into three sections: Online - GameTitle, Online - Elsewhere, and Offline.

Because we are building a text console application, we will use emojis to represent the status of each friend but you can use your own design elements to convey status and presence in your game.

Let's update our DisplayFriendsList function to reflect our three sections and categorize friends based on their status:

  • We will create three vectors to store the friends in each category.
  • We will filter out pending friends and blocked users.
  • We will add indicators for Discord friends, game friends, and provisional users.
  • We will categorize friends based on their game and presence status.
  • We will sort each category alphabetically.
  • We will display each category separately.
C++
void DisplayFriendsList(std::shared_ptr<discordpp::Client> client) {
    // Create vectors for each section
    std::vector<std::string> inGame;
    std::vector<std::string> online;
    std::vector<std::string> offline;
    
    for (auto& relationship : client->GetRelationships()) {
        auto user = relationship.User();
        if (!user) {
            continue;
        }

        // Filter out pending friends and blocked users
        // You can display friend requests and blocked users in a different view to allow players to manage them in your game
        if (relationship.DiscordRelationshipType() != discordpp::RelationshipType::Friend) {
            continue;
        }
 
        std::string str;
        str += user->DisplayName();

        // Add Discord friend indicator
        // In a real game, please use the official Discord logo available in our design guidelines
        if (relationship.DiscordRelationshipType() == discordpp::RelationshipType::Friend) {
            str += " 👾";
        }

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

        // Add provisional indicator
        if (user->IsProvisional()) {
            str += " (Provisional)";
        }

        // Categorize based on status
        if (user->GameActivity()) {
            // in game
            inGame.push_back("🟣 " + str);
        } else if (user->Status() != discordpp::StatusType::Offline) {
            // online
            online.push_back("🟢 " + str);
        } else {
            // offline
            offline.push_back("⚫ " + str);
        } 
    }
    
    // Sort each category
    std::sort(inGame.begin(), inGame.end());
    std::sort(online.begin(), online.end());
    std::sort(offline.begin(), offline.end());
    
    // Display "Online - GameTitle" Friends
    std::cout << "\n=== Online - GameTitle (" << inGame.size() << ") ===\n";
    for (const auto& str : inGame) {
        std::cout << str << "\n";
    }
    
    // Display "Online - Elsewhere" Friends
    std::cout << "\n=== Online - Elsewhere (" << online.size() << ") ===\n";
    for (const auto& str : online) {
        std::cout << str << "\n";
    }
    
    // Display "Offline" Friends
    std::cout << "\n=== Offline (" << offline.size() << ") ===\n";
    for (const auto& str : offline) {
        std::cout << str << "\n";
    }
}

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.

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

This callback will be triggered whenever a user's info is updated, such as name or presence changes (when they go online, offline, or start playing your game).

C++
client->SetUserUpdatedCallback([&client](uint64_t userId) {
    std::cout << "👤 User updated: " << userId << std::endl;
    DisplayFriendsList(*client);
});

Now your friends list will automatically update when the presence of a friend changes, such as when they go online, offline or start playing your game.


Let us setup two callbacks to handle relationship updates.

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

C++
client->SetRelationshipCreatedCallback([&client](uint64_t userId, bool isDiscordRelationshipUpdate) {
    std::optional<discordpp::UserHandle> user = client->GetUser(userId);
    // if the userid is valid (which it should be), we can display the user's display name
    if(user) {
        std::cout << "🤝 Relationship created: " << user->DisplayName() << std::endl;
        DisplayFriendsList(*client);
    }
});

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

C++
client->SetRelationshipDeletedCallback([&client](uint64_t userId, bool isDiscordRelationshipUpdate) {
    std::cout << "🔥 Relationship deleted: " << userId << std::endl;
    DisplayFriendsList(*client);
});

Now your friends list will automatically update when relationships change, such as when you add a new friend, accept a friend request, or block a user.


Now that you have a unified friends list, you can build on your social features by allowing players to manage relationships, send game invites, and more. Check out our other guides for more information:

Need help? Join the Discord Developers Server and share questions in the #social-sdk-dev-help channel for support from the community.

If you encounter a bug while working with the Social SDK, please report it here: https://dis.gd/social-sdk-bug-report


Date Changes
March 17, 2025 Initial release
July 17, 2025 Add UFL helper methods
Suggest an edit

Propose a replacement for this page. The site team reviews it before applying any changes.

Export
Documentation menu