#pragma once #include #include #include #include "music/Song.h" #include "../channel/ClientChannelView.h" #include "DataClient.h" #define CLIENT_LOG_PREFIX_(this) "[" << this->getLoggingPeerIp() << ":" << this->getPeerPort() << "/" << this->getDisplayName() << "]" #define CLIENT_LOG_PREFIX CLIENT_LOG_PREFIX_(this) #define CLIENT_STR_LOG_PREFIX_(this) (std::string("[") + this->getLoggingPeerIp() + ":" + std::to_string(this->getPeerPort()) + "/" + this->getDisplayName() + " | " + std::to_string(this->getClientId()) + "]") #define CLIENT_STR_LOG_PREFIX CLIENT_STR_LOG_PREFIX_(this) #define CMD_REQ_SERVER \ if(!this->server) return {findError("server_invalid_id"), "invalid bound server"} /* TODO: Play lock the server here with read? So the client dosn't get kicked within that moment */ #define CMD_REF_SERVER(variable_name) \ std::shared_ptr variable_name = this->getServer(); \ if(!variable_name) return {findError("server_invalid_id"), "invalid bound server"} #define CMD_REQ_CHANNEL \ if(!this->currentChannel) return {findError("channel_invalid_id"), "invalid bound channel"} #define CMD_RESET_IDLE \ do { \ this->resetIdleTime(); \ } while(false) #define CMD_REQ_PARM(parm) \ if(!cmd[0].has(parm)) return {findError("parameter_not_found"), parm} //the message here is show to the manager! #define CMD_CHK_AND_INC_FLOOD_POINTS(num) \ this->increaseFloodPoints(num); \ if(this->shouldFloodBlock()) return {findError("ban_flooding"), "You reached the flood limit"}; #define CMD_CHK_PARM_COUNT(count) \ if(cmd.bulkCount() != count) return {findError("parameter_invalid_count"), ""}; #define PERM_CHECK_CHANNEL_CR(pr, required, channel, req, cache) \ do { \ if(!this->permissionGranted(permission::PERMTEST_ORDERED, pr, required, channel, req, cache)) {\ return ts::CommandResultPermissionError(pr); \ }\ } while(false) //If a permission is required it could not be -1 #define PERM_CHECK_CHANNELR(pr, required, channel, req) PERM_CHECK_CHANNEL_CR(pr, required, channel, req, nullptr) //If a permission is required it could not be -1 #define PERM_CHECK_CHANNEL(pr, required, channel) PERM_CHECK_CHANNELR(pr, required, channel, false) #define PERM_CHECKR(pr, required, req) PERM_CHECK_CHANNELR(pr, (required), nullptr, req) #define PERM_CHECK(pr, required) PERM_CHECKR(pr, required, false) /* optional parameter required. By default true */ #define CACHED_PERM_CHECK(permission_type, required, ...) \ do { \ if(!this->permission_granted(this->cached_permission_value(permission_type), required, #__VA_ARGS__)) \ return CommandResultPermissionError{permission_type}; \ } while(0) //p = permission | target_permission = channel permission | channel = target channel | requires a power #define PERM_CHECK_CHANNEL_NEEDED_CR(p, target_permission, channel, req, cache) \ this->permissionGranted(permission::PERMTEST_ORDERED, p, (channel)->permissions()->getPermissionValue(permission::PERMTEST_ORDERED, target_permission, nullptr), channel, req, cache) #define PERM_CHECK_CHANNEL_NEEDEDR(p, target_permission, channel, req) PERM_CHECK_CHANNEL_NEEDED_CR(p, target_permission, channel, req, nullptr) #define PERM_CHECK_CHANNEL_NEEDED(p, target_permission, channel) PERM_CHECK_CHANNEL_NEEDEDR(p, target_permission, channel, true) namespace ts { class GroupManager; namespace connection { class VoiceClientConnection; } namespace server { class TSServer; class MusicClient; class WebClient; class MusicClient; struct ConnectionInfoData { std::chrono::time_point timestamp; std::map properties; }; class ConnectedClient : public DataClient { friend class TSServer; friend class VoiceServer; friend class VoiceClient; friend class MusicClient; friend class WebClient; friend class WebControlServer; friend class music::MusicBotManager; friend class QueryServer; friend class DataClient; friend class SpeakingClient; friend class connection::VoiceClientConnection; friend class ts::GroupManager; friend class ServerManager; public: explicit ConnectedClient(sql::SqlManager*, const std::shared_ptr& server); ~ConnectedClient() override; ConnectionState connectionState(){ return this->state; } std::string getLoggingPeerIp() { return config::server::disable_ip_saving || (this->server && this->server->disable_ip_saving()) ? "X.X.X.X" : this->getPeerIp(); } std::string getPeerIp(){ return this->isAddressV4() ? net::to_string(this->getAddressV4()->sin_addr) : this->isAddressV6() ? net::to_string(this->getAddressV6()->sin6_addr) : "localhost"; } uint16_t getPeerPort(){ return ntohs(this->isAddressV4() ? this->getAddressV4()->sin_port : this->isAddressV6() ? this->getAddressV6()->sin6_port : (uint16_t) 0); } std::string getHardwareId(){ return properties()[property::CLIENT_HARDWARE_ID]; } //General connection stuff bool isAddressV4() { return this->remote_address.ss_family == AF_INET; } const sockaddr_in* getAddressV4(){ return (sockaddr_in*) &this->remote_address; } bool isAddressV6() { return this->remote_address.ss_family == AF_INET6; } const sockaddr_in6* getAddressV6(){ return (sockaddr_in6*) &this->remote_address; } virtual void sendCommand(const ts::Command& command, bool low = false) = 0; //General manager stuff //FIXME cache the client id for speedup virtual uint16_t getClientId() { return this->properties()[property::CLIENT_ID]; } virtual void setClientId(uint16_t clId) { properties()[property::CLIENT_ID] = clId; } inline std::shared_ptr getChannel(){ return this->currentChannel; } inline std::shared_ptr getServer(){ return this->server; } inline ServerId getServerId(){ return this->server ? this->server->getServerId() : (ServerId) 0; } //bool channelSubscribed(const std::shared_ptr&); /* if lock_channel == false then channel_lock must be write locked! */ std::deque> subscribeChannel(const std::deque>& target, bool lock_channel, bool /* enforce */); /* if lock_channel == false then channel_lock must be write locked! */ std::deque> unsubscribeChannel(const std::deque>& target, bool lock_channel); bool isClientVisible(const std::shared_ptr&, bool /* lock channel lock */); inline std::deque> getVisibleClients(bool lock_channel){ std::shared_lock lock(this->channel_lock, std::defer_lock); if(lock_channel) lock.lock(); return this->visibleClients; } /** Notifies general stuff **/ virtual bool notifyError(const CommandResult&, const std::string& retCode = ""); /** Notifies (after request) */ bool sendNeededPermissions(bool /* force an update */); /* invoke this because it dosn't spam the client */ virtual bool notifyClientNeededPermissions(); virtual bool notifyServerGroupList(); virtual bool notifyGroupPermList(const std::shared_ptr&, bool); virtual bool notifyClientPermList(ClientDbId, const std::shared_ptr&, bool); virtual bool notifyChannelGroupList(); virtual bool notifyConnectionInfo(std::shared_ptr,std::shared_ptr); virtual bool notifyChannelSubscribed(const std::deque> &); virtual bool notifyChannelUnsubscribed(const std::deque> &); /** Notifies (without request) */ //Group server virtual bool notifyServerUpdated(std::shared_ptr); //Group manager virtual bool notifyClientPoke(std::shared_ptr invoker, std::string msg); virtual bool notifyClientUpdated( const std::shared_ptr &, const std::deque> &, bool lock_channel_tree ); /* invalid client id causes error: invalid clientID */ virtual bool notifyPluginCmd(std::string name, std::string msg, std::shared_ptr); //Group manager chat virtual bool notifyClientChatComposing(const std::shared_ptr &); virtual bool notifyClientChatClosed(const std::shared_ptr &); virtual bool notifyTextMessage(ChatMessageMode mode, const std::shared_ptr &sender, uint64_t targetId, const std::string &textMessage); inline void sendChannelMessage(const std::shared_ptr& sender, const std::string& textMessage){ this->notifyTextMessage(ChatMessageMode::TEXTMODE_CHANNEL, sender, this->currentChannel ? this->currentChannel->channelId() : 0, textMessage); } //Group Client Groups virtual bool notifyServerGroupClientAdd(const std::shared_ptr &invoker, const std::shared_ptr &client, const std::shared_ptr &group); virtual bool notifyServerGroupClientRemove(std::shared_ptr invoker, std::shared_ptr client, std::shared_ptr group); /* invalid client id causes error: invalid clientID */ /* invalid channel id causes error: invalid channelID */ /* an invalid channel or not a client's channel causes: invalid channelID */ virtual bool notifyClientChannelGroupChanged( const std::shared_ptr& invoker, const std::shared_ptr& client, const std::shared_ptr& /*channel*/, const std::shared_ptr& /*inherited channel*/, const std::shared_ptr& group, bool lock_channel_tree /* server channel tree AND client tree must be at least read locked! */ ); //Group channel virtual bool notifyChannelMoved(const std::shared_ptr &channel, ChannelId order, const std::shared_ptr &invoker); virtual bool notifyChannelDescriptionChanged(std::shared_ptr channel); virtual bool notifyChannelPasswordChanged(std::shared_ptr); virtual bool notifyChannelEdited(std::shared_ptr, std::vector keys, ConnectedClient* invoker); /* clients channel tree must be at least read locked */ virtual bool notifyChannelHide(const std::deque &channels, bool lock_channel_tree); virtual bool notifyChannelShow(const std::shared_ptr &channel, ChannelId orderId); /* client channel tree must be unique locked and server channel tree shared locked */ virtual bool notifyChannelCreate(const std::shared_ptr &channel, ChannelId orderId, const std::shared_ptr &invoker); virtual bool notifyChannelDeleted(const std::deque& /* channel_ids */, const std::shared_ptr& /* invoker */); //Client view virtual bool notifyClientEnterView( const std::shared_ptr &client, const std::shared_ptr &invoker, const std::string& /* reason */, const std::shared_ptr &to, ViewReasonId reasonId, const std::shared_ptr &from, bool lock_channel_tree ); virtual bool notifyClientEnterView(const std::deque>& /* clients */, const ViewReasonSystemT& /* mode */); /* channel lock must be write locked */ virtual bool notifyClientMoved( const std::shared_ptr &client, const std::shared_ptr &target_channel, ViewReasonId reason, std::string msg, std::shared_ptr invoker, bool lock_channel_tree ); virtual bool notifyClientLeftView( const std::shared_ptr &client, const std::shared_ptr &target_channel, ViewReasonId reasonId, const std::string& reasonMessage, std::shared_ptr invoker, bool lock_channel_tree ); virtual bool notifyClientLeftView( const std::deque>& /* clients */, const std::string& /* reason */, bool /* lock channel view */, const ViewReasonServerLeftT& /* mode */ ); virtual bool notifyClientLeftViewKicked( const std::shared_ptr &client, const std::shared_ptr &target_channel, const std::string& message, std::shared_ptr invoker, bool lock_channel_tree ); virtual bool notifyClientLeftViewBanned( const std::shared_ptr &client, const std::string& message, std::shared_ptr invoker, size_t length, bool lock_channel_tree ); virtual bool notifyMusicPlayerSongChange(const std::shared_ptr& bot, const std::shared_ptr& newEntry); virtual bool notifyMusicQueueAdd(const std::shared_ptr& bot, const std::shared_ptr& entry, int index, const std::shared_ptr& invoker); virtual bool notifyMusicQueueRemove(const std::shared_ptr& bot, const std::deque>& entry, const std::shared_ptr& invoker); virtual bool notifyMusicQueueOrderChange(const std::shared_ptr& bot, const std::shared_ptr& entry, int order, const std::shared_ptr& invoker); virtual bool notifyMusicPlayerStatusUpdate(const std::shared_ptr&); virtual bool closeConnection(const std::chrono::system_clock::time_point &timeout = std::chrono::system_clock::time_point()) = 0; virtual bool disconnect(const std::string& reason) = 0; void resetIdleTime(); void increaseFloodPoints(uint16_t); bool shouldFloodBlock(); virtual bool ignoresFlood() { return !this->block_flood; } std::shared_ptr requestConnectionInfo(const std::shared_ptr& /* receiver */); virtual void updateChannelClientProperties(bool /* lock channel tree */, bool /* notify our self */); void updateTalkRights(permission::PermissionValue talk_power); virtual std::shared_ptr resolveActiveBan(const std::string& ip_address); inline std::shared_ptr getConnectionStatistics() { return this->connectionStatistics; } inline std::shared_ptr channel_view() { return this->channels; } inline std::shared_ptr ref() { return _this.lock(); } /* * permission stuff */ inline permission::PermissionValue cached_permission_value(permission::PermissionType type) const { std::lock_guard lock(this->cached_permissions_lock); auto index = this->cached_permissions.find(type); if(index != this->cached_permissions.end()) return index->second; /* We're only caching permissions which are granted to reduce memory */ //logError(this->getServerId(), "{} Looked up cached permission, which hasn't been cached!", CLIENT_STR_LOG_PREFIX); return permNotGranted; } bool update_cached_permissions(); permission::v2::PermissionFlaggedValue calculate_permission_value(const permission::PermissionType& /* permission type */, ChannelId /* target channel */); protected: std::weak_ptr _this; //General states std::mutex state_lock; ConnectionState state = ConnectionState::UNKNWON; sockaddr_storage remote_address; std::shared_ptr currentChannel = nullptr; bool allowedToTalk = false; threads::Mutex disconnectLock; std::shared_mutex finalDisconnectLock; std::vector cached_server_groups{}; /* variable locked with channel_lock */ GroupId cached_channel_group = 0; /* variable locked with channel_lock */ std::deque> visibleClients{}; /* variable locked with channel_lock */ std::deque> mutedClients{}; /* variable locked with channel_lock */ std::deque> openChats{}; /* variable locked with channel_lock */ std::chrono::system_clock::time_point lastNeededNotify; std::shared_ptr lastNeededPermissionNotifyChannel = nullptr; bool requireNeededPermissionResend = false; std::chrono::system_clock::time_point connectTimestamp; std::chrono::system_clock::time_point lastOnlineTimestamp; std::chrono::system_clock::time_point lastTransfareTimestamp; std::chrono::system_clock::time_point idleTimestamp; std::chrono::system_clock::time_point last_statistics_tick; struct { std::mutex lock; std::shared_ptr data; std::chrono::system_clock::time_point data_age; std::deque> receiver; std::chrono::system_clock::time_point last_requested; } connection_info; struct { std::chrono::system_clock::time_point servergrouplist; std::chrono::system_clock::time_point channelgrouplist; std::chrono::system_clock::time_point last_notify; std::chrono::milliseconds notify_timeout = std::chrono::seconds(60); } command_times; std::shared_ptr connectionStatistics = nullptr; bool block_flood = true; FloodPoints floodPoints = 0; std::shared_ptr channels; std::shared_mutex channel_lock; std::mutex cached_permissions_lock; std::map cached_permissions; /* contains all needed permissions which are set */ #pragma pack(push, 1) struct CachedPermission { bool flag_skip : 1; /* could be enabled by server / channel or client group. If this flag is set we need no lookup for channel permissions */ bool flag_value : 1; /* says if we have a value or not */ permission::PermissionValue value; }; static_assert(sizeof(CachedPermission) == 5); #pragma pack(pop) permission::PermissionValue channels_view_power = permNotGranted; permission::PermissionValue channels_ignore_view = permNotGranted; bool subscribeToAll = false; std::weak_ptr selectedBot; std::weak_ptr subscribed_bot; virtual void tick(const std::chrono::system_clock::time_point &time); //Locked by everything who has something todo with command handling threads::Mutex command_lock; /* Note: This mutex must be recursive! */ std::vector> postCommandHandler; virtual bool handleCommandFull(Command&, bool disconnectOnFail = false); virtual CommandResult handleCommand(Command&); CommandResult handleCommandServerGetVariables(Command&); CommandResult handleCommandServerEdit(Command&); CommandResult handleCommandGetConnectionInfo(Command&); CommandResult handleCommandSetConnectionInfo(Command&); CommandResult handleCommandServerRequestConnectionInfo(Command&); CommandResult handleCommandConnectionInfoAutoUpdate(Command&); CommandResult handleCommandPermissionList(Command&); CommandResult handleCommandPropertyList(Command&); CommandResult handleCommandServerGroupList(Command&); CommandResult handleCommandClientGetIds(Command&); CommandResult handleCommandClientUpdate(Command&); CommandResult handleCommandClientEdit(Command&); CommandResult handleCommandClientEdit(Command&, const std::shared_ptr& /* target */); CommandResult handleCommandClientMove(Command&); //TODO: Use cached permission values CommandResult handleCommandClientGetVariables(Command&); CommandResult handleCommandClientKick(Command&); CommandResult handleCommandClientPoke(Command&); CommandResult handleCommandChannelSubscribe(Command&); CommandResult handleCommandChannelSubscribeAll(Command&); CommandResult handleCommandChannelUnsubscribe(Command&); CommandResult handleCommandChannelUnsubscribeAll(Command&); CommandResult handleCommandChannelCreate(Command&); CommandResult handleCommandChannelDelete(Command&); CommandResult handleCommandChannelEdit(Command&); CommandResult handleCommandChannelGetDescription(Command&); CommandResult handleCommandChannelMove(Command&); CommandResult handleCommandChannelPermList(Command&); CommandResult handleCommandChannelAddPerm(Command&); CommandResult handleCommandChannelDelPerm(Command&); //Server group manager management CommandResult handleCommandServerGroupCopy(Command&); CommandResult handleCommandServerGroupAdd(Command&); CommandResult handleCommandServerGroupRename(Command&); CommandResult handleCommandServerGroupDel(Command&); CommandResult handleCommandServerGroupClientList(Command&); CommandResult handleCommandServerGroupDelClient(Command&); CommandResult handleCommandServerGroupAddClient(Command&); CommandResult handleCommandServerGroupPermList(Command&); CommandResult handleCommandServerGroupAddPerm(Command&); CommandResult handleCommandServerGroupDelPerm(Command&); CommandResult handleCommandServerGroupAutoAddPerm(Command&); CommandResult handleCommandServerGroupAutoDelPerm(Command&); CommandResult handleCommandClientAddPerm(Command&); //TODO: Use cached permission values CommandResult handleCommandClientDelPerm(Command&); //TODO: Use cached permission values CommandResult handleCommandClientPermList(Command&); //TODO: Use cached permission values CommandResult handleCommandChannelClientAddPerm(Command&); //TODO: Use cached permission values CommandResult handleCommandChannelClientDelPerm(Command&); //TODO: Use cached permission values CommandResult handleCommandChannelClientPermList(Command&); //TODO: Use cached permission values CommandResult handleCommandChannelGroupAdd(Command&); CommandResult handleCommandChannelGroupCopy(Command&); CommandResult handleCommandChannelGroupRename(Command&); CommandResult handleCommandChannelGroupDel(Command&); CommandResult handleCommandChannelGroupList(Command&); CommandResult handleCommandChannelGroupClientList(Command&); CommandResult handleCommandChannelGroupPermList(Command&); CommandResult handleCommandChannelGroupAddPerm(Command&); CommandResult handleCommandChannelGroupDelPerm(Command&); CommandResult handleCommandSetClientChannelGroup(Command&); CommandResult handleCommandSendTextMessage(Command&); CommandResult handleCommandClientChatComposing(Command&); CommandResult handleCommandClientChatClosed(Command&); //File transfare commands CommandResult handleCommandFTGetFileList(Command&); //TODO: Use cached permission values CommandResult handleCommandFTCreateDir(Command&); //TODO: Use cached permission values CommandResult handleCommandFTDeleteFile(Command&); //TODO: Use cached permission values CommandResult handleCommandFTInitUpload(Command&); //TODO: Use cached permission values CommandResult handleCommandFTInitDownload(Command&); //TODO: Use cached permission values CommandResult handleCommandFTGetFileInfo(Command&); //TODO: Use cached permission values //CMD_TODO handleCommandFTGetFileInfo -> 5 points //CMD_TODO handleCommandFTStop -> 5 points //CMD_TODO handleCommandFTRenameFile -> 5 points //CMD_TODO handleCommandFTList -> 5 points CommandResult handleCommandBanList(Command&); CommandResult handleCommandBanAdd(Command&); CommandResult handleCommandBanEdit(Command&); CommandResult handleCommandBanClient(Command&); CommandResult handleCommandBanDel(Command&); CommandResult handleCommandBanDelAll(Command&); CommandResult handleCommandBanTriggerList(Command&); CommandResult handleCommandTokenList(Command&); CommandResult handleCommandTokenAdd(Command&); CommandResult handleCommandTokenUse(Command&); CommandResult handleCommandTokenDelete(Command&); CommandResult handleCommandClientDbList(Command&); CommandResult handleCommandClientDBEdit(Command&); CommandResult handleCommandClientDbInfo(Command&); CommandResult handleCommandClientDBDelete(Command&); CommandResult handleCommandClientDBFind(Command&); CommandResult handleCommandPluginCmd(Command&); CommandResult handleCommandClientMute(Command&); CommandResult handleCommandClientUnmute(Command&); CommandResult handleCommandComplainAdd(Command&); CommandResult handleCommandComplainList(Command&); CommandResult handleCommandComplainDel(Command&); CommandResult handleCommandComplainDelAll(Command&); CommandResult handleCommandClientGetDBIDfromUID(Command&); CommandResult handleCommandClientGetNameFromDBID(Command&); CommandResult handleCommandClientGetNameFromUid(Command&); CommandResult handleCommandClientGetUidFromClid(Command&); //Original from query but still reachable for all CommandResult handleCommandClientList(Command&); CommandResult handleCommandWhoAmI(Command&); CommandResult handleCommandServerGroupsByClientId(Command &); //Maybe not query? CommandResult handleCommandClientFind(Command&); CommandResult handleCommandClientInfo(Command&); CommandResult handleCommandVersion(Command&); CommandResult handleCommandVerifyChannelPassword(Command&); CommandResult handleCommandVerifyServerPassword(Command&); CommandResult handleCommandMessageList(Command&); CommandResult handleCommandMessageAdd(Command&); CommandResult handleCommandMessageGet(Command&); CommandResult handleCommandMessageUpdateFlag(Command&); CommandResult handleCommandMessageDel(Command&); CommandResult handleCommandPermGet(Command&); CommandResult handleCommandPermIdGetByName(Command&); CommandResult handleCommandPermFind(Command&); CommandResult handleCommandPermOverview(Command&); CommandResult handleCommandChannelFind(Command&); //TODO: Use cached permission values CommandResult handleCommandChannelInfo(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotCreate(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotDelete(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotSetSubscription(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotPlayerInfo(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotPlayerAction(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotQueueList(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotQueueAdd(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotQueueRemove(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotQueueReorder(Command&); //TODO: Use cached permission values CommandResult handleCommandMusicBotPlaylistAssign(Command&); /* playlist management */ CommandResult handleCommandPlaylistList(Command&); CommandResult handleCommandPlaylistCreate(Command&); CommandResult handleCommandPlaylistDelete(Command&); CommandResult handleCommandPlaylistPermList(Command&); CommandResult handleCommandPlaylistAddPerm(Command&); CommandResult handleCommandPlaylistDelPerm(Command&); /* playlist properties */ CommandResult handleCommandPlaylistInfo(Command&); CommandResult handleCommandPlaylistEdit(Command&); CommandResult handleCommandPlaylistSongList(Command&); CommandResult handleCommandPlaylistSongAdd(Command&); CommandResult handleCommandPlaylistSongReorder(Command&); CommandResult handleCommandPlaylistSongRemove(Command&); CommandResult handleCommandPermReset(Command&); //TODO: Use cached permission values CommandResult handleCommandHelp(Command&); //TODO: Use cached permission values CommandResult handleCommandUpdateMyTsId(Command&); CommandResult handleCommandUpdateMyTsData(Command&); /// /// With a whisper list set a client can talk to the specified clients and channels bypassing the standard rule that voice is only transmitted to the current channel. Whisper lists can be defined for individual clients. /// /// /// To control which client is allowed to whisper to own client, the Library implements an internal whisper whitelist mechanism. When a client receives a whisper while the whispering client has not yet been added to the whisper allow list, the receiving client gets the -Event. Note that whisper voice data is not received until the sending client is added to the receivers whisper allow list. /// /// array of channels to whisper to, set to null to disable /// array of clients to whisper to, set to null to disable //CMD_TODO handleCommandSetWhisperlist //CMD_TODO handleCommandServerTempPasswordList //CMD_TODO handleCommandServerTempPasswordDel //CMD_TODO handleCommandServerTempPasswordAdd -> servertemppasswordadd pw=PWD desc=DES duration=1200 (20 min) tcid=4 tcpw=asdasd (channel password) //Legacy, for TeamSpeak 3 CommandResult handleCommandClientSetServerQueryLogin(Command&); CommandResult handleCommandQueryList(Command&); CommandResult handleCommandQueryRename(Command&); CommandResult handleCommandQueryCreate(Command&); CommandResult handleCommandQueryDelete(Command&); CommandResult handleCommandQueryChangePassword(Command&); CommandResult handleCommandLogView(Command&); //CMD_TODO handleCommandLogAdd //handleCommandClientSiteReport() -> return findError(0x00) //handleCommandChannelCreatePrivate() -> return findError(0x02) //handleCommandCustome_Unknown_Command() -> return findError(0x100) CommandResult handleCommandDummy_IpChange(Command&); //handleCommandDummy_NewIp //handleCommandDummy_ConnectFailed //handleCommandDummy_ConnectionLost //Not needed - completly useless //CMD_TODO handleCommandCustomInfo //CMD_TODO handleCommandCustomSearch //CMD_TODO serverquerycmd void sendChannelList(bool lock_channel_tree); void sendServerInit(); void sendTSPermEditorWarning(); void sendChannelDescription(const std::shared_ptr&, bool lock_tree); bool handleTextMessage(ChatMessageMode, std::string, const std::shared_ptr& /* sender target */); typedef std::function& /* sender */, const std::string& /* message */)> handle_text_command_fn_t; bool handle_text_command( ChatMessageMode, const std::string& /* key */, const std::deque& /* arguments */, const handle_text_command_fn_t& /* send function */, const std::shared_ptr& /* sender target */ ); inline std::string notify_response_command(const std::string_view& notify) { if(this->getExternalType() == ClientType::CLIENT_TEAMSPEAK) return std::string(notify); return ""; } }; } }