Synchronize platform friends
Introduction
The AccelByte Gaming Services (AGS) Friend service allows players to synchronize first-party platform friends (e.g., Steam, Xbox, PlayStation, Epic, etc.) with the service. It will take the platformUserId
from the first-party platform, and then map the friends relation with the existing AGS users.
Manually synchronize friends in bulk
This process requires the game client to manually get the first-party platform friendsId
list, and then send it to the AGS IAM service to get the AGS userId
. After getting the AGS UserId
list, you can call the Friend service to add them into the friend list directly without any confirmation step. This process can be triggered every time your game starts or manually by interaction between a player and the game client.
To allow your players to synchronize their first-party platform friends lists with their AGS friends list, you must call user.BulkGetUserByOtherPlatformUserIds()
and lobby.BulkRequestFriend()
consecutively.
- Unreal Engine
- Unity
- Go Extend SDK
- Python Extend SDK
- Java Extend SDK
- C# Extend SDK
TArray < FString > ThirdPartyPlatformFriendId = {
"12345abcd",
"abcd12345"
};
EAccelBytePlatformType PlatformType = EAccelBytePlatformType::Steam;
FRegistry::User.BulkGetUserByOtherPlatformUserIds(PlatformType, ThirdPartyPlatformFriendId, THandler < FBulkPlatformUserIdResponse > ::CreateLambda([](const FBulkPlatformUserIdResponse & Result) {
TArray < FString > UserIds;
for (auto UserData: Result.UserIdPlatforms) {
UserIds.Add(UserData.UserId);
}
FAccelByteModelsBulkFriendsRequest BulkFriendsRequest;
BulkFriendsRequest.FriendIds = UserIds;
FRegistry::Lobby.BulkFriendRequest(BulkFriendsRequest, FVoidHandler::CreateLambda([]() {
// Do something if BulkFriendRequest succeeds
}), FErrorHandler::CreateLambda([](int32 ErrorCode,
const FString & ErrorMessage) {
// Do something if BulkFriendRequest fails
UE_LOG(LogTemp, Log, TEXT("Error BulkFriendRequest, Error Code: %d Error Message: %s"), ErrorCode, * ErrorMessage);
}));
}), FErrorHandler::CreateLambda([](int32 ErrorCode,
const FString ErrorMessage) {
// Do something if BulkGetUserByOtherPlatformUserIds fails
UE_LOG(LogTemp, Log, TEXT("Error BulkGetUserByOtherPlatformUserIds, Error Code: %d Error Message: %s"), ErrorCode, * ErrorMessage);
}));
string[] thirdPartyPlatformFriendId = {
"12345abcd",
"abcd12345"
};
PlatformType platformType = PlatformType.Steam;
AccelBytePlugin.GetUser().BulkGetUserByOtherPlatformUserIds(platformType, thirdPartyPlatformFriendId, result => {
if (result.IsError) {
// Do something if BulkGetUserByOtherPlatformUserIds fails
Debug.Log($"Error BulkGetUserByOtherPlatformUserIds, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
} else {
List < string > userIds = new List < string > ();
foreach(var userData in result.Value.userIdPlatforms) {
userIds.Add(userData.userId);
}
AccelBytePlugin.GetLobby().BulkRequestFriend(userIds.ToArray(), result => {
if (result.IsError) {
// Do something if BulkRequestFriend fails
Debug.Log($"Error BulkRequestFriend, Error Code: {result.Error.Code} Error Message: {result.Error.Message}");
} else {
// Do something if BulkRequestFriend succeeds
}
});
}
});
usersService := &iam.UsersService{
Client: factory.NewIamClient(&repository.ConfigRepositoryImpl{}),
TokenRepository: &repository.TokenRepositoryImpl{},
}
namespace := "mygame"
platformId := "Steam"
platformUserIds := []string {
"12345abcd",
"abcd12345",
}
input := &users.PublicListUserIDByPlatformUserIDsV3Params{
Body: &iamclientmodels.ModelPlatformUserIDRequest {
PlatformUserIds: platformUserIds,
},
Namespace: namespace,
PlatformID: platformId,
}
result, err := usersService.PublicListUserIDByPlatformUserIDsV3Short(input)
import accelbyte_py_sdk.api.iam as iam_service
import accelbyte_py_sdk.api.iam.models as iam_models
import accelbyte_py_sdk.api.lobby as lobby_service
import accelbyte_py_sdk.api.lobby.models as lobby_models
result, error = public_list_user_id_by_platform_user_i_ds_v3(
body=ModelPlatformUserIDRequest.create(
platform_user_ids=[
"12345abcd",
"abcd12345",
],
),
platform_id="steam",
)
if error:
exit(error)
friend_ids = [user.user_id for user in result.user_id_platforms]
lobby_service.add_friends_without_confirmation(
body=lobby_models.ModelBulkFriendsRequest().with_friend_ids(friend_ids),
user_id="********************************",
)
if error:
exit(error)
final Users sectionWrapper = new Users(sdk);
String userId = "<user-id>";
String platformId = "steam";
List<String> thirdPartyPlatformFriendId = Arrays.asList("abc123", "def123");
AccountcommonUserPlatforms response;
try {
response = sectionWrapper.adminListUserIDByPlatformUserIDsV3(AdminListUserIDByPlatformUserIDsV3.builder()
.namespace("<namespace>")
.platformId(platformId)
.body(ModelPlatformUserIDRequest.builder().platformUserIds(thirdPartyPlatformFriendId).build())
.build());
} catch (Exception e) {
// Do something when failed
return;
}
List<String> friendUserIds = new ArrayList<>();
if (response != null && response.getUserIdPlatforms() != null)
{
for (var user : response.getUserIdPlatforms()) {
friendUserIds.add(user.getUserId());
}
}
final Friends friendsWrapper = new Friends(sdk);
try {
friendsWrapper.addFriendsWithoutConfirmation(AddFriendsWithoutConfirmation.builder()
.namespace("<namespace>")
.userId(userId)
.body(ModelBulkFriendsRequest.builder().friendIds(friendUserIds).build())
.build());
} catch (Exception e) {
// Do something when failed
return;
}
string userId = "<user-id>";
string platformId = "steam";
string[] thirdPartyPlatformFriendId = new[] {
"abc123",
"def123"
};
List<string> friendUserIds = new();
var userData = sdk.Iam.Users.AdminListUserIDByPlatformUserIDsV3Op
.Execute(new ModelPlatformUserIDRequest()
{
PlatformUserIds = new List<string>(thirdPartyPlatformFriendId)
}, sdk.Namespace, platformId);
if ((userData != null) && (userData.UserIdPlatforms != null))
{
foreach (var user in userData.UserIdPlatforms)
{
friendUserIds.Add(user.UserId!);
}
}
sdk.Lobby.Friends.AddFriendsWithoutConfirmationOp
.Execute(new ModelBulkFriendsRequest()
{
FriendIds = friendUserIds
}, sdk.Namespace, userId);
Endpoint reference
Get list of UserIds by PlatformUserIds | https://prod.gamingservices.accelbyte.io/iam/apidocs/#/Users/PublicListUserIDByPlatformUserIDsV3 |
---|---|
Add friends without confirmation | https://prod.gamingservices.accelbyte.io/lobby/apidocs/#/friends/addFriendsWithoutConfirmation |
Service-to-service synchronize friends
The AGS Friends service also provides a way for users to synchronize their first-party platform in a service-to-service (S2S) way. The game client only needs to call one endpoint and the AGS backend will get the friends data from the first-party platform, then map them to the AGS Friends relationship in the background. This process will also add the friends relation without the confirmation from the impacted users. However, this flow is currently limited to the AGS-supported platforms.
FAccelByteModelsSyncThirdPartyFriendInfo
field details:
Parameter Name | Type | Description |
---|---|---|
IsLogin | Bool | If set to true , the currently logged in user platform token will be used. |
PlatformId | FString | The ID of the platform you want to synchronize the friend list into. Valid values are:steam, ps5, ps4. |
PlatformToken | FString | The user platform token to use when synchronizing. This can be left empty if IsLogin set to true . |
PsnEnv | FString | The selected PlayStation (PSN) environment to synchronize friends with. Valid values are:sp-int, prod-qa, np |
- OSS
- Unreal Engine
- Unity
- Go Extend SDK
- Python Extend SDK
- Java Extend SDK
- C# Extend SDK
/*** Set delegate that will trigger after the sync is complete ***/
// ================================================================
bool bSyncDone {false};
bool bSyncSuccess {false};
TArray<FAccelByteModelsSyncThirdPartyFriendsResponse> SyncResponse;
const FOnSyncThirdPartyPlatformFriendsV2CompleteDelegate OnSyncComplete =
FOnSyncThirdPartyPlatformFriendsV2CompleteDelegate::CreateLambda([&](
int32 LocalUserNum, const FOnlineError& ErrorInfo, const TArray<FAccelByteModelsSyncThirdPartyFriendsResponse>& Response)
{
// If our operation succeeds
if(ErrorInfo.WasSuccessful())
{
// Check success state for sync to each platform
for(const FAccelByteModelsSyncThirdPartyFriendsResponse& Response : Responses)
{
if(Response.Status == "success")
{
UE_LOG(LogTemp, Display, TEXT("friend sync to platform %s success"), *Response.PlatformId);
}
else if(Result.Status == "failed")
{
UE_LOG(LogTemp, Display, TEXT("friend sync to platform %s failed"), *Response.PlatformId);
}
}
}
});
FriendsInterface->AddOnSyncThirdPartyPlatformFriendsV2CompleteDelegate_Handle(UserNum, OnSyncComplete);
/*** Execute friend sync ***/
// ================================================================
// Set request
FAccelByteModelsSyncThirdPartyFriendInfo RequestInfo1;
RequestInfo1.IsLogin = true;
RequestInfo1.PlatformId = FAccelByteUtilities::GetPlatformString(EAccelBytePlatformType::Steam);
FAccelByteModelsSyncThirdPartyFriendInfo RequestInfo2;
RequestInfo2.IsLogin = false;
RequestInfo2.PlatformId = FAccelByteUtilities::GetPlatformString(EAccelBytePlatformType::PS5);
RequestInfo2.PlatformToken = TEXT("platform-token")
RequestInfo2.PsnEnv = TEXT("sp-int")
FAccelByteModelsSyncThirdPartyFriendsRequest Request;
Request.FriendSyncDetails.Emplace(RequestInfo1);
Request.FriendSyncDetails.Emplace(RequestInfo2);
// Execute function
if(!FriendsInterface->SyncThirdPartyPlatformFriendV2(UserNum, Request))
{
UE_LOG(LogAccelByteOSSManualFriendSyncTest, Error, TEXT("friend sync third party platform friend failed, SyncThirdPartyPlatformFriendV2 returned false"));
return false;
}
FAccelByteModelsSyncThirdPartyFriendInfo RequestInfo1;
RequestInfo1.IsLogin = true;
RequestInfo1.PlatformId = FAccelByteUtilities::GetPlatformString(EAccelBytePlatformType::Steam);
FAccelByteModelsSyncThirdPartyFriendInfo RequestInfo2;
RequestInfo2.IsLogin = false;
RequestInfo2.PlatformId = FAccelByteUtilities::GetPlatformString(EAccelBytePlatformType::PS5);
RequestInfo2.PlatformToken = TEXT("platform-token")
RequestInfo2.PsnEnv = TEXT("sp-int")
FAccelByteModelsSyncThirdPartyFriendsRequest Request;
Request.FriendSyncDetails.Emplace(RequestInfo1);
Request.FriendSyncDetails.Emplace(RequestInfo2);
SteamUserApiClient->Lobby.SyncThirdPartyFriends(Request,
THandler<TArray<FAccelByteModelsSyncThirdPartyFriendsResponse>>::CreateLambda([&](const TArray<FAccelByteModelsSyncThirdPartyFriendsResponse>& Result)
{
// On operation success, check success sync to each platform
for(const FAccelByteModelsSyncThirdPartyFriendsResponse& Result : Results)
{
if(Result.Status == "success")
{
UE_LOG(LogTemp, Display, TEXT("friend sync to platform %s success"), *Result.PlatformId);
}
else if(Result.Status == "failed")
{
UE_LOG(LogTemp, Display, TEXT("friend sync to platform %s failed"), *Result.PlatformId);
}
}
}), FErrorHandler::CreateLambda([&](int Code, FString const& Message)
{
// Do something if operation fails
}));
// Make sure user already logged in using Steam token to AGS
var apiClient = MultiRegistry.GetApiClient();
var syncThirdPartyFriendInfo1 = new SyncThirdPartyFriendInfo
{
IsLogin = false,
PlatformId = PlatformType.Steam.ToString().ToLower()
};
var syncThirdPartyFriendInfo2 = new SyncThirdPartyFriendInfo
{
IsLogin = false,
PlatformId = PlatformType.PS5.ToString().ToLower(),
PlatformToken = "platform-token",
PsnEnv = "sp-int"
};
request = new SyncThirdPartyFriendsRequest
{
FriendSyncDetails = new[]
{
syncThirdPartyFriendInfo1,
syncThirdPartyFriendInfo2
}
};
s2sFriendSyncResponses = null;
apiClient.GetLobby().SyncThirdPartyFriends(request, result =>
{
if (result.IsError)
{
// Handle error
Debug.Log($"S2S Friend Sync error {result.Error.Code} {result.Error.Message}");
}
else
{
// Friend sync success
SyncThirdPartyFriendsResponse[] response = result.Value;
}
});
friendsService := &lobby.FriendsService{
Client: factory.NewLobbyClient(&repository.ConfigRepositoryImpl{}),
TokenRepository: &repository.TokenRepositoryImpl{},
}
namespace, _ := cmd.Flags().GetString("namespace")
input := &friends.SyncNativeFriendsParams{
Body: []*lobbyclientmodels.ModelNativeFriendRequest {
{
IsLogin: false,
PlatformID: "steam",
},
{
IsLogin: false,
PlatformID: "ps5",
PlatformToken: "platform-token",
PsnEnv: "sp-int",
}
},
Namespace: namespace,
}
result, err := friendsService.SyncNativeFriendsShort(input)
import accelbyte_py_sdk.api.lobby as lobby_service
import accelbyte_py_sdk.api.lobby.models as lobby_models
result, error = lobby_service.sync_native_friends(
body=[
lobby_models.ModelNativeFriendRequest()
.with_is_login(False)
.with_platform_id("steam"),
lobby_models.ModelNativeFriendRequest()
.with_is_login(False)
.with_platform_id("ps5")
.with_platform_token("platform-token")
.with_psn_env("sp-int"),
]
)
if error:
exit(error)
List<ModelNativeFriendSyncResponse> resp;
try {
List<ModelNativeFriendRequest> reqBody = Arrays.asList(
ModelNativeFriendRequest.builder()
.isLogin(false)
.platformId("steam")
.build(),
ModelNativeFriendRequest.builder()
.isLogin(false)
.platformId("ps5")
.platformToken("<user-platform-token>")
.psnEnv("sp-int")
.build()
);
resp = friendsWrapper.syncNativeFriends(SyncNativeFriends.builder()
.namespace("<namespace>")
.body(reqBody)
.build());
} catch (Exception e) {
// Do something when failed
return;
}
if (resp == null) {
// Null response from server
} else {
// Do something when sync is success
}
var response = sdk.Lobby.Friends.SyncNativeFriendsOp
.Execute(new List<ModelNativeFriendRequest>()
{
new ModelNativeFriendRequest()
{
IsLogin = false,
PlatformId = "steam"
},
new ModelNativeFriendRequest()
{
IsLogin = false,
PlatformId = "ps5",
PlatformToken = "<user-platform-token>",
PsnEnv = "sp-int"
}
}, sdk.Namespace);
if (response != null)
{
//do something when sync is success
}
Endpoint Reference
Sync Native Friends | https://prod.gamingservices.accelbyte.io/lobby/apidocs/#/friends/syncNativeFriends |
---|