Add recent group call speakers.
This commit is contained in:
parent
9a4ab8fc23
commit
91d4b57713
@ -2068,10 +2068,11 @@ callStateError error:error = CallState;
|
|||||||
//@id Group call identifier
|
//@id Group call identifier
|
||||||
//@is_active True, if the call is active
|
//@is_active True, if the call is active
|
||||||
//@member_count Number of members in the group call
|
//@member_count Number of members in the group call
|
||||||
|
//@recent_speaker_user_ids Identifiers of recently speaking users in the group call
|
||||||
//@mute_new_members True, if only group call administrators can unmute new members
|
//@mute_new_members True, if only group call administrators can unmute new members
|
||||||
//@allowed_change_mute_new_members True, if group call administrators can enable or disable mute_new_members setting
|
//@allowed_change_mute_new_members True, if group call administrators can enable or disable mute_new_members setting
|
||||||
//@duration Call duration; for ended calls only
|
//@duration Call duration; for ended calls only
|
||||||
groupCall id:int32 is_active:Bool member_count:int32 mute_new_members:Bool allowed_change_mute_new_members:Bool duration:int32 = GroupCall;
|
groupCall id:int32 is_active:Bool member_count:int32 recent_speaker_user_ids:vector<int32> mute_new_members:Bool allowed_change_mute_new_members:Bool duration:int32 = GroupCall;
|
||||||
|
|
||||||
//@description Describes a payload fingerprint for interaction with tgcalls @hash Value of the field hash @setup Value of the field setup @fingerprint Value of the field fingerprint
|
//@description Describes a payload fingerprint for interaction with tgcalls @hash Value of the field hash @setup Value of the field setup @fingerprint Value of the field fingerprint
|
||||||
groupCallPayloadFingerprint hash:string setup:string fingerprint:string = GroupCallPayloadFingerprint;
|
groupCallPayloadFingerprint hash:string setup:string fingerprint:string = GroupCallPayloadFingerprint;
|
||||||
|
Binary file not shown.
@ -13161,6 +13161,17 @@ int32 ContactsManager::get_channel_slow_mode_delay(ChannelId channel_id) {
|
|||||||
return channel_full->slow_mode_delay;
|
return channel_full->slow_mode_delay;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GroupCallId ContactsManager::get_channel_active_group_call_id(ChannelId channel_id) {
|
||||||
|
auto channel_full = get_channel_full_const(channel_id);
|
||||||
|
if (channel_full == nullptr) {
|
||||||
|
channel_full = get_channel_full_force(channel_id, "get_channel_active_group_call_id");
|
||||||
|
if (channel_full == nullptr) {
|
||||||
|
return GroupCallId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return td_->group_call_manager_->get_group_call_id(channel_full->active_group_call_id, channel_id);
|
||||||
|
}
|
||||||
|
|
||||||
bool ContactsManager::have_channel(ChannelId channel_id) const {
|
bool ContactsManager::have_channel(ChannelId channel_id) const {
|
||||||
return channels_.count(channel_id) > 0;
|
return channels_.count(channel_id) > 0;
|
||||||
}
|
}
|
||||||
|
@ -501,6 +501,7 @@ class ContactsManager : public Actor {
|
|||||||
bool get_channel_has_linked_channel(ChannelId channel_id) const;
|
bool get_channel_has_linked_channel(ChannelId channel_id) const;
|
||||||
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
|
ChannelId get_channel_linked_channel_id(ChannelId channel_id);
|
||||||
int32 get_channel_slow_mode_delay(ChannelId channel_id);
|
int32 get_channel_slow_mode_delay(ChannelId channel_id);
|
||||||
|
GroupCallId get_channel_active_group_call_id(ChannelId channel_id);
|
||||||
|
|
||||||
std::pair<int32, vector<UserId>> search_among_users(const vector<UserId> &user_ids, const string &query, int32 limit);
|
std::pair<int32, vector<UserId>> search_among_users(const vector<UserId> &user_ids, const string &query, int32 limit);
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
#include "td/utils/JsonBuilder.h"
|
#include "td/utils/JsonBuilder.h"
|
||||||
#include "td/utils/Random.h"
|
#include "td/utils/Random.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace td {
|
namespace td {
|
||||||
|
|
||||||
class CreateGroupCallQuery : public Td::ResultHandler {
|
class CreateGroupCallQuery : public Td::ResultHandler {
|
||||||
@ -346,6 +348,10 @@ struct GroupCallManager::GroupCall {
|
|||||||
int32 source = 0;
|
int32 source = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GroupCallManager::GroupCallRecentSpeakers {
|
||||||
|
vector<std::pair<UserId, int32>> users; // user + time; sorted by time
|
||||||
|
};
|
||||||
|
|
||||||
struct GroupCallManager::PendingJoinRequest {
|
struct GroupCallManager::PendingJoinRequest {
|
||||||
NetQueryRef query_ref;
|
NetQueryRef query_ref;
|
||||||
uint64 generation = 0;
|
uint64 generation = 0;
|
||||||
@ -386,6 +392,8 @@ void GroupCallManager::on_send_speaking_action_timeout(GroupCallId group_call_id
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
on_user_speaking_in_group_call(group_call_id, td_->contacts_manager_->get_my_id(), G()->unix_time());
|
||||||
|
|
||||||
pending_send_speaking_action_timeout_.add_timeout_in(group_call_id.get(), 4.0);
|
pending_send_speaking_action_timeout_.add_timeout_in(group_call_id.get(), 4.0);
|
||||||
|
|
||||||
td_->messages_manager_->send_dialog_action(DialogId(group_call->channel_id), MessageId(),
|
td_->messages_manager_->send_dialog_action(DialogId(group_call->channel_id), MessageId(),
|
||||||
@ -749,7 +757,13 @@ void GroupCallManager::set_group_call_member_is_speaking(GroupCallId group_call_
|
|||||||
return promise.set_value(Unit());
|
return promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO process others speaking actions
|
if (is_speaking) {
|
||||||
|
// TODO convert source to user_id
|
||||||
|
// on_user_speaking_in_group_call(group_call_id, user_id, G()->unix_time());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO update member list by others speaking actions
|
||||||
|
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -906,7 +920,9 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!group_call->is_active && group_call_recent_speakers_.erase(group_call->group_call_id) != 0) {
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
if (!group_call->channel_id.is_valid()) {
|
if (!group_call->channel_id.is_valid()) {
|
||||||
group_call->channel_id = channel_id;
|
group_call->channel_id = channel_id;
|
||||||
}
|
}
|
||||||
@ -919,15 +935,81 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
|
|||||||
return call_id;
|
return call_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<td_api::groupCall> GroupCallManager::get_group_call_object(const GroupCall *group_call) {
|
void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, UserId user_id, int32 date) {
|
||||||
|
auto input_group_call_id = get_input_group_call_id(group_call_id).move_as_ok();
|
||||||
|
|
||||||
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
|
if (group_call != nullptr && group_call->is_inited && !group_call->is_active) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &recent_speakers = group_call_recent_speakers_[group_call_id];
|
||||||
|
if (recent_speakers == nullptr) {
|
||||||
|
recent_speakers = make_unique<GroupCallRecentSpeakers>();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < recent_speakers->users.size(); i++) {
|
||||||
|
if (recent_speakers->users[i].first == user_id) {
|
||||||
|
if (recent_speakers->users[i].second >= date) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
recent_speakers->users[i].second = date;
|
||||||
|
bool is_updated = false;
|
||||||
|
while (i > 0 && recent_speakers->users[i - 1].second < date) {
|
||||||
|
std::swap(recent_speakers->users[i - 1], recent_speakers->users[i]);
|
||||||
|
i--;
|
||||||
|
is_updated = true;
|
||||||
|
}
|
||||||
|
if (is_updated) {
|
||||||
|
on_group_call_recent_speakers_updated(group_call);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->contacts_manager_->get_user_id_object(user_id, "on_user_speaking_in_group_call");
|
||||||
|
|
||||||
|
for (size_t i = 0; i < recent_speakers->users.size(); i++) {
|
||||||
|
if (recent_speakers->users[i].second <= date) {
|
||||||
|
recent_speakers->users.insert(recent_speakers->users.begin() + i, {user_id, date});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static constexpr size_t MAX_RECENT_SPEAKERS = 3;
|
||||||
|
if (recent_speakers->users.size() > MAX_RECENT_SPEAKERS) {
|
||||||
|
recent_speakers->users.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
on_group_call_recent_speakers_updated(group_call);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCallManager::on_group_call_recent_speakers_updated(GroupCall *group_call) {
|
||||||
|
if (group_call == nullptr || !group_call->is_inited) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
send_closure(G()->td(), &Td::send_update, get_update_group_call_object(group_call));
|
||||||
|
}
|
||||||
|
|
||||||
|
tl_object_ptr<td_api::groupCall> GroupCallManager::get_group_call_object(const GroupCall *group_call) const {
|
||||||
CHECK(group_call != nullptr);
|
CHECK(group_call != nullptr);
|
||||||
CHECK(group_call->is_inited);
|
CHECK(group_call->is_inited);
|
||||||
|
|
||||||
|
vector<int32> recent_speaker_user_ids;
|
||||||
|
auto recent_speakers_it = group_call_recent_speakers_.find(group_call->group_call_id);
|
||||||
|
if (recent_speakers_it != group_call_recent_speakers_.end()) {
|
||||||
|
for (auto &recent_speaker : recent_speakers_it->second->users) {
|
||||||
|
recent_speaker_user_ids.push_back(recent_speaker.first.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return td_api::make_object<td_api::groupCall>(group_call->group_call_id.get(), group_call->is_active,
|
return td_api::make_object<td_api::groupCall>(group_call->group_call_id.get(), group_call->is_active,
|
||||||
group_call->member_count, group_call->mute_new_members,
|
group_call->member_count, std::move(recent_speaker_user_ids),
|
||||||
|
group_call->mute_new_members,
|
||||||
group_call->allowed_change_mute_new_members, group_call->duration);
|
group_call->allowed_change_mute_new_members, group_call->duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<td_api::updateGroupCall> GroupCallManager::get_update_group_call_object(const GroupCall *group_call) {
|
tl_object_ptr<td_api::updateGroupCall> GroupCallManager::get_update_group_call_object(
|
||||||
|
const GroupCall *group_call) const {
|
||||||
return td_api::make_object<td_api::updateGroupCall>(get_group_call_object(group_call));
|
return td_api::make_object<td_api::updateGroupCall>(get_group_call_object(group_call));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,11 +61,14 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, ChannelId channel_id);
|
void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, ChannelId channel_id);
|
||||||
|
|
||||||
|
void on_user_speaking_in_group_call(GroupCallId group_call_id, UserId user_id, int32 date);
|
||||||
|
|
||||||
void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
|
void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
|
||||||
tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise);
|
tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct GroupCall;
|
struct GroupCall;
|
||||||
|
struct GroupCallRecentSpeakers;
|
||||||
struct PendingJoinRequest;
|
struct PendingJoinRequest;
|
||||||
|
|
||||||
void tear_down() override;
|
void tear_down() override;
|
||||||
@ -98,12 +101,14 @@ class GroupCallManager : public Actor {
|
|||||||
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr,
|
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr,
|
||||||
ChannelId channel_id);
|
ChannelId channel_id);
|
||||||
|
|
||||||
|
void on_group_call_recent_speakers_updated(GroupCall *group_call);
|
||||||
|
|
||||||
static Result<td_api::object_ptr<td_api::groupCallJoinResponse>> get_group_call_join_response_object(
|
static Result<td_api::object_ptr<td_api::groupCallJoinResponse>> get_group_call_join_response_object(
|
||||||
string json_response);
|
string json_response);
|
||||||
|
|
||||||
static tl_object_ptr<td_api::updateGroupCall> get_update_group_call_object(const GroupCall *group_call);
|
tl_object_ptr<td_api::updateGroupCall> get_update_group_call_object(const GroupCall *group_call) const;
|
||||||
|
|
||||||
static tl_object_ptr<td_api::groupCall> get_group_call_object(const GroupCall *group_call);
|
tl_object_ptr<td_api::groupCall> get_group_call_object(const GroupCall *group_call) const;
|
||||||
|
|
||||||
Td *td_;
|
Td *td_;
|
||||||
ActorShared<> parent_;
|
ActorShared<> parent_;
|
||||||
@ -114,6 +119,8 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
std::unordered_map<InputGroupCallId, unique_ptr<GroupCall>, InputGroupCallIdHash> group_calls_;
|
std::unordered_map<InputGroupCallId, unique_ptr<GroupCall>, InputGroupCallIdHash> group_calls_;
|
||||||
|
|
||||||
|
std::unordered_map<GroupCallId, unique_ptr<GroupCallRecentSpeakers>, GroupCallIdHash> group_call_recent_speakers_;
|
||||||
|
|
||||||
std::unordered_map<InputGroupCallId, vector<Promise<td_api::object_ptr<td_api::groupCall>>>, InputGroupCallIdHash>
|
std::unordered_map<InputGroupCallId, vector<Promise<td_api::object_ptr<td_api::groupCall>>>, InputGroupCallIdHash>
|
||||||
load_group_call_queries_;
|
load_group_call_queries_;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "td/telegram/files/FileManager.h"
|
#include "td/telegram/files/FileManager.h"
|
||||||
#include "td/telegram/files/FileType.h"
|
#include "td/telegram/files/FileType.h"
|
||||||
#include "td/telegram/Global.h"
|
#include "td/telegram/Global.h"
|
||||||
|
#include "td/telegram/GroupCallManager.h"
|
||||||
#include "td/telegram/InlineQueriesManager.h"
|
#include "td/telegram/InlineQueriesManager.h"
|
||||||
#include "td/telegram/InputMessageText.h"
|
#include "td/telegram/InputMessageText.h"
|
||||||
#include "td/telegram/Location.h"
|
#include "td/telegram/Location.h"
|
||||||
@ -6992,10 +6993,6 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
|
|||||||
if (td_->auth_manager_->is_bot() || !user_id.is_valid() || is_broadcast_channel(dialog_id)) {
|
if (td_->auth_manager_->is_bot() || !user_id.is_valid() || is_broadcast_channel(dialog_id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!have_dialog(dialog_id)) {
|
|
||||||
LOG(DEBUG) << "Ignore typing in unknown " << dialog_id;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!td_->contacts_manager_->have_min_user(user_id)) {
|
if (!td_->contacts_manager_->have_min_user(user_id)) {
|
||||||
LOG(DEBUG) << "Ignore typing of unknown " << user_id;
|
LOG(DEBUG) << "Ignore typing of unknown " << user_id;
|
||||||
return;
|
return;
|
||||||
@ -7005,6 +7002,24 @@ void MessagesManager::on_user_dialog_action(DialogId dialog_id, MessageId top_th
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (action == DialogAction::get_speaking_action()) {
|
||||||
|
if (dialog_id.get_type() != DialogType::Channel || top_thread_message_id.is_valid()) {
|
||||||
|
LOG(ERROR) << "Receive " << action << " in thread of " << top_thread_message_id << " in " << dialog_id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto group_call_id = td_->contacts_manager_->get_channel_active_group_call_id(dialog_id.get_channel_id());
|
||||||
|
if (group_call_id.is_valid()) {
|
||||||
|
td_->group_call_manager_->on_user_speaking_in_group_call(group_call_id, user_id, date);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!have_dialog(dialog_id)) {
|
||||||
|
LOG(DEBUG) << "Ignore typing in unknown " << dialog_id;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool is_canceled = action == DialogAction();
|
bool is_canceled = action == DialogAction();
|
||||||
if (!is_canceled || message_content_type != MessageContentType::None) {
|
if (!is_canceled || message_content_type != MessageContentType::None) {
|
||||||
td_->contacts_manager_->on_update_user_local_was_online(user_id, date);
|
td_->contacts_manager_->on_update_user_local_was_online(user_id, date);
|
||||||
|
Loading…
Reference in New Issue
Block a user