Files
UnrealEngine/Engine/Source/Runtime/Online/XMPP/Public/XmppMultiUserChat.h
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

362 lines
12 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "XmppConnection.h"
#include "XmppPresence.h"
#include "XmppChat.h"
/**
* Id of a chat room
*/
typedef FString FXmppRoomId;
/**
* Affiliation of a chat room member
* (long term associations with a room, persists across visits)
* http://xmpp.org/extensions/xep-0045.html#affil
*/
namespace EXmppChatMemberAffiliation
{
enum Type
{
/** Owner of the room */
Owner,
/* An admin or owner enters a room as a moderator */
Admin,
/* A member enters a room as a participant. */
/* As a default, an unaffiliated user enters a moderated room as a visitor, and enters an open room as a participant. */
Member,
/** Banned from the room */
Outcast,
/** Absence of an affiliation */
None
};
inline const TCHAR* ToString(Type Affiliation)
{
switch (Affiliation)
{
case Owner:
return TEXT("Owner");
case Admin:
return TEXT("Admin");
case Member:
return TEXT("Member");
case Outcast:
return TEXT("Outcast");
case None:
default:
return TEXT("None");
}
}
inline Type ToType(const FString& Affiliation)
{
if (Affiliation == TEXT("Owner"))
{
return Owner;
}
else if (Affiliation == TEXT("Admin"))
{
return Admin;
}
else if (Affiliation == TEXT("Member"))
{
return Member;
}
else if (Affiliation == TEXT("Outcast"))
{
return Outcast;
}
else
{
return None;
}
}
}
/**
* Role of a chat room member
* (temporary role while in the room)
* http://xmpp.org/extensions/xep-0045.html#roles
*/
namespace EXmppChatMemberRole
{
enum Type
{
/* A moderator is the most powerful role within the context of the room, and can to some extent manage other occupants' roles in the room. */
Moderator,
/* A participant has fewer privileges than a moderator, although they always have the right to speak. */
Participant,
/* A visitor is a more restricted role within the context of a moderated room */
Visitor,
None
};
inline const TCHAR* ToString(Type Role)
{
switch (Role)
{
case Moderator:
return TEXT("Moderator");
case Participant:
return TEXT("Participant");
case Visitor:
return TEXT("Visitor");
case None:
default:
return TEXT("None");
}
}
inline Type ToType(const FString& Role)
{
if (Role == TEXT("Moderator"))
{
return Moderator;
}
else if (Role == TEXT("Participant"))
{
return Participant;
}
else if (Role == TEXT("Visitor"))
{
return Visitor;
}
else
{
return None;
}
}
}
/**
* Member of a chat room
*/
class FXmppChatMember
{
public:
FXmppChatMember()
: Affiliation(EXmppChatMemberAffiliation::None)
, Role(EXmppChatMemberRole::None)
{}
explicit FXmppChatMember(const FXmppMucPresence& MemberPresence)
: Nickname(MemberPresence.GetNickName())
, RoomMemberJid(MemberPresence.UserJid)
, UserJid(MemberPresence.MemberJid)
, UserPresence(MemberPresence)
, Affiliation(EXmppChatMemberAffiliation::ToType(MemberPresence.Affiliation))
, Role(EXmppChatMemberRole::ToType(MemberPresence.Role))
{
}
/** Nickname of the user */
FString Nickname;
/**
* JID of the member for the chat room
* Use this to identify the user in the chat room (such as iterating the chat room's members)
* ex: RoomId@MucDomain/MemberMucResource
*/
FXmppUserJid RoomMemberJid;
/**
* JID of the member outside of the chat room, if the room is non-anonymous. May be blank.
* Use this to identify the user outside of the chat room (such as private messages)
* ex: AccountId@Domain/Resource
* @see https://xmpp.org/extensions/xep-0045.html#enter-nonanon
*/
FXmppUserJid UserJid;
/** Presence of the member */
FXmppUserPresence UserPresence;
/** Affiliation of the member in the chat room */
EXmppChatMemberAffiliation::Type Affiliation;
/** Role of the member in the chat room */
EXmppChatMemberRole::Type Role;
/** @return string representation of this object suitable for logging */
FString ToDebugString() const
{
return FString::Printf(TEXT("Nick=[%s] RoomMemberJid=[%s] UserJid=[%s] Affiliation=%d Role=%d"), *Nickname, *RoomMemberJid.ToDebugString(), *UserJid.ToDebugString(), static_cast<int32>(Affiliation), static_cast<int32>(Role));
}
};
typedef TSharedPtr<FXmppChatMember, ESPMode::ThreadSafe> FXmppChatMemberPtr;
typedef TSharedRef<FXmppChatMember, ESPMode::ThreadSafe> FXmppChatMemberRef;
/**
* Info for a joined/created chat room
*/
class FXmppRoomInfo
{
public:
FXmppRoomInfo()
: bIsPrivate(false)
{}
FXmppRoomId Id;
FString OwnerId;
FString Subject;
bool bIsPrivate;
FString ToDebugString() const
{
return FString::Printf(TEXT("%s Owner: %s Subj: %s Priv: %d"), *Id, *OwnerId, *Subject, bIsPrivate);
}
};
/**
* Info to configure a new room
*/
class FXmppRoomConfig
{
public:
FXmppRoomConfig()
: RoomName(TEXT(""))
, RoomDesc(TEXT(""))
, bIsPrivate(true)
, Password(TEXT(""))
, bIsPersistent(false)
, bAllowPublicSearch(false)
, bIsModerated(false)
, bIsMembersOnly(false)
, bAllowChangeSubject(false)
, MaxMsgHistory(0)
, RoomAnonymity(ERoomAnonymity::Semianonymous)
{}
enum class ERoomAnonymity
{
Semianonymous,
Nonanonymous,
Fullanonymous
};
static const FString ConvertRoomAnonymityToString(ERoomAnonymity InRoomAnonymity)
{
if (InRoomAnonymity == ERoomAnonymity::Nonanonymous)
{
return TEXT("nonanonymous");
}
else if (InRoomAnonymity == ERoomAnonymity::Semianonymous)
{
return TEXT("semianonymous");
}
else if (InRoomAnonymity == ERoomAnonymity::Fullanonymous)
{
return TEXT("fullanonymous");
}
else
{
return TEXT("INVALID ROOMANONYMITY ENUM");
}
}
// <field type = "text-single" label = "Natural-Language Room Name" var = "muc#roomconfig_roomname">
FString RoomName;
// <field type = "text-single" label = "Short Description of Room" var = "muc#roomconfig_roomdesc">
FString RoomDesc;
// <field type = "boolean" label = "Password Required to Enter?" var = "muc#roomconfig_passwordprotectedroom">
bool bIsPrivate;
// <field type = "text-single" label = "Password" var = "muc#roomconfig_roomsecret">
FString Password;
// <field type = "boolean" label = "Make Room Persistent?" var = "muc#roomconfig_persistentroom">
bool bIsPersistent;
private:
// These fields are not used yet. Move to public when hooking up
// <field type = "boolean" label = "Make Room Publicly Searchable?" var = "muc#roomconfig_publicroom">
bool bAllowPublicSearch;
// <field type = "boolean" label = "Make Room Moderated?" var = "muc#roomconfig_moderatedroom">
bool bIsModerated;
// <field type = "boolean" label = "Make Room Members Only?" var = "muc#roomconfig_membersonly">
bool bIsMembersOnly;
// <field type = "boolean" label = "Allow Occupants to Change Subject?" var = "muc#roomconfig_changesubject">
bool bAllowChangeSubject;
// <field type = "text-single" label = "Maximum Number of History Messages Returned by Room" var = "muc#maxhistoryfetch">
int32 MaxMsgHistory;
// <field type = "list-single" label = "Room anonymity level:" var = "muc#roomconfig_anonymity">
ERoomAnonymity RoomAnonymity;
// <field type = "list-single" label = "Presence delivery logic" var = "tigase#presence_delivery_logic">
// <field type = "boolean" label = "Enable filtering of presence (broadcasting presence only between selected groups" var = "tigase#presence_filtering">
// <field type = "list-multi" label = "Affiliations for which presence should be delivered" var = "tigase#presence_filtered_affiliations">
// Allow RoomConfigOp to use the defaults we don't expose yet for consumers to change
friend class FXmppChatRoomConfigOp;
friend class FXmppMultiUserChatStrophe;
};
/**
* Interface for creating/joining/chatting in a MUC
*/
class IXmppMultiUserChat
{
public:
virtual ~IXmppMultiUserChat() {}
virtual bool CreateRoom(const FXmppRoomId& RoomId, const FString& Nickname, const FXmppRoomConfig& RoomConfig = FXmppRoomConfig()) = 0;
virtual bool ConfigureRoom(const FXmppRoomId& RoomId, const FXmppRoomConfig& RoomConfig) = 0;
virtual bool JoinPublicRoom(const FXmppRoomId& RoomId, const FString& Nickname) = 0;
virtual bool JoinPrivateRoom(const FXmppRoomId& RoomId, const FString& Nickname, const FString& Password) = 0;
virtual bool RegisterMember(const FXmppRoomId& RoomId, const FString& Nickname) = 0;
virtual bool UnregisterMember(const FXmppRoomId& RoomId, const FString& Nickname) = 0;
virtual bool ExitRoom(const FXmppRoomId& RoomId) = 0;
virtual bool SendChat(const FXmppRoomId& RoomId, const FString& MsgBody, const FString& ChatInfo) = 0;
virtual void GetJoinedRooms(TArray<FXmppRoomId>& OutRooms) = 0;
virtual bool RefreshRoomInfo(const FXmppRoomId& RoomId) = 0;
virtual bool GetRoomInfo(const FXmppRoomId& RoomId, FXmppRoomInfo& OutRoomInfo) = 0;
virtual bool GetMembers(const FXmppRoomId& RoomId, TArray<FXmppChatMemberRef>& OutMembers) = 0;
virtual FXmppChatMemberPtr GetMember(const FXmppRoomId& RoomId, const FXmppUserJid& MemberJid) = 0;
virtual bool GetLastMessages(const FXmppRoomId& RoomId, int32 NumMessages, TArray< TSharedRef<FXmppChatMessage> >& OutMessages) = 0;
virtual void HandleMucPresence(const FXmppMucPresence& MemberPresence) = 0;
virtual void DumpMultiUserChatState() const = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomCreateComplete, const TSharedRef<IXmppConnection>& /*Connection*/, bool /*bSuccess*/, const FXmppRoomId& /*RoomId*/, const FString& /*Error*/);
/** @return room created delegate */
virtual FOnXmppRoomCreateComplete& OnRoomCreated() = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomConfigureComplete, const TSharedRef<IXmppConnection>& /*Connection*/, bool /*bSuccess*/, const FXmppRoomId& /*RoomId*/, const FString& /*Error*/);
/** @return room configured delegate */
virtual FOnXmppRoomConfigureComplete& OnRoomConfigured() = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomInfoRefreshComplete, const TSharedRef<IXmppConnection>& /*Connection*/, bool /*bSuccess*/, const FXmppRoomId& /*RoomId*/, const FString& /*Error*/);
/** @return room refresh delegate */
virtual FOnXmppRoomInfoRefreshComplete& OnRoomInfoRefreshed() = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomJoinPublicComplete, const TSharedRef<IXmppConnection>& /*Connection*/, bool /*bSuccess*/, const FXmppRoomId& /*RoomId*/, const FString& /*Error*/);
/** @return public room joined delegate */
virtual FOnXmppRoomJoinPublicComplete& OnJoinPublicRoom() = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomJoinPrivateComplete, const TSharedRef<IXmppConnection>& /*Connection*/, bool /*bSuccess*/, const FXmppRoomId& /*RoomId*/, const FString& /*Error*/);
/** @return private room joined delegate */
virtual FOnXmppRoomJoinPrivateComplete& OnJoinPrivateRoom() = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomExitComplete, const TSharedRef<IXmppConnection>& /*Connection*/, bool /*bSuccess*/, const FXmppRoomId& /*RoomId*/, const FString& /*Error*/);
/** @return exit room delegate */
virtual FOnXmppRoomExitComplete& OnExitRoom() = 0;
/**
* Delegate when a member joins a room
* @param Connection the XMPP connection
* @param RoomId the ID of the room that a member joined
* @param RoomMemberJid the JID the member that joined, used to lookup the member inside of the room
*/
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnXmppRoomMemberJoin, const TSharedRef<IXmppConnection>& /*Connection*/, const FXmppRoomId& /*RoomId*/, const FXmppUserJid& /*RoomMemberJid*/);
/** @return room member joined room delegate */
virtual FOnXmppRoomMemberJoin& OnRoomMemberJoin() = 0;
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnXmppRoomMemberExit, const TSharedRef<IXmppConnection>& /*Connection*/, const FXmppRoomId& /*RoomId*/, const FXmppUserJid& /*RoomMemberJid*/);
/** @return room member exited room delegate */
virtual FOnXmppRoomMemberExit& OnRoomMemberExit() = 0;
DECLARE_MULTICAST_DELEGATE_ThreeParams(FOnXmppRoomMemberChanged, const TSharedRef<IXmppConnection>& /*Connection*/, const FXmppRoomId& /*RoomId*/, const FXmppUserJid& /*RoomMemberJid*/);
/** @return room member changed delegate */
virtual FOnXmppRoomMemberChanged& OnRoomMemberChanged() = 0;
DECLARE_MULTICAST_DELEGATE_FourParams(FOnXmppRoomChatReceived, const TSharedRef<IXmppConnection>& /*Connection*/, const FXmppRoomId& /*RoomId*/, const FXmppUserJid& /*RoomMemberJid*/, const TSharedRef<FXmppChatMessage>& /*ChatMsg*/);
/** @return chat room message received delegate */
virtual FOnXmppRoomChatReceived& OnRoomChatReceived() = 0;
};