Implemented new chat system

This commit is contained in:
WolverinDEV
2019-07-23 10:37:56 +02:00
parent c720a80bc0
commit af4106614c
21 changed files with 451 additions and 177 deletions
@@ -1186,7 +1186,8 @@ CommandResult ConnectedClient::handleCommandChannelGroupAddPerm(Command &cmd) {
if (cl->channelGroupAssigned(channelGroup, cl->getChannel())) {
if(cl->update_cached_permissions())
cl->sendNeededPermissions(false); /* update the needed permissions */
cl->updateChannelClientProperties(true, true);
cl->updateChannelClientProperties(false, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
}
@@ -1236,7 +1237,8 @@ CommandResult ConnectedClient::handleCommandChannelGroupDelPerm(Command &cmd) {
if (cl->channelGroupAssigned(channelGroup, cl->getChannel())) {
if(cl->update_cached_permissions()) /* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
cl->updateChannelClientProperties(true, false);
cl->updateChannelClientProperties(false, false);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
}
@@ -1311,17 +1313,18 @@ CommandResult ConnectedClient::handleCommandClientMove(Command &cmd) {
if(!this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_channel_ignore_join_power, 1, channel, true, permission_cache)) {
CHANNEL_PERMISSION_TEST(permission::i_channel_join_power, permission::i_channel_needed_join_power, channel, false);
if (target_client == this) {
auto permission_cache_current = make_shared<CalculateCache>();
auto val = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_is_sticky, this->currentChannel, permission_cache_current);
if (val != permNotGranted && val > 0) {
auto st = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_ignore_sticky, this->currentChannel, permission_cache_current);
if (st != 1)
return CommandResultPermissionError{permission::b_client_is_sticky};
}
}
}
if (target_client == this) {
auto permission_cache_current = make_shared<CalculateCache>();
auto val = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_is_sticky, this->currentChannel, permission_cache_current);
if (val != permNotGranted && val > 0) {
auto st = this->permissionValue(permission::PERMTEST_ORDERED, permission::b_client_ignore_sticky, this->currentChannel, permission_cache_current);
if (st != 1)
return CommandResultPermissionError{permission::b_client_is_sticky};
}
}
if (target_client != this) {
PERM_CHECK_CHANNELR(permission::i_client_move_power, target_client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_move_power, target_client->getChannel()), target_client->getChannel(), true);
PERM_CHECK_CHANNEL_CR(permission::i_client_move_power, target_client->permissionValue(permission::PERMTEST_ORDERED, permission::i_client_needed_move_power, channel), channel, true, permission_cache);
@@ -2394,29 +2397,31 @@ CommandResult ConnectedClient::handleCommandChannelAddPerm(Command &cmd) {
for(const auto& client : this->server->getClientsByChannel(channel)) {
/* let them lock the server channel tree as well (read lock so does not matter) */
client->updateChannelClientProperties(true, true);
client->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
if(update_view && this->server)
this->server->forEachClient([&](const shared_ptr<ConnectedClient>& cl) {
/* server tree read lock still active */
auto l_source = cl->server->channelTree->findLinkedChannel(channel->channelId());
auto l_target = !cl->currentChannel ? nullptr : cl->server->channelTree->findLinkedChannel(cl->currentChannel->channelId());
sassert(l_source);
if(cl->currentChannel) sassert(l_target);
if(update_view && this->server) {
auto l_source = this->server->channelTree->findLinkedChannel(channel->channelId());
this->server->forEachClient([&](const shared_ptr<ConnectedClient>& cl) {
/* server tree read lock still active */
auto l_target = !cl->currentChannel ? nullptr : cl->server->channelTree->findLinkedChannel(cl->currentChannel->channelId());
sassert(l_source);
if(cl->currentChannel) sassert(l_target);
{
unique_lock client_channel_lock(cl->channel_lock);
{
unique_lock client_channel_lock(cl->channel_lock);
deque<ChannelId> deleted;
for(const auto& update_entry : cl->channels->update_channel(l_source, l_target)) {
if(update_entry.first)
cl->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel);
else deleted.push_back(update_entry.second->channelId());
}
if(!deleted.empty())
cl->notifyChannelHide(deleted, false);
}
});
deque<ChannelId> deleted;
for(const auto& update_entry : cl->channels->update_channel(l_source, l_target)) {
if(update_entry.first)
cl->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel);
else deleted.push_back(update_entry.second->channelId());
}
if(!deleted.empty())
cl->notifyChannelHide(deleted, false);
}
});
}
return command_result;
}
@@ -2468,8 +2473,10 @@ CommandResult ConnectedClient::handleCommandChannelDelPerm(Command &cmd) {
if(updateClients && this->server)
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
if(cl->currentChannel == channel)
if(cl->currentChannel == channel) {
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
if(update_view && this->server) {
this->server->forEachClient([&](std::shared_ptr<ConnectedClient> cl) {
@@ -2866,6 +2873,7 @@ CommandResult ConnectedClient::handleCommandServerGroupAddPerm(Command &cmd) {
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
}).detach();
@@ -2935,6 +2943,7 @@ CommandResult ConnectedClient::handleCommandServerGroupDelPerm(Command &cmd) {
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
});
}).detach();
@@ -3021,10 +3030,13 @@ CommandResult ConnectedClient::handleCommandServerGroupAutoAddPerm(ts::Command&
server->forEachClient([groups, checkTp](shared_ptr<ConnectedClient> cl) {
for(const auto& serverGroup : groups) {
if (cl->serverGroupAssigned(serverGroup)) {
if(cl->update_cached_permissions()) /* update cached calculated permissions */
if(cl->update_cached_permissions()) {/* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
cl->updateChannelClientProperties(true, true);
}
if (checkTp) {
cl->updateChannelClientProperties(true, true);
}
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate if needed */
break;
}
}
@@ -3104,6 +3116,7 @@ CommandResult ConnectedClient::handleCommandServerGroupAutoDelPerm(ts::Command&
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (checkTp)
cl->updateChannelClientProperties(true, true);
cl->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
break;
}
}
@@ -3228,25 +3241,57 @@ CommandResult ConnectedClient::handleCommandSendTextMessage(Command &cmd) {
}
if(this->handleTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, cmd["msg"], target)) return CommandResult::Success;
target->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), target->getClientId(), cmd["msg"].string());
this->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), target->getClientId(), cmd["msg"].string());
target->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), target->getClientId(), 0, cmd["msg"].string());
this->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), target->getClientId(), 0, cmd["msg"].string());
} else if (cmd["targetmode"] == ChatMessageMode::TEXTMODE_CHANNEL) {
CMD_REQ_CHANNEL;
CACHED_PERM_CHECK(permission::b_client_channel_textmessage_send, 1, false);
if(!cmd[0].has("cid"))
cmd["cid"] = 0;
RESOLVE_CHANNEL_R(cmd["cid"], false);
auto channel = l_channel ? dynamic_pointer_cast<BasicChannel>(l_channel->entry) : nullptr;
if(!channel) {
CMD_REQ_CHANNEL;
channel = this->currentChannel;
channel_id = this->currentChannel->channelId();
if(this->handleTextMessage(ChatMessageMode::TEXTMODE_CHANNEL, cmd["msg"], nullptr)) return CommandResult::Success;
for (auto &cl : this->server->getClientsByChannel(this->currentChannel))
cl->notifyTextMessage(ChatMessageMode::TEXTMODE_CHANNEL, _this.lock(), this->getClientId(), cmd["msg"].string());
if(this->handleTextMessage(ChatMessageMode::TEXTMODE_CHANNEL, cmd["msg"], nullptr))
return CommandResult::Success;
}
auto message = cmd["msg"].string();
auto _this = this->_this.lock();
auto client_id = this->getClientId();
auto flag_password = channel->properties()[property::CHANNEL_FLAG_PASSWORD].as<bool>();
for(const auto& client : this->server->getClients()) {
if(client->connectionState() != ConnectionState::CONNECTED)
continue;
auto type = client->getType();
if(type == ClientType::CLIENT_INTERNAL || type == ClientType::CLIENT_MUSIC)
continue;
auto own_channel = client->currentChannel == this->currentChannel;
if(type != ClientType::CLIENT_TEAMSPEAK || own_channel) {
if(!own_channel && &*client != this) {
if(flag_password)
continue; /* TODO: Send notification about new message. The client then could request messages via message history */
if(!client->calculate_and_get_join_state(channel))
continue;
}
client->notifyTextMessage(ChatMessageMode::TEXTMODE_CHANNEL, _this, client_id, channel_id, message);
}
}
auto conversations = this->server->conversation_manager();
auto conversation = conversations->get_or_create(this->currentChannel->channelId());
auto conversation = conversations->get_or_create(channel->channelId());
conversation->register_message(this->getClientDatabaseId(), this->getUid(), this->getDisplayName(), cmd["msg"].string());
} else if (cmd["targetmode"] == ChatMessageMode::TEXTMODE_SERVER) {
CACHED_PERM_CHECK(permission::b_client_server_textmessage_send, 1);
if(this->handleTextMessage(ChatMessageMode::TEXTMODE_SERVER, cmd["msg"], nullptr)) return CommandResult::Success;
this->server->forEachClient([&](shared_ptr<ConnectedClient> client) {
client->notifyTextMessage(ChatMessageMode::TEXTMODE_SERVER, _this.lock(), this->getClientId(), cmd["msg"].string());
client->notifyTextMessage(ChatMessageMode::TEXTMODE_SERVER, _this.lock(), this->getClientId(), 0, cmd["msg"].string());
});
} else return {findError("parameter_invalid"), "invalid target mode"};
@@ -4568,7 +4613,7 @@ CommandResult ConnectedClient::handleCommandClientMute(Command &cmd) {
}
if (config::voice::notifyMuted)
client->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), client->getClientId(), config::messages::mute_notify_message);
client->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), client->getClientId(), 0, config::messages::mute_notify_message);
return CommandResult::Success;
}
@@ -4589,7 +4634,7 @@ CommandResult ConnectedClient::handleCommandClientUnmute(Command &cmd) {
}
if (config::voice::notifyMuted)
client->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), client->getClientId(), config::messages::unmute_notify_message);
client->notifyTextMessage(ChatMessageMode::TEXTMODE_PRIVATE, _this.lock(), client->getClientId(), 0, config::messages::unmute_notify_message);
return CommandResult::Success;
}
@@ -4879,6 +4924,7 @@ CommandResult ConnectedClient::handleCommandClientAddPerm(Command &cmd) {
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if(update_channels)
elm->updateChannelClientProperties(true, true);
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
return CommandResult::Success;
@@ -4917,6 +4963,7 @@ CommandResult ConnectedClient::handleCommandClientDelPerm(Command &cmd) {
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if(update_channel)
elm->updateChannelClientProperties(true, true);
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
return CommandResult::Success;
}
@@ -4938,9 +4985,9 @@ CommandResult ConnectedClient::handleCommandChannelClientPermList(Command &cmd)
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
PERM_CHECKR(permission::b_virtualserver_channelclient_permission_list, 1, true);
std::shared_ptr<BasicChannel> channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
if (!channel) return {findError("channel_invalid_id"), "Cant resolve channel"};
RESOLVE_CHANNEL_R(cmd["cid"], true);
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
if(!channel) return {ErrorType::VSError};
if(!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return {findError("client_invalid_id"), "invalid client id"};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"].as<ClientDbId>());
@@ -4987,21 +5034,21 @@ CommandResult ConnectedClient::handleCommandChannelClientPermList(Command &cmd)
return CommandResult::Success;
}
//TODO: Update this specific channel visibility?
CommandResult ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd) {
CMD_REQ_SERVER;
CMD_REF_SERVER(server_ref);
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
if (!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return {findError("parameter_invalid"), "Invalid manager db id"};
std::shared_ptr<BasicChannel> channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
if (!channel) return {findError("channel_invalid_id"), "Cant resolve channel"};
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"]);
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"]);
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
RESOLVE_CHANNEL_R(cmd["cid"], true);
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
if(!channel) return {ErrorType::VSError};
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, this->currentChannel);
bool conOnError = cmd[0].has("continueonerror");
bool conOnError = cmd[0].has("continueonerror"), update_view = false;
auto cll = this->server->findClientsByCldbId(cmd["cldbid"]);
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
@@ -5013,27 +5060,42 @@ CommandResult ConnectedClient::handleCommandChannelClientDelPerm(Command &cmd) {
mgr->set_channel_permission(permType, channel->channelId(), permission::v2::empty_permission_values, permission::v2::do_nothing, permission::v2::delete_value);
} else {
mgr->set_channel_permission(permType, channel->channelId(), permission::v2::empty_permission_values, permission::v2::delete_value, permission::v2::do_nothing);
update_view = permType == permission::b_channel_ignore_view_power || permType == permission::i_channel_view_power;
}
}
if (!cll.empty()) {
for (const auto &cl : cll) {
if(cl->update_cached_permissions()) /* update cached calculated permissions */
cl->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
}
for (const auto &elm : cll) {
if(elm->update_cached_permissions()) /* update cached calculated permissions */
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
for (const auto &elm : cll)
if (elm->currentChannel == channel) {
if(elm->currentChannel == channel) {
elm->updateChannelClientProperties(true, true);
} else if(update_view) {
unique_lock client_channel_lock(this->channel_lock);
auto elm_channel = elm->currentChannel;
if(elm_channel) {
deque<ChannelId> deleted;
for(const auto& update_entry : elm->channels->update_channel_path(l_channel, this->server->channelTree->findLinkedChannel(elm->currentChannel->channelId()))) {
if(update_entry.first)
elm->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel);
else deleted.push_back(update_entry.second->channelId());
}
if(!deleted.empty())
elm->notifyChannelHide(deleted, false); /* we've locked the tree before */
}
}
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
}
return CommandResult::Success;
}
//TODO: Update this specific channel visibility?
CommandResult ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) {
CMD_REQ_SERVER;
CMD_REF_SERVER(server_ref);
CMD_RESET_IDLE;
CMD_CHK_AND_INC_FLOOD_POINTS(5);
if (!serverInstance->databaseHelper()->validClientDatabaseId(this->server, cmd["cldbid"])) return {findError("parameter_invalid"), "Invalid manager db id"};
@@ -5041,13 +5103,16 @@ CommandResult ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) {
auto mgr = serverInstance->databaseHelper()->loadClientPermissionManager(this->server, cmd["cldbid"]);
PERM_CHECKR(permission::i_client_permission_modify_power, this->server->calculatePermission(permission::PERMTEST_ORDERED, cmd["cldbid"], permission::i_client_needed_permission_modify_power, ClientType::CLIENT_TEAMSPEAK, nullptr), true);
std::shared_ptr<BasicChannel> channel = this->server->channelTree->findChannel(cmd["cid"].as<ChannelId>());
if (!channel) return {findError("channel_invalid_id"), "Cant resolve channel"};
RESOLVE_CHANNEL_R(cmd["cid"], true);
auto channel = dynamic_pointer_cast<ServerChannel>(l_channel->entry);
if(!channel) return {ErrorType::VSError};
auto maxValue = this->getPermissionGrantValue(permission::PERMTEST_ORDERED, permission::i_permission_modify_power, this->currentChannel);
bool ignoreGrant = this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_permission_modify_power_ignore, 1, this->currentChannel);
bool conOnError = cmd[0].has("continueonerror");
auto onlineClientInstances = this->server->findClientsByCldbId(cmd["cldbid"]);
bool update_view = false;
for (int index = 0; index < cmd.bulkCount(); index++) {
PARSE_PERMISSION(cmd);
@@ -5063,6 +5128,7 @@ CommandResult ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) {
mgr->set_channel_permission(permType, channel->channelId(), {0, cmd[index]["permvalue"]}, permission::v2::do_nothing, permission::v2::set_value);
} else {
mgr->set_channel_permission(permType, channel->channelId(), {cmd[index]["permvalue"], 0}, permission::v2::set_value, permission::v2::do_nothing, cmd[index]["permskip"] ? 1 : 0, cmd[index]["permnegated"] ? 1 : 0);
update_view = permType == permission::b_channel_ignore_view_power || permType == permission::i_channel_view_power;
}
}
if (!onlineClientInstances.empty())
@@ -5070,9 +5136,24 @@ CommandResult ConnectedClient::handleCommandChannelClientAddPerm(Command &cmd) {
if (elm->update_cached_permissions()) /* update cached calculated permissions */
elm->sendNeededPermissions(false); /* cached permissions had changed, notify the client */
if (elm->currentChannel == channel) {
if(elm->currentChannel == channel) {
elm->updateChannelClientProperties(true, true);
} else if(update_view) {
unique_lock client_channel_lock(this->channel_lock);
auto elm_channel = elm->currentChannel;
if(elm_channel) {
deque<ChannelId> deleted;
for(const auto& update_entry : elm->channels->update_channel_path(l_channel, this->server->channelTree->findLinkedChannel(elm->currentChannel->channelId()))) {
if(update_entry.first)
elm->notifyChannelShow(update_entry.second->channel(), update_entry.second->previous_channel);
else deleted.push_back(update_entry.second->channelId());
}
if(!deleted.empty())
elm->notifyChannelHide(deleted, false); /* we've locked the tree before */
}
}
elm->join_state_id++; /* join permission may changed, all channels need to be recalculate dif needed */
}
return CommandResult::Success;
@@ -7337,12 +7418,14 @@ CommandResult ConnectedClient::handleCommandConversationHistory(ts::Command &com
size_t index = 0;
size_t length = 0;
bool merge = command.hasParm("merge");
for(auto& message : messages) {
for(auto it = messages.rbegin(); it != messages.rend(); it++) {
if(index == 0) {
notify[index]["cid"] = conversation_id;
notify[index]["flag_volatile"] = conversation->volatile_only();
}
auto& message = *it;
notify[index]["timestamp"] = duration_cast<milliseconds>(message->message_timestamp.time_since_epoch()).count();
notify[index]["sender_database_id"] = message->sender_database_id;
notify[index]["sender_unique_id"] = message->sender_unique_id;