From c720a80bc098ea75a6be1c128d46dc9169c598ed Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sun, 21 Jul 2019 17:02:32 +0200 Subject: [PATCH] Updating the conversation stuff --- server/src/TSServer.cpp | 2 +- .../client/ConnectedClientCommandHandler.cpp | 29 ++++++++++++++++++- .../src/client/query/QueryClientCommands.cpp | 4 +-- server/src/manager/ConversationManager.cpp | 22 ++++++++++++-- server/src/manager/ConversationManager.h | 9 +++--- 5 files changed, 55 insertions(+), 11 deletions(-) diff --git a/server/src/TSServer.cpp b/server/src/TSServer.cpp index 21ffcd2..ece14c3 100644 --- a/server/src/TSServer.cpp +++ b/server/src/TSServer.cpp @@ -227,7 +227,7 @@ bool TSServer::initialize(bool test_properties) { this->properties()[property::VIRTUALSERVER_FILEBASE] = serverInstance->getFileServer()->server_file_base(self.lock()); /* lets cleanup the conversations for not existent channels */ - this->_conversation_manager->cleanup_channels(); + this->_conversation_manager->synchronize_channels(); return true; } diff --git a/server/src/client/ConnectedClientCommandHandler.cpp b/server/src/client/ConnectedClientCommandHandler.cpp index 53177a0..eb85b04 100644 --- a/server/src/client/ConnectedClientCommandHandler.cpp +++ b/server/src/client/ConnectedClientCommandHandler.cpp @@ -1395,6 +1395,15 @@ CommandResult ConnectedClient::handleCommandChannelCreate(Command &cmd) { auto& tree_lock = this->server ? this->server->channel_tree_lock : serverInstance->getChannelTreeLock(); unique_lock tree_channel_lock(tree_lock); + if(cmd[0].has("channel_conversation_history_length")) { + auto value = cmd["channel_conversation_history_length"].as(); + if(value == 0) { + CACHED_PERM_CHECK(permission::b_channel_create_modify_conversation_history_unlimited, 1); + } else { + CACHED_PERM_CHECK(permission::i_channel_create_modify_conversation_history_length, 1); + } + } + { auto delete_delay = cmd[0].has("channel_delete_delay") ? cmd["channel_delete_delay"].as() : 0UL; if(delete_delay == 0) { @@ -1785,6 +1794,13 @@ CommandResult ConnectedClient::handleCommandChannelEdit(Command &cmd) { } else if (key == "channel_password" || key == "channel_flag_password") { CHANNEL_PERM_TEST(permission::b_channel_modify_password, 1, true); update_password = true; + } else if (key == "channel_conversation_history_length") { + auto value = cmd["channel_conversation_history_length"].as(); + if(value == 0) { + CHANNEL_PERM_TEST(permission::b_channel_create_modify_conversation_history_unlimited, 1, true); + } else { + CHANNEL_PERM_TEST(permission::i_channel_create_modify_conversation_history_length, 1, true); + } } else { logCritical( this->getServerId(), @@ -2066,6 +2082,14 @@ CommandResult ConnectedClient::handleCommandChannelEdit(Command &cmd) { } } } + } else if(*key == property::CHANNEL_CONVERSATION_HISTORY_LENGTH) { + //channel_conversation_history_length + auto conversation_manager = this->server->conversation_manager(); + if(conversation_manager) { + auto conversation = conversation_manager->get(channel->channelId()); + if(conversation) + conversation->set_history_length(cmd[key->name]); + } } channel->properties()[key] = cmd[key->name].string(); @@ -7314,8 +7338,10 @@ CommandResult ConnectedClient::handleCommandConversationHistory(ts::Command &com size_t length = 0; bool merge = command.hasParm("merge"); for(auto& message : messages) { - if(index == 0) + if(index == 0) { notify[index]["cid"] = conversation_id; + notify[index]["flag_volatile"] = conversation->volatile_only(); + } notify[index]["timestamp"] = duration_cast(message->message_timestamp.time_since_epoch()).count(); notify[index]["sender_database_id"] = message->sender_database_id; @@ -7415,6 +7441,7 @@ CommandResult ConnectedClient::handleCommandConversationFetch(ts::Command &cmd) result_bulk["timestamp"] = duration_cast(conversation->last_message().time_since_epoch()).count(); else result_bulk["timestamp"] = 0; + result_bulk["flag_volatile"] = conversation->volatile_only(); } if(result_index == 0) return {ErrorType::DBEmpty}; diff --git a/server/src/client/query/QueryClientCommands.cpp b/server/src/client/query/QueryClientCommands.cpp index 14019e4..9db866f 100644 --- a/server/src/client/query/QueryClientCommands.cpp +++ b/server/src/client/query/QueryClientCommands.cpp @@ -16,10 +16,8 @@ using namespace std::chrono; using namespace ts; using namespace ts::server; -extern ts::server::InstanceHandler* serverInstance; - constexpr unsigned int string_hash(const char* str, int h = 0) { - return !str[h] ? 5381 : (string_hash(str, h + 1) * 33) ^ str[h]; + return !str[h] ? 5381 : (string_hash(str, h + 1U) * 33U) ^ str[h]; } CommandResult QueryClient::handleCommand(Command& cmd) { diff --git a/server/src/manager/ConversationManager.cpp b/server/src/manager/ConversationManager.cpp index 275bee0..9bfcc97 100644 --- a/server/src/manager/ConversationManager.cpp +++ b/server/src/manager/ConversationManager.cpp @@ -1253,8 +1253,26 @@ void ConversationManager::delete_conversation(ts::ChannelId channel_id) { } } -void ConversationManager::cleanup_channels() { - //TODO: Check if the channel for the conversation still exists! +void ConversationManager::synchronize_channels() { + auto ref_server = this->ref_server(); + if(!ref_server) { + logWarning(ref_server->getServerId(), "[Conversations][{}] Failed to synchronize conversations (server expired)"); + return; + } + + auto chan_tree = ref_server->getChannelTree(); + deque> channels{this->_conversations}; + for(auto& channel : channels) { + auto schannel = chan_tree->findChannel(channel->channel_id()); + if(!schannel) { + logMessage(ref_server->getServerId(), "[Conversations][{}] Deleting conversation because channel does not exists anymore.", channel->channel_id()); + this->delete_conversation(channel->channel_id()); + continue; + } + + auto history_size = schannel->properties()[property::CHANNEL_CONVERSATION_HISTORY_LENGTH].as(); + channel->set_history_length(history_size); + } } void ConversationManager::cleanup_cache() { diff --git a/server/src/manager/ConversationManager.h b/server/src/manager/ConversationManager.h index 7f0e385..4df9d31 100644 --- a/server/src/manager/ConversationManager.h +++ b/server/src/manager/ConversationManager.h @@ -143,11 +143,11 @@ namespace ts { inline ChannelId channel_id() { return this->_channel_id; } /* if for some reason we're not able to open the file then we're in volatile mode */ - inline bool volatile_only() { return this->_volatile; } + inline bool volatile_only() { return this->_volatile || this->_history_length < 0; } void cleanup_cache(); - //void set_history_length(ssize_t /* save length */); - //ssize_t history_length(); + void set_history_length(ssize_t length) { this->_history_length = length; } + ssize_t history_length() { return this->_history_length; } inline std::chrono::system_clock::time_point last_message() { return this->_last_message_timestamp; } void register_message(ClientDbId sender_database_id, const std::string& sender_unique_id, const std::string& sender_name, const std::string& message); @@ -210,6 +210,7 @@ namespace ts { FILE* file_handle = nullptr; ChannelId _channel_id; + ssize_t _history_length = 0; bool _volatile = false; std::chrono::system_clock::time_point _last_message_timestamp; @@ -221,7 +222,7 @@ namespace ts { virtual ~ConversationManager(); void initialize(const std::shared_ptr& _this); - void cleanup_channels(); + void synchronize_channels(); void cleanup_cache(); bool conversation_exists(ChannelId /* channel */);