Merge
This commit is contained in:
commit
d0611518f6
@ -125,8 +125,8 @@ TDLib has a simple and convenient C++11-interface for sending and receiving requ
|
|||||||
See [example/cpp](https://github.com/tdlib/td/tree/master/example/cpp) for an example of TDLib usage from C++.
|
See [example/cpp](https://github.com/tdlib/td/tree/master/example/cpp) for an example of TDLib usage from C++.
|
||||||
[td_example.cpp](https://github.com/tdlib/td/tree/master/example/cpp/td_example.cpp) contains an example of authorization, processing new incoming messages, getting a list of chats and sending a text message.
|
[td_example.cpp](https://github.com/tdlib/td/tree/master/example/cpp/td_example.cpp) contains an example of authorization, processing new incoming messages, getting a list of chats and sending a text message.
|
||||||
|
|
||||||
See also the source code of [Depecher](https://github.com/blacksailer/depecher) – a Telegram app for Sailfish OS, [TELEports](https://gitlab.com/ubports/apps/teleports) – a Qt-client for Ubuntu Touch, or
|
See also the source code of [Fernschreiber](https://github.com/Wunderfitz/harbour-fernschreiber) and [Depecher](https://github.com/blacksailer/depecher) – Telegram apps for Sailfish OS,
|
||||||
[tdlib-purple](https://github.com/ars3niy/tdlib-purple) - Telegram plugin for Pidgin, all of which are based on TDLib.
|
[TELEports](https://gitlab.com/ubports/apps/teleports) – a Qt-client for Ubuntu Touch, or [tdlib-purple](https://github.com/ars3niy/tdlib-purple) - Telegram plugin for Pidgin, all of which are based on TDLib.
|
||||||
|
|
||||||
<a name="swift"></a>
|
<a name="swift"></a>
|
||||||
## Using TDLib in Swift projects
|
## Using TDLib in Swift projects
|
||||||
|
@ -34,7 +34,9 @@ target_compile_definitions(tdsqlite PRIVATE
|
|||||||
-DSQLITE_ENABLE_SORTER_REFERENCES
|
-DSQLITE_ENABLE_SORTER_REFERENCES
|
||||||
-DSQLITE_DIRECT_OVERFLOW_READ
|
-DSQLITE_DIRECT_OVERFLOW_READ
|
||||||
-DSQLITE_ENABLE_MEMORY_MANAGEMENT
|
-DSQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||||
|
-DSQLITE_OMIT_DEPRECATED
|
||||||
)
|
)
|
||||||
|
target_compile_definitions(tdsqlite PRIVATE -DSQLITE_HAS_CODEC -DSQLITE_TEMP_STORE=2 -DSQLITE_ENABLE_FTS5 -DSQLITE_DISABLE_LFS -DOMIT_MEMLOCK)
|
||||||
|
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
target_compile_definitions(tdsqlite PRIVATE -DHAVE_USLEEP -DNDEBUG=1)
|
target_compile_definitions(tdsqlite PRIVATE -DHAVE_USLEEP -DNDEBUG=1)
|
||||||
|
230517
sqlite/sqlite/sqlite3.c
vendored
230517
sqlite/sqlite/sqlite3.c
vendored
File diff suppressed because it is too large
Load Diff
@ -2070,13 +2070,14 @@ 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
|
||||||
//@is_joined True, if the call is joined
|
//@is_joined True, if the call is joined
|
||||||
|
//@can_unmute_self True, if the user can unmute themself
|
||||||
//@participant_count Number of participants in the group call
|
//@participant_count Number of participants in the group call
|
||||||
//@loaded_all_participants True, if all group call participants are loaded
|
//@loaded_all_participants True, if all group call participants are loaded
|
||||||
//@recent_speaker_user_ids Identifiers of recently speaking users in the group call
|
//@recent_speaker_user_ids Identifiers of recently speaking users in the group call
|
||||||
//@mute_new_participants True, if only group call administrators can unmute new participants
|
//@mute_new_participants True, if only group call administrators can unmute new participants
|
||||||
//@allowed_change_mute_new_participants True, if group call administrators can enable or disable mute_new_participants setting
|
//@allowed_change_mute_new_participants True, if group call administrators can enable or disable mute_new_participants setting
|
||||||
//@duration Call duration; for ended calls only
|
//@duration Call duration; for ended calls only
|
||||||
groupCall id:int32 is_active:Bool is_joined:Bool participant_count:int32 loaded_all_participants:Bool recent_speaker_user_ids:vector<int32> mute_new_participants:Bool allowed_change_mute_new_participants:Bool duration:int32 = GroupCall;
|
groupCall id:int32 is_active:Bool is_joined:Bool can_unmute_self:Bool participant_count:int32 loaded_all_participants:Bool recent_speaker_user_ids:vector<int32> mute_new_participants:Bool allowed_change_mute_new_participants: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;
|
||||||
@ -2093,9 +2094,9 @@ groupCallJoinResponseCandidate port:string protocol:string network:string genera
|
|||||||
groupCallJoinResponse payload:groupCallPayload candidates:vector<groupCallJoinResponseCandidate> = GroupCallJoinResponse;
|
groupCallJoinResponse payload:groupCallPayload candidates:vector<groupCallJoinResponseCandidate> = GroupCallJoinResponse;
|
||||||
|
|
||||||
//@description Represents a group call participant @user_id Identifier of the user @source User's synchronization source
|
//@description Represents a group call participant @user_id Identifier of the user @source User's synchronization source
|
||||||
//@is_speaking True, if the user is speaking as set by setGroupCallParticipantIsSpeaking @is_muted True, if the user is muted @can_self_unmute True, if the user can unmute themself
|
//@is_speaking True, if the user is speaking as set by setGroupCallParticipantIsSpeaking @is_muted True, if the user is muted @can_unmute_self True, if the user can unmute themself
|
||||||
//@order User's order in the group call participant list. The bigger is order, the higher is user in the list. If order is 0, the user must be removed from the participant list
|
//@order User's order in the group call participant list. The bigger is order, the higher is user in the list. If order is 0, the user must be removed from the participant list
|
||||||
groupCallParticipant user_id:int32 source:int32 is_speaking:Bool is_muted:Bool can_self_unmute:Bool order:int64 = GroupCallParticipant;
|
groupCallParticipant user_id:int32 source:int32 is_speaking:Bool is_muted:Bool can_unmute_self:Bool order:int64 = GroupCallParticipant;
|
||||||
|
|
||||||
|
|
||||||
//@class CallProblem @description Describes the exact type of a problem with a call
|
//@class CallProblem @description Describes the exact type of a problem with a call
|
||||||
@ -4369,7 +4370,7 @@ createVoiceChat chat_id:int53 = GroupCallId;
|
|||||||
//@description Returns information about a group call @group_call_id Group call identifier
|
//@description Returns information about a group call @group_call_id Group call identifier
|
||||||
getGroupCall group_call_id:int32 = GroupCall;
|
getGroupCall group_call_id:int32 = GroupCall;
|
||||||
|
|
||||||
//@description Joins a group call @group_call_id Group call identifier @payload Group join payload, received from tgcalls @source Caller synchronization source identifier; received from tgcalls @is_muted True, if the user's microphone is muted
|
//@description Joins a group call @group_call_id Group call identifier @payload Group join payload, received from tgcalls. Use null to cancel previous joinGroupCall request @source Caller synchronization source identifier; received from tgcalls @is_muted True, if the user's microphone is muted
|
||||||
joinGroupCall group_call_id:int32 payload:groupCallPayload source:int32 is_muted:Bool = GroupCallJoinResponse;
|
joinGroupCall group_call_id:int32 payload:groupCallPayload source:int32 is_muted:Bool = GroupCallJoinResponse;
|
||||||
|
|
||||||
//@description Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires can_manage_voice_chats rights in the corresponding chat and allowed_change_mute_mew_participants group call flag
|
//@description Toggles whether new participants of a group call can be unmuted only by administrators of the group call. Requires can_manage_voice_chats rights in the corresponding chat and allowed_change_mute_mew_participants group call flag
|
||||||
@ -4391,7 +4392,9 @@ toggleGroupCallParticipantIsMuted group_call_id:int32 user_id:int32 is_muted:Boo
|
|||||||
//@description Checks whether a group call is still joined. Should be called every 10 seconds when tgcalls notifies about lost connection with the server @group_call_id Group call identifier
|
//@description Checks whether a group call is still joined. Should be called every 10 seconds when tgcalls notifies about lost connection with the server @group_call_id Group call identifier
|
||||||
checkGroupCallIsJoined group_call_id:int32 = Ok;
|
checkGroupCallIsJoined group_call_id:int32 = Ok;
|
||||||
|
|
||||||
//@description Loads more group call participants. The loaded participants will be received through updates @group_call_id Group call identifier @limit Maximum number of participants to load
|
//@description Loads more group call participants. The loaded participants will be received through updates. Use the field groupCall.loaded_all_participants to check whether all participants has already been loaded
|
||||||
|
//@group_call_id Group call identifier. The group call must be previously received through getGroupCall and must be joined or being joined
|
||||||
|
//@limit Maximum number of participants to load
|
||||||
loadGroupCallParticipants group_call_id:int32 limit:int32 = Ok;
|
loadGroupCallParticipants group_call_id:int32 limit:int32 = Ok;
|
||||||
|
|
||||||
//@description Leaves a group call @group_call_id Group call identifier
|
//@description Leaves a group call @group_call_id Group call identifier
|
||||||
|
@ -10983,16 +10983,17 @@ void ContactsManager::drop_channel_photos(ChannelId channel_id, bool is_empty, b
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay) {
|
void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool need_drop_invite_link,
|
||||||
|
bool need_drop_slow_mode_delay) {
|
||||||
LOG(INFO) << "Invalidate supergroup full for " << channel_id;
|
LOG(INFO) << "Invalidate supergroup full for " << channel_id;
|
||||||
// drop channel full cache
|
// drop channel full cache
|
||||||
auto channel_full = get_channel_full_force(channel_id, "invalidate_channel_full");
|
auto channel_full = get_channel_full_force(channel_id, "invalidate_channel_full");
|
||||||
if (channel_full != nullptr) {
|
if (channel_full != nullptr) {
|
||||||
channel_full->expires_at = 0.0;
|
channel_full->expires_at = 0.0;
|
||||||
if (drop_invite_link) {
|
if (need_drop_invite_link) {
|
||||||
on_update_channel_full_invite_link(channel_full, nullptr);
|
on_update_channel_full_invite_link(channel_full, nullptr);
|
||||||
}
|
}
|
||||||
if (drop_slow_mode_delay && channel_full->slow_mode_delay != 0) {
|
if (need_drop_slow_mode_delay && channel_full->slow_mode_delay != 0) {
|
||||||
channel_full->slow_mode_delay = 0;
|
channel_full->slow_mode_delay = 0;
|
||||||
channel_full->slow_mode_next_send_date = 0;
|
channel_full->slow_mode_next_send_date = 0;
|
||||||
channel_full->is_slow_mode_next_send_date_changed = true;
|
channel_full->is_slow_mode_next_send_date_changed = true;
|
||||||
@ -11000,7 +11001,7 @@ void ContactsManager::invalidate_channel_full(ChannelId channel_id, bool drop_in
|
|||||||
}
|
}
|
||||||
update_channel_full(channel_full, channel_id);
|
update_channel_full(channel_full, channel_id);
|
||||||
}
|
}
|
||||||
if (drop_invite_link) {
|
if (need_drop_invite_link) {
|
||||||
remove_dialog_access_by_invite_link(DialogId(channel_id));
|
remove_dialog_access_by_invite_link(DialogId(channel_id));
|
||||||
|
|
||||||
auto it = dialog_invite_links_.find(DialogId(channel_id));
|
auto it = dialog_invite_links_.find(DialogId(channel_id));
|
||||||
@ -11705,7 +11706,8 @@ void ContactsManager::on_update_chat_delete_user(ChatId chat_id, UserId user_id,
|
|||||||
void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParticipantStatus status) {
|
void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParticipantStatus status) {
|
||||||
if (c->status != status) {
|
if (c->status != status) {
|
||||||
LOG(INFO) << "Update " << chat_id << " status from " << c->status << " to " << status;
|
LOG(INFO) << "Update " << chat_id << " status from " << c->status << " to " << status;
|
||||||
bool drop_invite_link = c->status.is_left() != status.is_left();
|
bool need_drop_invite_link = c->status.is_left() != status.is_left();
|
||||||
|
bool need_reload_group_call = c->status.can_manage_calls() != status.can_manage_calls();
|
||||||
|
|
||||||
c->status = status;
|
c->status = status;
|
||||||
|
|
||||||
@ -11717,12 +11719,15 @@ void ContactsManager::on_update_chat_status(Chat *c, ChatId chat_id, DialogParti
|
|||||||
|
|
||||||
drop_chat_full(chat_id);
|
drop_chat_full(chat_id);
|
||||||
}
|
}
|
||||||
if (drop_invite_link) {
|
if (need_drop_invite_link) {
|
||||||
auto it = dialog_invite_links_.find(DialogId(chat_id));
|
auto it = dialog_invite_links_.find(DialogId(chat_id));
|
||||||
if (it != dialog_invite_links_.end()) {
|
if (it != dialog_invite_links_.end()) {
|
||||||
invalidate_invite_link_info(it->second);
|
invalidate_invite_link_info(it->second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (need_reload_group_call) {
|
||||||
|
td_->messages_manager_->reload_dialog_group_call(DialogId(chat_id));
|
||||||
|
}
|
||||||
|
|
||||||
c->is_changed = true;
|
c->is_changed = true;
|
||||||
}
|
}
|
||||||
@ -12048,9 +12053,10 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
|
|||||||
const DialogParticipantStatus &new_status) {
|
const DialogParticipantStatus &new_status) {
|
||||||
CHECK(c->is_update_supergroup_sent);
|
CHECK(c->is_update_supergroup_sent);
|
||||||
|
|
||||||
bool drop_invite_link = old_status.is_administrator() != new_status.is_administrator() ||
|
bool need_drop_invite_link = old_status.is_administrator() != new_status.is_administrator() ||
|
||||||
old_status.is_member() != new_status.is_member();
|
old_status.is_member() != new_status.is_member();
|
||||||
invalidate_channel_full(channel_id, drop_invite_link, !c->is_slow_mode_enabled);
|
bool need_reload_group_call = old_status.can_manage_calls() != new_status.can_manage_calls();
|
||||||
|
invalidate_channel_full(channel_id, need_drop_invite_link, !c->is_slow_mode_enabled);
|
||||||
|
|
||||||
if (old_status.is_creator() != new_status.is_creator()) {
|
if (old_status.is_creator() != new_status.is_creator()) {
|
||||||
for (size_t i = 0; i < 2; i++) {
|
for (size_t i = 0; i < 2; i++) {
|
||||||
@ -12061,6 +12067,9 @@ void ContactsManager::on_channel_status_changed(Channel *c, ChannelId channel_id
|
|||||||
send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner");
|
send_get_channel_full_query(nullptr, channel_id, Auto(), "update channel owner");
|
||||||
reload_dialog_administrators(DialogId(channel_id), 0, Auto());
|
reload_dialog_administrators(DialogId(channel_id), 0, Auto());
|
||||||
}
|
}
|
||||||
|
if (need_reload_group_call) {
|
||||||
|
td_->messages_manager_->reload_dialog_group_call(DialogId(channel_id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_update_channel_default_permissions(Channel *c, ChannelId channel_id,
|
void ContactsManager::on_update_channel_default_permissions(Channel *c, ChannelId channel_id,
|
||||||
@ -13832,7 +13841,8 @@ void ContactsManager::on_chat_update(telegram_api::chat &chat, const char *sourc
|
|||||||
|
|
||||||
bool has_active_group_call = (chat.flags_ & CHAT_FLAG_HAS_ACTIVE_GROUP_CALL) != 0;
|
bool has_active_group_call = (chat.flags_ & CHAT_FLAG_HAS_ACTIVE_GROUP_CALL) != 0;
|
||||||
bool is_group_call_empty = (chat.flags_ & CHAT_FLAG_IS_GROUP_CALL_NON_EMPTY) == 0;
|
bool is_group_call_empty = (chat.flags_ & CHAT_FLAG_IS_GROUP_CALL_NON_EMPTY) == 0;
|
||||||
td_->messages_manager_->on_update_dialog_group_call(DialogId(chat_id), has_active_group_call, is_group_call_empty);
|
td_->messages_manager_->on_update_dialog_group_call(DialogId(chat_id), has_active_group_call, is_group_call_empty,
|
||||||
|
"receive chat");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_chat_update(telegram_api::chatForbidden &chat, const char *source) {
|
void ContactsManager::on_chat_update(telegram_api::chatForbidden &chat, const char *source) {
|
||||||
@ -14025,7 +14035,8 @@ void ContactsManager::on_chat_update(telegram_api::channel &channel, const char
|
|||||||
|
|
||||||
bool has_active_group_call = (channel.flags_ & CHANNEL_FLAG_HAS_ACTIVE_GROUP_CALL) != 0;
|
bool has_active_group_call = (channel.flags_ & CHANNEL_FLAG_HAS_ACTIVE_GROUP_CALL) != 0;
|
||||||
bool is_group_call_empty = (channel.flags_ & CHANNEL_FLAG_IS_GROUP_CALL_NON_EMPTY) == 0;
|
bool is_group_call_empty = (channel.flags_ & CHANNEL_FLAG_IS_GROUP_CALL_NON_EMPTY) == 0;
|
||||||
td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), has_active_group_call, is_group_call_empty);
|
td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), has_active_group_call, is_group_call_empty,
|
||||||
|
"receive channel");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, const char *source) {
|
void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, const char *source) {
|
||||||
@ -14064,7 +14075,7 @@ void ContactsManager::on_chat_update(telegram_api::channelForbidden &channel, co
|
|||||||
// on_update_channel_username(c, channel_id, ""); // don't know if channel username is empty, so don't update it
|
// on_update_channel_username(c, channel_id, ""); // don't know if channel username is empty, so don't update it
|
||||||
tl_object_ptr<telegram_api::chatBannedRights> banned_rights; // == nullptr
|
tl_object_ptr<telegram_api::chatBannedRights> banned_rights; // == nullptr
|
||||||
on_update_channel_default_permissions(c, channel_id, get_restricted_rights(banned_rights));
|
on_update_channel_default_permissions(c, channel_id, get_restricted_rights(banned_rights));
|
||||||
td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), false, false);
|
td_->messages_manager_->on_update_dialog_group_call(DialogId(channel_id), false, false, "receive channelForbidden");
|
||||||
|
|
||||||
bool sign_messages = false;
|
bool sign_messages = false;
|
||||||
bool is_slow_mode_enabled = false;
|
bool is_slow_mode_enabled = false;
|
||||||
|
@ -219,7 +219,7 @@ class ContactsManager : public Actor {
|
|||||||
|
|
||||||
void speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me);
|
void speculative_delete_channel_participant(ChannelId channel_id, UserId deleted_user_id, bool by_me);
|
||||||
|
|
||||||
void invalidate_channel_full(ChannelId channel_id, bool drop_invite_link, bool drop_slow_mode_delay);
|
void invalidate_channel_full(ChannelId channel_id, bool need_drop_invite_link, bool need_drop_slow_mode_delay);
|
||||||
|
|
||||||
bool on_get_channel_error(ChannelId channel_id, const Status &status, const string &source);
|
bool on_get_channel_error(ChannelId channel_id, const Status &status, const string &source);
|
||||||
|
|
||||||
@ -721,7 +721,7 @@ class ContactsManager : public Actor {
|
|||||||
DialogParticipantStatus status = DialogParticipantStatus::Banned(0);
|
DialogParticipantStatus status = DialogParticipantStatus::Banned(0);
|
||||||
RestrictedRights default_permissions{false, false, false, false, false, false, false, false, false, false, false};
|
RestrictedRights default_permissions{false, false, false, false, false, false, false, false, false, false, false};
|
||||||
|
|
||||||
static constexpr uint32 CACHE_VERSION = 2;
|
static constexpr uint32 CACHE_VERSION = 3;
|
||||||
uint32 cache_version = 0;
|
uint32 cache_version = 0;
|
||||||
|
|
||||||
bool is_active = false;
|
bool is_active = false;
|
||||||
@ -788,7 +788,7 @@ class ContactsManager : public Actor {
|
|||||||
int32 date = 0;
|
int32 date = 0;
|
||||||
int32 participant_count = 0;
|
int32 participant_count = 0;
|
||||||
|
|
||||||
static constexpr uint32 CACHE_VERSION = 5;
|
static constexpr uint32 CACHE_VERSION = 6;
|
||||||
uint32 cache_version = 0;
|
uint32 cache_version = 0;
|
||||||
|
|
||||||
bool has_linked_channel = false;
|
bool has_linked_channel = false;
|
||||||
|
@ -405,6 +405,8 @@ struct GroupCallManager::GroupCall {
|
|||||||
bool is_active = false;
|
bool is_active = false;
|
||||||
bool is_joined = false;
|
bool is_joined = false;
|
||||||
bool is_speaking = false;
|
bool is_speaking = false;
|
||||||
|
bool can_self_unmute = false;
|
||||||
|
bool syncing_participants = false;
|
||||||
bool loaded_all_participants = false;
|
bool loaded_all_participants = false;
|
||||||
bool mute_new_participants = false;
|
bool mute_new_participants = false;
|
||||||
bool allowed_change_mute_new_participants = false;
|
bool allowed_change_mute_new_participants = false;
|
||||||
@ -590,6 +592,46 @@ GroupCallManager::GroupCall *GroupCallManager::get_group_call(InputGroupCallId i
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Status GroupCallManager::can_manage_group_calls(DialogId dialog_id) {
|
||||||
|
switch (dialog_id.get_type()) {
|
||||||
|
case DialogType::Chat: {
|
||||||
|
auto chat_id = dialog_id.get_chat_id();
|
||||||
|
if (!td_->contacts_manager_->get_chat_permissions(chat_id).can_manage_calls()) {
|
||||||
|
return Status::Error(400, "Not enough rights in the chat");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DialogType::Channel: {
|
||||||
|
auto channel_id = dialog_id.get_channel_id();
|
||||||
|
switch (td_->contacts_manager_->get_channel_type(channel_id)) {
|
||||||
|
case ChannelType::Unknown:
|
||||||
|
return Status::Error(400, "Chat info not found");
|
||||||
|
case ChannelType::Megagroup:
|
||||||
|
// OK
|
||||||
|
break;
|
||||||
|
case ChannelType::Broadcast:
|
||||||
|
return Status::Error(400, "Chat is not a group");
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!td_->contacts_manager_->get_channel_permissions(channel_id).can_manage_calls()) {
|
||||||
|
return Status::Error(400, "Not enough rights in the chat");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DialogType::User:
|
||||||
|
case DialogType::SecretChat:
|
||||||
|
return Status::Error(400, "Chat can't have a voice chat");
|
||||||
|
case DialogType::None:
|
||||||
|
// OK
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCallManager::create_voice_chat(DialogId dialog_id, Promise<GroupCallId> &&promise) {
|
void GroupCallManager::create_voice_chat(DialogId dialog_id, Promise<GroupCallId> &&promise) {
|
||||||
if (!dialog_id.is_valid()) {
|
if (!dialog_id.is_valid()) {
|
||||||
return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
|
return promise.set_error(Status::Error(400, "Invalid chat identifier specified"));
|
||||||
@ -601,39 +643,7 @@ void GroupCallManager::create_voice_chat(DialogId dialog_id, Promise<GroupCallId
|
|||||||
return promise.set_error(Status::Error(400, "Can't access chat"));
|
return promise.set_error(Status::Error(400, "Can't access chat"));
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (dialog_id.get_type()) {
|
TRY_STATUS_PROMISE(promise, can_manage_group_calls(dialog_id));
|
||||||
case DialogType::Chat: {
|
|
||||||
auto chat_id = dialog_id.get_chat_id();
|
|
||||||
if (!td_->contacts_manager_->get_chat_permissions(chat_id).can_manage_calls()) {
|
|
||||||
return promise.set_error(Status::Error(400, "Not enough rights in the chat"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DialogType::Channel: {
|
|
||||||
auto channel_id = dialog_id.get_channel_id();
|
|
||||||
switch (td_->contacts_manager_->get_channel_type(channel_id)) {
|
|
||||||
case ChannelType::Unknown:
|
|
||||||
return promise.set_error(Status::Error(400, "Chat info not found"));
|
|
||||||
case ChannelType::Megagroup:
|
|
||||||
// OK
|
|
||||||
break;
|
|
||||||
case ChannelType::Broadcast:
|
|
||||||
return promise.set_error(Status::Error(400, "Chat is not a group"));
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!td_->contacts_manager_->get_channel_permissions(channel_id).can_manage_calls()) {
|
|
||||||
return promise.set_error(Status::Error(400, "Not enough rights in the chat"));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DialogType::User:
|
|
||||||
case DialogType::SecretChat:
|
|
||||||
return promise.set_error(Status::Error(400, "Chat can't have a voice chat"));
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto query_promise = PromiseCreator::lambda(
|
auto query_promise = PromiseCreator::lambda(
|
||||||
[actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result<InputGroupCallId> result) mutable {
|
[actor_id = actor_id(this), dialog_id, promise = std::move(promise)](Result<InputGroupCallId> result) mutable {
|
||||||
@ -656,7 +666,7 @@ void GroupCallManager::on_voice_chat_created(DialogId dialog_id, InputGroupCallI
|
|||||||
return promise.set_error(Status::Error(500, "Receive invalid group call identifier"));
|
return promise.set_error(Status::Error(500, "Receive invalid group call identifier"));
|
||||||
}
|
}
|
||||||
|
|
||||||
td_->messages_manager_->on_update_dialog_group_call(dialog_id, true, true);
|
td_->messages_manager_->on_update_dialog_group_call(dialog_id, true, true, "on_voice_chat_created");
|
||||||
td_->messages_manager_->on_update_dialog_group_call_id(dialog_id, input_group_call_id);
|
td_->messages_manager_->on_update_dialog_group_call_id(dialog_id, input_group_call_id);
|
||||||
|
|
||||||
promise.set_value(get_group_call_id(input_group_call_id, dialog_id));
|
promise.set_value(get_group_call_id(input_group_call_id, dialog_id));
|
||||||
@ -701,16 +711,6 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i
|
|||||||
if (update_group_call(result.ok()->call_, DialogId()) != input_group_call_id) {
|
if (update_group_call(result.ok()->call_, DialogId()) != input_group_call_id) {
|
||||||
LOG(ERROR) << "Expected " << input_group_call_id << ", but received " << to_string(result.ok());
|
LOG(ERROR) << "Expected " << input_group_call_id << ", but received " << to_string(result.ok());
|
||||||
result = Status::Error(500, "Receive another group call");
|
result = Status::Error(500, "Receive another group call");
|
||||||
} else {
|
|
||||||
process_group_call_participants(input_group_call_id, std::move(result.ok_ref()->participants_), true);
|
|
||||||
|
|
||||||
auto participants_it = group_call_participants_.find(input_group_call_id);
|
|
||||||
if (participants_it != group_call_participants_.end()) {
|
|
||||||
CHECK(participants_it->second != nullptr);
|
|
||||||
if (participants_it->second->next_offset.empty()) {
|
|
||||||
participants_it->second->next_offset = std::move(result.ok_ref()->participants_next_offset_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,15 +721,29 @@ void GroupCallManager::finish_get_group_call(InputGroupCallId input_group_call_i
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto call = result.move_as_ok();
|
||||||
|
process_group_call_participants(input_group_call_id, std::move(call->participants_), true, false);
|
||||||
|
if (need_group_call_participants(input_group_call_id)) {
|
||||||
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
|
if (participants_it != group_call_participants_.end()) {
|
||||||
|
CHECK(participants_it->second != nullptr);
|
||||||
|
if (participants_it->second->next_offset.empty()) {
|
||||||
|
participants_it->second->next_offset = std::move(call->participants_next_offset_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto group_call = get_group_call(input_group_call_id);
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
for (auto &promise : promises) {
|
for (auto &promise : promises) {
|
||||||
|
if (promise) {
|
||||||
promise.set_value(get_group_call_object(group_call, get_recent_speaker_user_ids(group_call, false)));
|
promise.set_value(get_group_call_object(group_call, get_recent_speaker_user_ids(group_call, false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool GroupCallManager::need_group_call_participants(InputGroupCallId input_group_call_id) const {
|
bool GroupCallManager::need_group_call_participants(InputGroupCallId input_group_call_id) const {
|
||||||
auto *group_call = get_group_call(input_group_call_id);
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
if (group_call == nullptr || !group_call->is_inited) {
|
if (group_call == nullptr || !group_call->is_inited || !group_call->is_active) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (group_call->is_joined) {
|
if (group_call->is_joined) {
|
||||||
@ -753,13 +767,33 @@ void GroupCallManager::on_get_group_call_participants(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto is_empty = participants->participants_.empty();
|
bool is_sync = is_load && offset.empty();
|
||||||
process_group_call_participants(input_group_call_id, std::move(participants->participants_), is_load);
|
if (is_sync) {
|
||||||
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
|
is_sync = group_call->syncing_participants;
|
||||||
|
if (is_sync) {
|
||||||
|
group_call->syncing_participants = false;
|
||||||
|
|
||||||
|
if (group_call->version >= participants->version_) {
|
||||||
|
LOG(INFO) << "Ignore result of outdated participants sync with version " << participants->version_ << " in "
|
||||||
|
<< input_group_call_id << " from " << group_call->dialog_id << ", because current version is "
|
||||||
|
<< group_call->version;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LOG(INFO) << "Finish syncing participants in " << input_group_call_id << " from " << group_call->dialog_id
|
||||||
|
<< " with version " << participants->version_;
|
||||||
|
group_call->version = participants->version_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto is_empty = participants->participants_.empty();
|
||||||
|
process_group_call_participants(input_group_call_id, std::move(participants->participants_), is_load, is_sync);
|
||||||
|
|
||||||
|
if (!is_sync) {
|
||||||
on_receive_group_call_version(input_group_call_id, participants->version_);
|
on_receive_group_call_version(input_group_call_id, participants->version_);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_load) {
|
if (is_load) {
|
||||||
// TODO use count
|
|
||||||
auto participants_it = group_call_participants_.find(input_group_call_id);
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
if (participants_it != group_call_participants_.end()) {
|
if (participants_it != group_call_participants_.end()) {
|
||||||
CHECK(participants_it->second != nullptr);
|
CHECK(participants_it->second != nullptr);
|
||||||
@ -768,26 +802,43 @@ void GroupCallManager::on_get_group_call_participants(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_empty) {
|
if (is_empty || is_sync) {
|
||||||
bool need_update = false;
|
bool need_update = false;
|
||||||
auto group_call = get_group_call(input_group_call_id);
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
CHECK(group_call != nullptr && group_call->is_inited);
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
if (!group_call->loaded_all_participants) {
|
if (is_empty && !group_call->loaded_all_participants) {
|
||||||
group_call->loaded_all_participants = true;
|
group_call->loaded_all_participants = true;
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto real_participant_count = participants_it != group_call_participants_.end()
|
auto real_participant_count = participants->count_;
|
||||||
|
if (is_empty) {
|
||||||
|
auto known_participant_count = participants_it != group_call_participants_.end()
|
||||||
? static_cast<int32>(participants_it->second->participants.size())
|
? static_cast<int32>(participants_it->second->participants.size())
|
||||||
: 0;
|
: 0;
|
||||||
|
if (real_participant_count != known_participant_count) {
|
||||||
|
LOG(ERROR) << "Receive participant count " << real_participant_count << ", but know "
|
||||||
|
<< known_participant_count << " participants in " << input_group_call_id << " from "
|
||||||
|
<< group_call->dialog_id;
|
||||||
|
real_participant_count = known_participant_count;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (real_participant_count != group_call->participant_count) {
|
if (real_participant_count != group_call->participant_count) {
|
||||||
|
if (!is_sync) {
|
||||||
LOG(ERROR) << "Have participant count " << group_call->participant_count << " instead of "
|
LOG(ERROR) << "Have participant count " << group_call->participant_count << " instead of "
|
||||||
<< real_participant_count << " in " << input_group_call_id;
|
<< real_participant_count << " in " << input_group_call_id << " from " << group_call->dialog_id;
|
||||||
|
}
|
||||||
group_call->participant_count = real_participant_count;
|
group_call->participant_count = real_participant_count;
|
||||||
need_update = true;
|
need_update = true;
|
||||||
|
|
||||||
|
update_group_call_dialog(group_call, "on_get_group_call_participants");
|
||||||
|
}
|
||||||
|
if (!is_empty && is_sync && group_call->loaded_all_participants && group_call->participant_count > 50) {
|
||||||
|
group_call->loaded_all_participants = false;
|
||||||
|
need_update = true;
|
||||||
}
|
}
|
||||||
if (need_update) {
|
if (need_update) {
|
||||||
send_update_group_call(group_call);
|
send_update_group_call(group_call, "on_get_group_call_participants");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -797,7 +848,45 @@ void GroupCallManager::on_update_group_call_participants(
|
|||||||
InputGroupCallId input_group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
InputGroupCallId input_group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
||||||
int32 version) {
|
int32 version) {
|
||||||
if (!need_group_call_participants(input_group_call_id)) {
|
if (!need_group_call_participants(input_group_call_id)) {
|
||||||
LOG(INFO) << "Ignore updateGroupCallParticipants in " << input_group_call_id;
|
int32 diff = 0;
|
||||||
|
bool need_update = false;
|
||||||
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
|
for (auto &group_call_participant : participants) {
|
||||||
|
GroupCallParticipant participant(group_call_participant);
|
||||||
|
if (participant.user_id == td_->contacts_manager_->get_my_id() && group_call != nullptr &&
|
||||||
|
group_call->is_inited && group_call->is_joined &&
|
||||||
|
(participant.joined_date == 0) == (participant.source == group_call->source)) {
|
||||||
|
on_group_call_left_impl(group_call);
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
|
if (participant.joined_date == 0) {
|
||||||
|
diff--;
|
||||||
|
remove_recent_group_call_speaker(input_group_call_id, participant.user_id);
|
||||||
|
} else {
|
||||||
|
if (participant.is_just_joined) {
|
||||||
|
diff++;
|
||||||
|
}
|
||||||
|
on_participant_speaking_in_group_call(input_group_call_id, participant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group_call != nullptr && group_call->is_inited && group_call->is_active && group_call->version == -1) {
|
||||||
|
if (diff != 0 && (group_call->participant_count != 0 || diff > 0)) {
|
||||||
|
group_call->participant_count += diff;
|
||||||
|
if (group_call->participant_count < 0) {
|
||||||
|
LOG(ERROR) << "Participant count became negative in " << input_group_call_id << " from "
|
||||||
|
<< group_call->dialog_id;
|
||||||
|
group_call->participant_count = 0;
|
||||||
|
}
|
||||||
|
update_group_call_dialog(group_call, "on_update_group_call_participants");
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (need_update) {
|
||||||
|
send_update_group_call(group_call, "on_update_group_call_participants");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Ignore updateGroupCallParticipants in " << input_group_call_id << " from " << group_call->dialog_id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (version <= 0) {
|
if (version <= 0) {
|
||||||
@ -816,7 +905,7 @@ void GroupCallManager::on_update_group_call_participants(
|
|||||||
}
|
}
|
||||||
auto &pending_updates = group_call_participants->pending_updates_[version];
|
auto &pending_updates = group_call_participants->pending_updates_[version];
|
||||||
if (!pending_updates.empty()) {
|
if (!pending_updates.empty()) {
|
||||||
LOG(ERROR) << "Receive duplicate updateGroupCallParticipants with version " << version << " in "
|
LOG(INFO) << "Receive duplicate updateGroupCallParticipants with version " << version << " in "
|
||||||
<< input_group_call_id;
|
<< input_group_call_id;
|
||||||
sync_group_call_participants(input_group_call_id);
|
sync_group_call_participants(input_group_call_id);
|
||||||
return;
|
return;
|
||||||
@ -838,11 +927,12 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
|
|||||||
auto &pending_updates = participants_it->second->pending_updates_;
|
auto &pending_updates = participants_it->second->pending_updates_;
|
||||||
auto group_call = get_group_call(input_group_call_id);
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
CHECK(group_call != nullptr && group_call->is_inited);
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
if (group_call->version == -1) {
|
if (group_call->version == -1 || !group_call->is_active) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 diff = 0;
|
int32 diff = 0;
|
||||||
|
bool is_left = false;
|
||||||
while (!pending_updates.empty()) {
|
while (!pending_updates.empty()) {
|
||||||
auto it = pending_updates.begin();
|
auto it = pending_updates.begin();
|
||||||
auto version = it->first;
|
auto version = it->first;
|
||||||
@ -853,23 +943,35 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
|
|||||||
if (participant.user_id == td_->contacts_manager_->get_my_id()) {
|
if (participant.user_id == td_->contacts_manager_->get_my_id()) {
|
||||||
process_group_call_participant(input_group_call_id, std::move(participant));
|
process_group_call_participant(input_group_call_id, std::move(participant));
|
||||||
}
|
}
|
||||||
|
on_participant_speaking_in_group_call(input_group_call_id, participant);
|
||||||
}
|
}
|
||||||
LOG(INFO) << "Ignore already applied updateGroupCallParticipants with version " << version << " in "
|
LOG(INFO) << "Ignore already applied updateGroupCallParticipants with version " << version << " in "
|
||||||
<< input_group_call_id;
|
<< input_group_call_id << " from " << group_call->dialog_id;
|
||||||
pending_updates.erase(it);
|
pending_updates.erase(it);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (version < group_call->version + static_cast<int32>(participants.size())) {
|
if (version < group_call->version + static_cast<int32>(participants.size())) {
|
||||||
|
LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version
|
||||||
|
<< ", but current version is " << group_call->version;
|
||||||
sync_group_call_participants(input_group_call_id);
|
sync_group_call_participants(input_group_call_id);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (version == group_call->version + static_cast<int32>(participants.size())) {
|
if (version == group_call->version + static_cast<int32>(participants.size())) {
|
||||||
group_call->version = version;
|
group_call->version = version;
|
||||||
diff += process_group_call_participants_from_updates(input_group_call_id, std::move(participants));
|
for (auto &participant : participants) {
|
||||||
|
GroupCallParticipant group_call_participant(participant);
|
||||||
|
if (group_call_participant.user_id == td_->contacts_manager_->get_my_id() && group_call->is_joined &&
|
||||||
|
(group_call_participant.joined_date == 0) == (group_call_participant.source == group_call->source)) {
|
||||||
|
is_left = true;
|
||||||
|
}
|
||||||
|
diff += process_group_call_participant(input_group_call_id, std::move(group_call_participant));
|
||||||
|
}
|
||||||
pending_updates.erase(it);
|
pending_updates.erase(it);
|
||||||
} else {
|
} else if (!group_call->syncing_participants) {
|
||||||
// found a gap
|
// found a gap
|
||||||
|
LOG(INFO) << "Receive " << participants.size() << " group call participant updates with version " << version
|
||||||
|
<< ", but current version is " << group_call->version;
|
||||||
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
|
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -877,16 +979,26 @@ bool GroupCallManager::process_pending_group_call_participant_updates(InputGroup
|
|||||||
if (pending_updates.empty()) {
|
if (pending_updates.empty()) {
|
||||||
sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get());
|
sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool need_update = false;
|
||||||
if (diff != 0 && (group_call->participant_count != 0 || diff > 0)) {
|
if (diff != 0 && (group_call->participant_count != 0 || diff > 0)) {
|
||||||
group_call->participant_count += diff;
|
group_call->participant_count += diff;
|
||||||
if (group_call->participant_count < 0) {
|
if (group_call->participant_count < 0) {
|
||||||
LOG(ERROR) << "Participant count became negative in " << input_group_call_id;
|
LOG(ERROR) << "Participant count became negative in " << input_group_call_id << " from " << group_call->dialog_id;
|
||||||
group_call->participant_count = 0;
|
group_call->participant_count = 0;
|
||||||
}
|
}
|
||||||
send_update_group_call(group_call);
|
need_update = true;
|
||||||
return true;
|
update_group_call_dialog(group_call, "process_pending_group_call_participant_updates");
|
||||||
}
|
}
|
||||||
return false;
|
if (is_left && group_call->is_joined) {
|
||||||
|
on_group_call_left_impl(group_call);
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
|
if (need_update) {
|
||||||
|
send_update_group_call(group_call, "process_pending_group_call_participant_updates");
|
||||||
|
}
|
||||||
|
|
||||||
|
return need_update;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCallManager::sync_group_call_participants(InputGroupCallId input_group_call_id) {
|
void GroupCallManager::sync_group_call_participants(InputGroupCallId input_group_call_id) {
|
||||||
@ -899,17 +1011,60 @@ void GroupCallManager::sync_group_call_participants(InputGroupCallId input_group
|
|||||||
|
|
||||||
sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get());
|
sync_participants_timeout_.cancel_timeout(group_call->group_call_id.get());
|
||||||
|
|
||||||
LOG(INFO) << "Force participants synchronization in " << input_group_call_id;
|
if (group_call->syncing_participants) {
|
||||||
// TODO
|
return;
|
||||||
|
}
|
||||||
|
group_call->syncing_participants = true;
|
||||||
|
|
||||||
|
LOG(INFO) << "Force participants synchronization in " << input_group_call_id << " from " << group_call->dialog_id;
|
||||||
|
auto promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id](Result<Unit> &&result) {
|
||||||
|
if (result.is_error()) {
|
||||||
|
send_closure(actor_id, &GroupCallManager::on_sync_group_call_participants_failed, input_group_call_id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
td_->create_handler<GetGroupCallParticipantsQuery>(std::move(promise))->send(input_group_call_id, string(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCallManager::on_sync_group_call_participants_failed(InputGroupCallId input_group_call_id) {
|
||||||
|
if (G()->close_flag() || !need_group_call_participants(input_group_call_id)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
|
CHECK(group_call->syncing_participants);
|
||||||
|
group_call->syncing_participants = false;
|
||||||
|
|
||||||
|
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCallManager::process_group_call_participants(
|
void GroupCallManager::process_group_call_participants(
|
||||||
InputGroupCallId input_group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
InputGroupCallId input_group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
||||||
bool is_load) {
|
bool is_load, bool is_sync) {
|
||||||
if (!need_group_call_participants(input_group_call_id)) {
|
if (!need_group_call_participants(input_group_call_id)) {
|
||||||
|
for (auto &participant : participants) {
|
||||||
|
GroupCallParticipant group_call_participant(participant);
|
||||||
|
if (!group_call_participant.is_valid()) {
|
||||||
|
LOG(ERROR) << "Receive invalid " << to_string(participant);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_participant_speaking_in_group_call(input_group_call_id, group_call_participant);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_set<UserId, UserIdHash> old_participant_user_ids;
|
||||||
|
if (is_sync) {
|
||||||
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
|
if (participants_it != group_call_participants_.end()) {
|
||||||
|
CHECK(participants_it->second != nullptr);
|
||||||
|
for (auto &participant : participants_it->second->participants) {
|
||||||
|
old_participant_user_ids.insert(participant.user_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int64 min_order = std::numeric_limits<int64>::max();
|
int64 min_order = std::numeric_limits<int64>::max();
|
||||||
for (auto &participant : participants) {
|
for (auto &participant : participants) {
|
||||||
GroupCallParticipant group_call_participant(participant);
|
GroupCallParticipant group_call_participant(participant);
|
||||||
@ -925,14 +1080,44 @@ void GroupCallManager::process_group_call_participants(
|
|||||||
} else {
|
} else {
|
||||||
min_order = real_order;
|
min_order = real_order;
|
||||||
}
|
}
|
||||||
process_group_call_participant(input_group_call_id, GroupCallParticipant(participant));
|
if (is_sync) {
|
||||||
|
old_participant_user_ids.erase(group_call_participant.user_id);
|
||||||
|
}
|
||||||
|
process_group_call_participant(input_group_call_id, std::move(group_call_participant));
|
||||||
|
}
|
||||||
|
if (is_sync) {
|
||||||
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
|
if (participants_it != group_call_participants_.end()) {
|
||||||
|
CHECK(participants_it->second != nullptr);
|
||||||
|
auto &group_participants = participants_it->second->participants;
|
||||||
|
for (auto participant_it = group_participants.begin(); participant_it != group_participants.end();) {
|
||||||
|
auto &participant = *participant_it;
|
||||||
|
if (old_participant_user_ids.count(participant.user_id) == 0) {
|
||||||
|
CHECK(participant.order == 0 || participant.order >= min_order);
|
||||||
|
++participant_it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// not synced user, needs to be deleted
|
||||||
|
if (participant.order != 0) {
|
||||||
|
CHECK(participant.order >= participants_it->second->min_order);
|
||||||
|
participant.order = 0;
|
||||||
|
send_update_group_call_participant(input_group_call_id, participant);
|
||||||
|
}
|
||||||
|
participant_it = group_participants.erase(participant_it);
|
||||||
|
}
|
||||||
|
if (participants_it->second->min_order < min_order) {
|
||||||
|
// if previously known more users, adjust min_order
|
||||||
|
participants_it->second->min_order = min_order;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (is_load) {
|
if (is_load) {
|
||||||
auto participants_it = group_call_participants_.find(input_group_call_id);
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
if (participants_it != group_call_participants_.end()) {
|
if (participants_it != group_call_participants_.end()) {
|
||||||
CHECK(participants_it->second != nullptr);
|
CHECK(participants_it->second != nullptr);
|
||||||
if (participants_it->second->min_order > min_order) {
|
|
||||||
auto old_min_order = participants_it->second->min_order;
|
auto old_min_order = participants_it->second->min_order;
|
||||||
|
if (old_min_order > min_order) {
|
||||||
participants_it->second->min_order = min_order;
|
participants_it->second->min_order = min_order;
|
||||||
|
|
||||||
for (auto &participant : participants_it->second->participants) {
|
for (auto &participant : participants_it->second->participants) {
|
||||||
@ -948,15 +1133,6 @@ void GroupCallManager::process_group_call_participants(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 GroupCallManager::process_group_call_participants_from_updates(
|
|
||||||
InputGroupCallId input_group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants) {
|
|
||||||
int32 diff = 0;
|
|
||||||
for (auto &participant : participants) {
|
|
||||||
diff += process_group_call_participant(input_group_call_id, GroupCallParticipant(participant));
|
|
||||||
}
|
|
||||||
return diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
int GroupCallManager::process_group_call_participant(InputGroupCallId input_group_call_id,
|
int GroupCallManager::process_group_call_participant(InputGroupCallId input_group_call_id,
|
||||||
GroupCallParticipant &&participant) {
|
GroupCallParticipant &&participant) {
|
||||||
if (!participant.is_valid()) {
|
if (!participant.is_valid()) {
|
||||||
@ -967,6 +1143,17 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Process " << participant << " in " << input_group_call_id;
|
||||||
|
|
||||||
|
if (participant.user_id == td_->contacts_manager_->get_my_id()) {
|
||||||
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
|
if (group_call->is_joined && group_call->is_active && group_call->can_self_unmute != participant.can_self_unmute) {
|
||||||
|
group_call->can_self_unmute = participant.can_self_unmute;
|
||||||
|
send_update_group_call(group_call, "process_group_call_participant");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto &participants = group_call_participants_[input_group_call_id];
|
auto &participants = group_call_participants_[input_group_call_id];
|
||||||
if (participants == nullptr) {
|
if (participants == nullptr) {
|
||||||
participants = make_unique<GroupCallParticipants>();
|
participants = make_unique<GroupCallParticipants>();
|
||||||
@ -976,14 +1163,16 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
|
|||||||
auto &old_participant = participants->participants[i];
|
auto &old_participant = participants->participants[i];
|
||||||
if (old_participant.user_id == participant.user_id) {
|
if (old_participant.user_id == participant.user_id) {
|
||||||
if (participant.joined_date == 0) {
|
if (participant.joined_date == 0) {
|
||||||
// removed participant
|
LOG(INFO) << "Remove " << old_participant;
|
||||||
if (old_participant.order != 0) {
|
if (old_participant.order != 0) {
|
||||||
send_update_group_call_participant(input_group_call_id, participant);
|
send_update_group_call_participant(input_group_call_id, participant);
|
||||||
}
|
}
|
||||||
|
remove_recent_group_call_speaker(input_group_call_id, participant.user_id);
|
||||||
participants->participants.erase(participants->participants.begin() + i);
|
participants->participants.erase(participants->participants.begin() + i);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Edit " << old_participant;
|
||||||
if (participant.joined_date < old_participant.joined_date) {
|
if (participant.joined_date < old_participant.joined_date) {
|
||||||
LOG(ERROR) << "Join date of " << participant.user_id << " in " << input_group_call_id << " decreased from "
|
LOG(ERROR) << "Join date of " << participant.user_id << " in " << input_group_call_id << " decreased from "
|
||||||
<< old_participant.joined_date << " to " << participant.joined_date;
|
<< old_participant.joined_date << " to " << participant.joined_date;
|
||||||
@ -1006,18 +1195,24 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
|
|||||||
if (need_update) {
|
if (need_update) {
|
||||||
send_update_group_call_participant(input_group_call_id, old_participant);
|
send_update_group_call_participant(input_group_call_id, old_participant);
|
||||||
}
|
}
|
||||||
|
on_participant_speaking_in_group_call(input_group_call_id, participant);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (participant.joined_date == 0) {
|
if (participant.joined_date == 0) {
|
||||||
// unknown removed participant
|
LOG(INFO) << "Remove unknown " << participant;
|
||||||
|
remove_recent_group_call_speaker(input_group_call_id, participant.user_id);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// unknown added or edited participant
|
|
||||||
int diff = participant.is_just_joined ? 1 : 0;
|
int diff = participant.is_just_joined ? 1 : 0;
|
||||||
|
if (participant.is_just_joined) {
|
||||||
|
LOG(INFO) << "Add new " << participant;
|
||||||
|
} else {
|
||||||
|
LOG(INFO) << "Receive new " << participant;
|
||||||
|
}
|
||||||
auto real_order = participant.get_real_order();
|
auto real_order = participant.get_real_order();
|
||||||
if (real_order >= participants->min_order) {
|
if (real_order >= participants->min_order) {
|
||||||
participant.order = real_order;
|
participant.order = real_order;
|
||||||
@ -1027,6 +1222,7 @@ int GroupCallManager::process_group_call_participant(InputGroupCallId input_grou
|
|||||||
if (participants->participants.back().order != 0) {
|
if (participants->participants.back().order != 0) {
|
||||||
send_update_group_call_participant(input_group_call_id, participants->participants.back());
|
send_update_group_call_participant(input_group_call_id, participants->participants.back());
|
||||||
}
|
}
|
||||||
|
on_participant_speaking_in_group_call(input_group_call_id, participants->participants.back());
|
||||||
return diff;
|
return diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1281,7 +1477,7 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_
|
|||||||
} else {
|
} else {
|
||||||
recursive = true;
|
recursive = true;
|
||||||
}
|
}
|
||||||
UserId user_id = get_group_call_participant_by_source(input_group_call_id, source);
|
UserId user_id = set_group_call_participant_is_speaking_by_source(input_group_call_id, source, is_speaking, date);
|
||||||
if (!user_id.is_valid()) {
|
if (!user_id.is_valid()) {
|
||||||
if (!recursive) {
|
if (!recursive) {
|
||||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, source, is_speaking,
|
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, source, is_speaking,
|
||||||
@ -1299,7 +1495,8 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_
|
|||||||
td_->create_handler<GetGroupCallParticipantQuery>(std::move(query_promise))
|
td_->create_handler<GetGroupCallParticipantQuery>(std::move(query_promise))
|
||||||
->send(input_group_call_id, {}, {source});
|
->send(input_group_call_id, {}, {source});
|
||||||
} else {
|
} else {
|
||||||
LOG(INFO) << "Failed to find participant with source " << source << " in " << group_call_id;
|
LOG(INFO) << "Failed to find participant with source " << source << " in " << group_call_id << " from "
|
||||||
|
<< group_call->dialog_id;
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -1318,8 +1515,6 @@ void GroupCallManager::set_group_call_participant_is_speaking(GroupCallId group_
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO update participant list by speaking actions
|
|
||||||
|
|
||||||
promise.set_value(Unit());
|
promise.set_value(Unit());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1327,9 +1522,22 @@ void GroupCallManager::toggle_group_call_participant_is_muted(GroupCallId group_
|
|||||||
Promise<Unit> &&promise) {
|
Promise<Unit> &&promise) {
|
||||||
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
TRY_RESULT_PROMISE(promise, input_group_call_id, get_input_group_call_id(group_call_id));
|
||||||
|
|
||||||
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
|
if (group_call == nullptr || !group_call->is_inited || !group_call->is_active || !group_call->is_joined) {
|
||||||
|
return promise.set_error(Status::Error(400, "GROUP_CALL_JOIN_MISSING"));
|
||||||
|
}
|
||||||
if (!td_->contacts_manager_->have_input_user(user_id)) {
|
if (!td_->contacts_manager_->have_input_user(user_id)) {
|
||||||
return promise.set_error(Status::Error(400, "Have no access to the user"));
|
return promise.set_error(Status::Error(400, "Have no access to the user"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (user_id != td_->contacts_manager_->get_my_id()) {
|
||||||
|
TRY_STATUS_PROMISE(promise, can_manage_group_calls(group_call->dialog_id));
|
||||||
|
} else {
|
||||||
|
if (!is_muted && !group_call->can_self_unmute) {
|
||||||
|
return promise.set_error(Status::Error(400, "Can't unmute self"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
td_->create_handler<EditGroupCallMemberQuery>(std::move(promise))->send(input_group_call_id, user_id, is_muted);
|
td_->create_handler<EditGroupCallMemberQuery>(std::move(promise))->send(input_group_call_id, user_id, is_muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1368,6 +1576,9 @@ void GroupCallManager::load_group_call_participants(GroupCallId group_call_id, i
|
|||||||
}
|
}
|
||||||
auto *group_call = get_group_call(input_group_call_id);
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
CHECK(group_call != nullptr && group_call->is_inited);
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
|
if (group_call->loaded_all_participants) {
|
||||||
|
return promise.set_value(Unit());
|
||||||
|
}
|
||||||
|
|
||||||
string next_offset;
|
string next_offset;
|
||||||
auto participants_it = group_call_participants_.find(input_group_call_id);
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
@ -1391,6 +1602,7 @@ void GroupCallManager::leave_group_call(GroupCallId group_call_id, Promise<Unit>
|
|||||||
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source,
|
auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, source,
|
||||||
promise = std::move(promise)](Result<Unit> &&result) mutable {
|
promise = std::move(promise)](Result<Unit> &&result) mutable {
|
||||||
if (result.is_ok()) {
|
if (result.is_ok()) {
|
||||||
|
// just in case
|
||||||
send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source);
|
send_closure(actor_id, &GroupCallManager::on_group_call_left, input_group_call_id, source);
|
||||||
}
|
}
|
||||||
promise.set_result(std::move(result));
|
promise.set_result(std::move(result));
|
||||||
@ -1402,13 +1614,20 @@ void GroupCallManager::on_group_call_left(InputGroupCallId input_group_call_id,
|
|||||||
auto *group_call = get_group_call(input_group_call_id);
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
CHECK(group_call != nullptr && group_call->is_inited);
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
if (group_call->is_joined && group_call->source == source) {
|
if (group_call->is_joined && group_call->source == source) {
|
||||||
|
on_group_call_left_impl(group_call);
|
||||||
|
send_update_group_call(group_call, "on_group_call_left");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupCallManager::on_group_call_left_impl(GroupCall *group_call) {
|
||||||
|
CHECK(group_call != nullptr && group_call->is_inited && group_call->is_joined);
|
||||||
group_call->is_joined = false;
|
group_call->is_joined = false;
|
||||||
group_call->is_speaking = false;
|
group_call->is_speaking = false;
|
||||||
|
group_call->can_self_unmute = false;
|
||||||
group_call->source = 0;
|
group_call->source = 0;
|
||||||
send_update_group_call(group_call);
|
group_call->loaded_all_participants = false;
|
||||||
|
group_call->version = -1;
|
||||||
try_clear_group_call_participants(input_group_call_id);
|
try_clear_group_call_participants(get_input_group_call_id(group_call->group_call_id).ok());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCallManager::discard_group_call(GroupCallId group_call_id, Promise<Unit> &&promise) {
|
void GroupCallManager::discard_group_call(GroupCallId group_call_id, Promise<Unit> &&promise) {
|
||||||
@ -1427,7 +1646,7 @@ void GroupCallManager::on_update_group_call(tl_object_ptr<telegram_api::GroupCal
|
|||||||
}
|
}
|
||||||
auto input_group_call_id = update_group_call(group_call_ptr, dialog_id);
|
auto input_group_call_id = update_group_call(group_call_ptr, dialog_id);
|
||||||
if (input_group_call_id.is_valid()) {
|
if (input_group_call_id.is_valid()) {
|
||||||
LOG(INFO) << "Update " << input_group_call_id;
|
LOG(INFO) << "Update " << input_group_call_id << " from " << dialog_id;
|
||||||
} else {
|
} else {
|
||||||
LOG(ERROR) << "Receive invalid " << to_string(group_call_ptr);
|
LOG(ERROR) << "Receive invalid " << to_string(group_call_ptr);
|
||||||
}
|
}
|
||||||
@ -1448,9 +1667,10 @@ void GroupCallManager::try_clear_group_call_participants(InputGroupCallId input_
|
|||||||
|
|
||||||
auto group_call = get_group_call(input_group_call_id);
|
auto group_call = get_group_call(input_group_call_id);
|
||||||
CHECK(group_call != nullptr && group_call->is_inited);
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
|
LOG(INFO) << "Clear participants in " << input_group_call_id << " from " << group_call->dialog_id;
|
||||||
if (group_call->loaded_all_participants) {
|
if (group_call->loaded_all_participants) {
|
||||||
group_call->loaded_all_participants = false;
|
group_call->loaded_all_participants = false;
|
||||||
send_update_group_call(group_call);
|
send_update_group_call(group_call, "try_clear_group_call_participants");
|
||||||
}
|
}
|
||||||
group_call->version = -1;
|
group_call->version = -1;
|
||||||
|
|
||||||
@ -1504,11 +1724,24 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
|
|||||||
auto *group_call = add_group_call(input_group_call_id, dialog_id);
|
auto *group_call = add_group_call(input_group_call_id, dialog_id);
|
||||||
call.group_call_id = group_call->group_call_id;
|
call.group_call_id = group_call->group_call_id;
|
||||||
call.dialog_id = dialog_id.is_valid() ? dialog_id : group_call->dialog_id;
|
call.dialog_id = dialog_id.is_valid() ? dialog_id : group_call->dialog_id;
|
||||||
|
call.can_self_unmute =
|
||||||
|
call.is_active && (!call.mute_new_participants || can_manage_group_calls(call.dialog_id).is_ok());
|
||||||
if (!group_call->dialog_id.is_valid()) {
|
if (!group_call->dialog_id.is_valid()) {
|
||||||
group_call->dialog_id = dialog_id;
|
group_call->dialog_id = dialog_id;
|
||||||
}
|
}
|
||||||
|
LOG(INFO) << "Update " << call.group_call_id << " with " << group_call->participant_count
|
||||||
|
<< " participants and version " << group_call->version;
|
||||||
if (!group_call->is_inited) {
|
if (!group_call->is_inited) {
|
||||||
*group_call = std::move(call);
|
*group_call = std::move(call);
|
||||||
|
if (need_group_call_participants(input_group_call_id)) {
|
||||||
|
// init version
|
||||||
|
group_call->version = call.version;
|
||||||
|
if (process_pending_group_call_participant_updates(input_group_call_id)) {
|
||||||
|
need_update = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
group_call->version = -1;
|
||||||
|
}
|
||||||
need_update = true;
|
need_update = true;
|
||||||
} else {
|
} else {
|
||||||
if (!group_call->is_active) {
|
if (!group_call->is_active) {
|
||||||
@ -1517,9 +1750,6 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
|
|||||||
// always update to an ended call, droping also is_joined and is_speaking flags
|
// always update to an ended call, droping also is_joined and is_speaking flags
|
||||||
*group_call = std::move(call);
|
*group_call = std::move(call);
|
||||||
need_update = true;
|
need_update = true;
|
||||||
if (group_call->dialog_id.is_valid()) {
|
|
||||||
td_->messages_manager_->on_update_dialog_group_call(group_call->dialog_id, false, false);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
auto mute_flags_changed =
|
auto mute_flags_changed =
|
||||||
call.mute_new_participants != group_call->mute_new_participants ||
|
call.mute_new_participants != group_call->mute_new_participants ||
|
||||||
@ -1535,24 +1765,26 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
|
|||||||
on_receive_group_call_version(input_group_call_id, call.version);
|
on_receive_group_call_version(input_group_call_id, call.version);
|
||||||
} else {
|
} else {
|
||||||
if (call.participant_count != group_call->participant_count) {
|
if (call.participant_count != group_call->participant_count) {
|
||||||
|
LOG(INFO) << "Set " << call.group_call_id << " participant count to " << call.participant_count;
|
||||||
group_call->participant_count = call.participant_count;
|
group_call->participant_count = call.participant_count;
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
if (need_group_call_participants(input_group_call_id)) {
|
if (need_group_call_participants(input_group_call_id) && !join_params.empty()) {
|
||||||
// init version
|
LOG(INFO) << "Init " << call.group_call_id << " version to " << call.version;
|
||||||
|
if (group_call->can_self_unmute != call.can_self_unmute) {
|
||||||
|
group_call->can_self_unmute = call.can_self_unmute;
|
||||||
|
need_update = true;
|
||||||
|
}
|
||||||
group_call->version = call.version;
|
group_call->version = call.version;
|
||||||
if (process_pending_group_call_participant_updates(input_group_call_id)) {
|
if (process_pending_group_call_participant_updates(input_group_call_id)) {
|
||||||
need_update = false;
|
need_update = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (group_call->dialog_id.is_valid()) {
|
|
||||||
td_->messages_manager_->on_update_dialog_group_call(group_call->dialog_id, true,
|
|
||||||
group_call->participant_count == 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
update_group_call_dialog(group_call, "update_group_call");
|
||||||
if (!group_call->is_active && group_call_recent_speakers_.erase(group_call->group_call_id) != 0) {
|
if (!group_call->is_active && group_call_recent_speakers_.erase(group_call->group_call_id) != 0) {
|
||||||
need_update = true;
|
need_update = true;
|
||||||
}
|
}
|
||||||
@ -1560,7 +1792,7 @@ InputGroupCallId GroupCallManager::update_group_call(const tl_object_ptr<telegra
|
|||||||
need_update |= on_join_group_call_response(input_group_call_id, std::move(join_params));
|
need_update |= on_join_group_call_response(input_group_call_id, std::move(join_params));
|
||||||
}
|
}
|
||||||
if (need_update) {
|
if (need_update) {
|
||||||
send_update_group_call(group_call);
|
send_update_group_call(group_call, "update_group_call");
|
||||||
}
|
}
|
||||||
try_clear_group_call_participants(input_group_call_id);
|
try_clear_group_call_participants(input_group_call_id);
|
||||||
return input_group_call_id;
|
return input_group_call_id;
|
||||||
@ -1579,6 +1811,9 @@ void GroupCallManager::on_receive_group_call_version(InputGroupCallId input_grou
|
|||||||
if (version <= group_call->version) {
|
if (version <= group_call->version) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (group_call->syncing_participants) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// found a gap
|
// found a gap
|
||||||
auto &group_call_participants = group_call_participants_[input_group_call_id];
|
auto &group_call_participants = group_call_participants_[input_group_call_id];
|
||||||
@ -1589,6 +1824,20 @@ void GroupCallManager::on_receive_group_call_version(InputGroupCallId input_grou
|
|||||||
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
|
sync_participants_timeout_.add_timeout_in(group_call->group_call_id.get(), 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCallManager::on_participant_speaking_in_group_call(InputGroupCallId input_group_call_id,
|
||||||
|
const GroupCallParticipant &participant) {
|
||||||
|
if (participant.active_date < G()->unix_time() - RECENT_SPEAKER_TIMEOUT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto *group_call = get_group_call(input_group_call_id);
|
||||||
|
if (group_call == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
on_user_speaking_in_group_call(group_call->group_call_id, participant.user_id, participant.active_date, true);
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, UserId user_id, int32 date,
|
void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id, UserId user_id, int32 date,
|
||||||
bool recursive) {
|
bool recursive) {
|
||||||
if (G()->close_flag()) {
|
if (G()->close_flag()) {
|
||||||
@ -1665,21 +1914,47 @@ void GroupCallManager::on_user_speaking_in_group_call(GroupCallId group_call_id,
|
|||||||
on_group_call_recent_speakers_updated(group_call, recent_speakers.get());
|
on_group_call_recent_speakers_updated(group_call, recent_speakers.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCallManager::remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, UserId user_id) {
|
||||||
|
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_it = group_call_recent_speakers_.find(group_call->group_call_id);
|
||||||
|
if (recent_speakers_it == group_call_recent_speakers_.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto &recent_speakers = recent_speakers_it->second;
|
||||||
|
CHECK(recent_speakers != nullptr);
|
||||||
|
for (size_t i = 0; i < recent_speakers->users.size(); i++) {
|
||||||
|
if (recent_speakers->users[i].first == user_id) {
|
||||||
|
LOG(INFO) << "Remove " << user_id << " from recent speakers in " << input_group_call_id << " from "
|
||||||
|
<< group_call->dialog_id;
|
||||||
|
recent_speakers->users.erase(recent_speakers->users.begin() + i);
|
||||||
|
on_group_call_recent_speakers_updated(group_call, recent_speakers.get());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCallManager::on_group_call_recent_speakers_updated(const GroupCall *group_call,
|
void GroupCallManager::on_group_call_recent_speakers_updated(const GroupCall *group_call,
|
||||||
GroupCallRecentSpeakers *recent_speakers) {
|
GroupCallRecentSpeakers *recent_speakers) {
|
||||||
if (group_call == nullptr || !group_call->is_inited || recent_speakers->is_changed) {
|
if (group_call == nullptr || !group_call->is_inited || recent_speakers->is_changed) {
|
||||||
LOG(INFO) << "Don't need to send update of recent speakers in " << group_call->group_call_id;
|
LOG(INFO) << "Don't need to send update of recent speakers in " << group_call->group_call_id << " from "
|
||||||
|
<< group_call->dialog_id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
recent_speakers->is_changed = true;
|
recent_speakers->is_changed = true;
|
||||||
|
|
||||||
LOG(INFO) << "Schedule update of recent speakers in " << group_call->group_call_id;
|
LOG(INFO) << "Schedule update of recent speakers in " << group_call->group_call_id << " from "
|
||||||
|
<< group_call->dialog_id;
|
||||||
const double MAX_RECENT_SPEAKER_UPDATE_DELAY = 0.5;
|
const double MAX_RECENT_SPEAKER_UPDATE_DELAY = 0.5;
|
||||||
recent_speaker_update_timeout_.set_timeout_in(group_call->group_call_id.get(), MAX_RECENT_SPEAKER_UPDATE_DELAY);
|
recent_speaker_update_timeout_.set_timeout_in(group_call->group_call_id.get(), MAX_RECENT_SPEAKER_UPDATE_DELAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
UserId GroupCallManager::get_group_call_participant_by_source(InputGroupCallId input_group_call_id, int32 source) {
|
UserId GroupCallManager::set_group_call_participant_is_speaking_by_source(InputGroupCallId input_group_call_id,
|
||||||
|
int32 source, bool is_speaking, int32 date) {
|
||||||
auto participants_it = group_call_participants_.find(input_group_call_id);
|
auto participants_it = group_call_participants_.find(input_group_call_id);
|
||||||
if (participants_it == group_call_participants_.end()) {
|
if (participants_it == group_call_participants_.end()) {
|
||||||
return UserId();
|
return UserId();
|
||||||
@ -1687,12 +1962,35 @@ UserId GroupCallManager::get_group_call_participant_by_source(InputGroupCallId i
|
|||||||
|
|
||||||
for (auto &participant : participants_it->second->participants) {
|
for (auto &participant : participants_it->second->participants) {
|
||||||
if (participant.source == source) {
|
if (participant.source == source) {
|
||||||
|
if (participant.is_speaking != is_speaking) {
|
||||||
|
participant.is_speaking = is_speaking;
|
||||||
|
if (is_speaking) {
|
||||||
|
participant.local_active_date = max(participant.local_active_date, date);
|
||||||
|
}
|
||||||
|
auto real_order = participant.get_real_order();
|
||||||
|
if (real_order >= participants_it->second->min_order) {
|
||||||
|
participant.order = real_order;
|
||||||
|
}
|
||||||
|
if (participant.order != 0) {
|
||||||
|
send_update_group_call_participant(input_group_call_id, participant);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return participant.user_id;
|
return participant.user_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UserId();
|
return UserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCallManager::update_group_call_dialog(const GroupCall *group_call, const char *source) {
|
||||||
|
if (!group_call->dialog_id.is_valid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
td_->messages_manager_->on_update_dialog_group_call(group_call->dialog_id, group_call->is_active,
|
||||||
|
group_call->participant_count == 0, source);
|
||||||
|
}
|
||||||
|
|
||||||
vector<int32> GroupCallManager::get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update) {
|
vector<int32> GroupCallManager::get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update) {
|
||||||
CHECK(group_call != nullptr && group_call->is_inited);
|
CHECK(group_call != nullptr && group_call->is_inited);
|
||||||
|
|
||||||
@ -1704,7 +2002,8 @@ vector<int32> GroupCallManager::get_recent_speaker_user_ids(const GroupCall *gro
|
|||||||
|
|
||||||
auto *recent_speakers = recent_speakers_it->second.get();
|
auto *recent_speakers = recent_speakers_it->second.get();
|
||||||
CHECK(recent_speakers != nullptr);
|
CHECK(recent_speakers != nullptr);
|
||||||
LOG(INFO) << "Found " << recent_speakers->users.size() << " recent speakers in " << group_call->group_call_id;
|
LOG(INFO) << "Found " << recent_speakers->users.size() << " recent speakers in " << group_call->group_call_id
|
||||||
|
<< " from " << group_call->dialog_id;
|
||||||
while (!recent_speakers->users.empty() &&
|
while (!recent_speakers->users.empty() &&
|
||||||
recent_speakers->users.back().second < G()->unix_time() - RECENT_SPEAKER_TIMEOUT) {
|
recent_speakers->users.back().second < G()->unix_time() - RECENT_SPEAKER_TIMEOUT) {
|
||||||
recent_speakers->users.pop_back();
|
recent_speakers->users.pop_back();
|
||||||
@ -1728,7 +2027,7 @@ vector<int32> GroupCallManager::get_recent_speaker_user_ids(const GroupCall *gro
|
|||||||
|
|
||||||
if (!for_update) {
|
if (!for_update) {
|
||||||
// the change must be received through update first
|
// the change must be received through update first
|
||||||
send_update_group_call(group_call);
|
send_update_group_call(group_call, "get_recent_speaker_user_ids");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return recent_speaker_user_ids;
|
return recent_speaker_user_ids;
|
||||||
@ -1740,9 +2039,9 @@ tl_object_ptr<td_api::groupCall> GroupCallManager::get_group_call_object(const G
|
|||||||
CHECK(group_call->is_inited);
|
CHECK(group_call->is_inited);
|
||||||
|
|
||||||
return td_api::make_object<td_api::groupCall>(
|
return td_api::make_object<td_api::groupCall>(
|
||||||
group_call->group_call_id.get(), group_call->is_active, group_call->is_joined, group_call->participant_count,
|
group_call->group_call_id.get(), group_call->is_active, group_call->is_joined, group_call->can_self_unmute,
|
||||||
group_call->loaded_all_participants, std::move(recent_speaker_user_ids), group_call->mute_new_participants,
|
group_call->participant_count, group_call->loaded_all_participants, std::move(recent_speaker_user_ids),
|
||||||
group_call->allowed_change_mute_new_participants, group_call->duration);
|
group_call->mute_new_participants, group_call->allowed_change_mute_new_participants, group_call->duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
tl_object_ptr<td_api::updateGroupCall> GroupCallManager::get_update_group_call_object(
|
tl_object_ptr<td_api::updateGroupCall> GroupCallManager::get_update_group_call_object(
|
||||||
@ -1757,7 +2056,8 @@ tl_object_ptr<td_api::updateGroupCallParticipant> GroupCallManager::get_update_g
|
|||||||
group_call_id.get(), participant.get_group_call_participant_object(td_->contacts_manager_.get()));
|
group_call_id.get(), participant.get_group_call_participant_object(td_->contacts_manager_.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCallManager::send_update_group_call(const GroupCall *group_call) {
|
void GroupCallManager::send_update_group_call(const GroupCall *group_call, const char *source) {
|
||||||
|
LOG(INFO) << "Send update about " << group_call->group_call_id << " from " << source;
|
||||||
send_closure(G()->td(), &Td::send_update,
|
send_closure(G()->td(), &Td::send_update,
|
||||||
get_update_group_call_object(group_call, get_recent_speaker_user_ids(group_call, true)));
|
get_update_group_call_object(group_call, get_recent_speaker_user_ids(group_call, true)));
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,9 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void get_group_call(GroupCallId group_call_id, Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
void get_group_call(GroupCallId group_call_id, Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
||||||
|
|
||||||
|
void reload_group_call(InputGroupCallId input_group_call_id,
|
||||||
|
Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
||||||
|
|
||||||
void join_group_call(GroupCallId group_call_id, td_api::object_ptr<td_api::groupCallPayload> &&payload, int32 source,
|
void join_group_call(GroupCallId group_call_id, td_api::object_ptr<td_api::groupCallPayload> &&payload, int32 source,
|
||||||
bool is_muted, Promise<td_api::object_ptr<td_api::groupCallJoinResponse>> &&promise);
|
bool is_muted, Promise<td_api::object_ptr<td_api::groupCallJoinResponse>> &&promise);
|
||||||
|
|
||||||
@ -109,10 +112,9 @@ class GroupCallManager : public Actor {
|
|||||||
const GroupCall *get_group_call(InputGroupCallId input_group_call_id) const;
|
const GroupCall *get_group_call(InputGroupCallId input_group_call_id) const;
|
||||||
GroupCall *get_group_call(InputGroupCallId input_group_call_id);
|
GroupCall *get_group_call(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise<GroupCallId> &&promise);
|
Status can_manage_group_calls(DialogId dialog_id);
|
||||||
|
|
||||||
void reload_group_call(InputGroupCallId input_group_call_id,
|
void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise<GroupCallId> &&promise);
|
||||||
Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
|
||||||
|
|
||||||
void finish_get_group_call(InputGroupCallId input_group_call_id,
|
void finish_get_group_call(InputGroupCallId input_group_call_id,
|
||||||
Result<tl_object_ptr<telegram_api::phone_groupCall>> &&result);
|
Result<tl_object_ptr<telegram_api::phone_groupCall>> &&result);
|
||||||
@ -123,12 +125,11 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void sync_group_call_participants(InputGroupCallId input_group_call_id);
|
void sync_group_call_participants(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
|
void on_sync_group_call_participants_failed(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
void process_group_call_participants(InputGroupCallId group_call_id,
|
void process_group_call_participants(InputGroupCallId group_call_id,
|
||||||
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
||||||
bool is_load);
|
bool is_load, bool is_sync);
|
||||||
|
|
||||||
int32 process_group_call_participants_from_updates(
|
|
||||||
InputGroupCallId group_call_id, vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants);
|
|
||||||
|
|
||||||
int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant);
|
int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant);
|
||||||
|
|
||||||
@ -138,19 +139,29 @@ class GroupCallManager : public Actor {
|
|||||||
|
|
||||||
void on_group_call_left(InputGroupCallId input_group_call_id, int32 source);
|
void on_group_call_left(InputGroupCallId input_group_call_id, int32 source);
|
||||||
|
|
||||||
|
void on_group_call_left_impl(GroupCall *group_call);
|
||||||
|
|
||||||
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr, DialogId dialog_id);
|
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr, DialogId dialog_id);
|
||||||
|
|
||||||
void on_receive_group_call_version(InputGroupCallId input_group_call_id, int32 version);
|
void on_receive_group_call_version(InputGroupCallId input_group_call_id, int32 version);
|
||||||
|
|
||||||
|
void on_participant_speaking_in_group_call(InputGroupCallId input_group_call_id,
|
||||||
|
const GroupCallParticipant &participant);
|
||||||
|
|
||||||
|
void remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, UserId user_id);
|
||||||
|
|
||||||
void on_group_call_recent_speakers_updated(const GroupCall *group_call, GroupCallRecentSpeakers *recent_speakers);
|
void on_group_call_recent_speakers_updated(const GroupCall *group_call, GroupCallRecentSpeakers *recent_speakers);
|
||||||
|
|
||||||
UserId get_group_call_participant_by_source(InputGroupCallId input_group_call_id, int32 source);
|
UserId set_group_call_participant_is_speaking_by_source(InputGroupCallId input_group_call_id, int32 source,
|
||||||
|
bool is_speaking, int32 date);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
void try_clear_group_call_participants(InputGroupCallId input_group_call_id);
|
void try_clear_group_call_participants(InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
|
void update_group_call_dialog(const GroupCall *group_call, const char *source);
|
||||||
|
|
||||||
vector<int32> get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update);
|
vector<int32> get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update);
|
||||||
|
|
||||||
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,
|
||||||
@ -162,7 +173,7 @@ class GroupCallManager : public Actor {
|
|||||||
tl_object_ptr<td_api::updateGroupCallParticipant> get_update_group_call_participant_object(
|
tl_object_ptr<td_api::updateGroupCallParticipant> get_update_group_call_participant_object(
|
||||||
GroupCallId group_call_id, const GroupCallParticipant &participant);
|
GroupCallId group_call_id, const GroupCallParticipant &participant);
|
||||||
|
|
||||||
void send_update_group_call(const GroupCall *group_call);
|
void send_update_group_call(const GroupCall *group_call, const char *source);
|
||||||
|
|
||||||
void send_update_group_call_participant(GroupCallId group_call_id, const GroupCallParticipant &participant);
|
void send_update_group_call_participant(GroupCallId group_call_id, const GroupCallParticipant &participant);
|
||||||
|
|
||||||
|
@ -8110,6 +8110,7 @@ void MessagesManager::remove_dialog_action_bar(DialogId dialog_id, Promise<Unit>
|
|||||||
|
|
||||||
void MessagesManager::repair_dialog_active_group_call_id(DialogId dialog_id) {
|
void MessagesManager::repair_dialog_active_group_call_id(DialogId dialog_id) {
|
||||||
if (have_input_peer(dialog_id, AccessRights::Read)) {
|
if (have_input_peer(dialog_id, AccessRights::Read)) {
|
||||||
|
LOG(INFO) << "Repair active voice chat ID in " << dialog_id;
|
||||||
create_actor<SleepActor>("RepairChatActiveVoiceChatId", 1.0,
|
create_actor<SleepActor>("RepairChatActiveVoiceChatId", 1.0,
|
||||||
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id](Result<Unit> result) {
|
PromiseCreator::lambda([actor_id = actor_id(this), dialog_id](Result<Unit> result) {
|
||||||
send_closure(actor_id, &MessagesManager::do_repair_dialog_active_group_call_id,
|
send_closure(actor_id, &MessagesManager::do_repair_dialog_active_group_call_id,
|
||||||
@ -10817,6 +10818,22 @@ void MessagesManager::delete_dialog(DialogId dialog_id) {
|
|||||||
close_dialog(d);
|
close_dialog(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MessagesManager::reload_dialog_group_call(DialogId dialog_id) {
|
||||||
|
if (td_->auth_manager_->is_bot()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto d = get_dialog(dialog_id);
|
||||||
|
if (d == nullptr) {
|
||||||
|
// nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->active_group_call_id.is_valid()) {
|
||||||
|
td_->group_call_manager_->reload_group_call(d->active_group_call_id, Auto());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MessagesManager::read_all_dialog_mentions(DialogId dialog_id, Promise<Unit> &&promise) {
|
void MessagesManager::read_all_dialog_mentions(DialogId dialog_id, Promise<Unit> &&promise) {
|
||||||
bool is_bot = td_->auth_manager_->is_bot();
|
bool is_bot = td_->auth_manager_->is_bot();
|
||||||
if (is_bot) {
|
if (is_bot) {
|
||||||
@ -29293,14 +29310,18 @@ void MessagesManager::do_set_dialog_folder_id(Dialog *d, FolderId folder_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MessagesManager::on_update_dialog_group_call(DialogId dialog_id, bool has_active_group_call,
|
void MessagesManager::on_update_dialog_group_call(DialogId dialog_id, bool has_active_group_call,
|
||||||
bool is_group_call_empty) {
|
bool is_group_call_empty, const char *source) {
|
||||||
if (td_->auth_manager_->is_bot()) {
|
if (td_->auth_manager_->is_bot()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LOG(INFO) << "Update voice chat in " << dialog_id << " with has_active_voice_chat = " << has_active_group_call
|
||||||
|
<< " and is_voice_chat_empty = " << is_group_call_empty << " from " << source;
|
||||||
|
|
||||||
CHECK(dialog_id.is_valid());
|
CHECK(dialog_id.is_valid());
|
||||||
Dialog *d = get_dialog(dialog_id); // must not create the Dialog, because is called from on_get_chat
|
Dialog *d = get_dialog(dialog_id); // must not create the Dialog, because is called from on_get_chat
|
||||||
if (d == nullptr) {
|
if (d == nullptr) {
|
||||||
|
LOG(INFO) << "Can't find " << dialog_id;
|
||||||
pending_dialog_group_call_updates_[dialog_id] = {has_active_group_call, is_group_call_empty};
|
pending_dialog_group_call_updates_[dialog_id] = {has_active_group_call, is_group_call_empty};
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -29309,6 +29330,7 @@ void MessagesManager::on_update_dialog_group_call(DialogId dialog_id, bool has_a
|
|||||||
is_group_call_empty = false;
|
is_group_call_empty = false;
|
||||||
}
|
}
|
||||||
if (d->has_active_group_call == has_active_group_call && d->is_group_call_empty == is_group_call_empty) {
|
if (d->has_active_group_call == has_active_group_call && d->is_group_call_empty == is_group_call_empty) {
|
||||||
|
LOG(INFO) << "Nothing changed in " << dialog_id;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +337,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void on_update_dialog_folder_id(DialogId dialog_id, FolderId folder_id);
|
void on_update_dialog_folder_id(DialogId dialog_id, FolderId folder_id);
|
||||||
|
|
||||||
void on_update_dialog_group_call(DialogId dialog_id, bool has_active_group_call, bool is_group_call_empty);
|
void on_update_dialog_group_call(DialogId dialog_id, bool has_active_group_call, bool is_group_call_empty,
|
||||||
|
const char *source);
|
||||||
|
|
||||||
void on_update_dialog_group_call_id(DialogId dialog_id, InputGroupCallId input_group_call_id);
|
void on_update_dialog_group_call_id(DialogId dialog_id, InputGroupCallId input_group_call_id);
|
||||||
|
|
||||||
@ -400,6 +401,8 @@ class MessagesManager : public Actor {
|
|||||||
|
|
||||||
void delete_dialog(DialogId dialog_id);
|
void delete_dialog(DialogId dialog_id);
|
||||||
|
|
||||||
|
void reload_dialog_group_call(DialogId dialog_id);
|
||||||
|
|
||||||
void read_all_dialog_mentions(DialogId dialog_id, Promise<Unit> &&promise);
|
void read_all_dialog_mentions(DialogId dialog_id, Promise<Unit> &&promise);
|
||||||
|
|
||||||
Status add_recently_found_dialog(DialogId dialog_id) TD_WARN_UNUSED_RESULT;
|
Status add_recently_found_dialog(DialogId dialog_id) TD_WARN_UNUSED_RESULT;
|
||||||
|
@ -1500,6 +1500,10 @@ vector<td_api::object_ptr<td_api::closedVectorPath>> StickersManager::get_sticke
|
|||||||
make_point(last_end_control_point_x, last_end_control_point_y), make_point(x, y)));
|
make_point(last_end_control_point_x, last_end_control_point_y), make_point(x, y)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'm':
|
||||||
|
case 'M':
|
||||||
|
pos--;
|
||||||
|
// falltrough
|
||||||
case 'z':
|
case 'z':
|
||||||
case 'Z':
|
case 'Z':
|
||||||
if (x != start_x || y != start_y) {
|
if (x != start_x || y != start_y) {
|
||||||
|
@ -3233,17 +3233,17 @@ void Td::on_get_promo_data(Result<telegram_api::object_ptr<telegram_api::help_Pr
|
|||||||
auto promo_data_ptr = r_promo_data.move_as_ok();
|
auto promo_data_ptr = r_promo_data.move_as_ok();
|
||||||
CHECK(promo_data_ptr != nullptr);
|
CHECK(promo_data_ptr != nullptr);
|
||||||
LOG(DEBUG) << "Receive " << to_string(promo_data_ptr);
|
LOG(DEBUG) << "Receive " << to_string(promo_data_ptr);
|
||||||
int32 expires = 0;
|
int32 expires_at = 0;
|
||||||
switch (promo_data_ptr->get_id()) {
|
switch (promo_data_ptr->get_id()) {
|
||||||
case telegram_api::help_promoDataEmpty::ID: {
|
case telegram_api::help_promoDataEmpty::ID: {
|
||||||
auto promo = telegram_api::move_object_as<telegram_api::help_promoDataEmpty>(promo_data_ptr);
|
auto promo = telegram_api::move_object_as<telegram_api::help_promoDataEmpty>(promo_data_ptr);
|
||||||
expires = promo->expires_;
|
expires_at = promo->expires_;
|
||||||
messages_manager_->remove_sponsored_dialog();
|
messages_manager_->remove_sponsored_dialog();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case telegram_api::help_promoData::ID: {
|
case telegram_api::help_promoData::ID: {
|
||||||
auto promo = telegram_api::move_object_as<telegram_api::help_promoData>(promo_data_ptr);
|
auto promo = telegram_api::move_object_as<telegram_api::help_promoData>(promo_data_ptr);
|
||||||
expires = promo->expires_;
|
expires_at = promo->expires_;
|
||||||
bool is_proxy = (promo->flags_ & telegram_api::help_promoData::PROXY_MASK) != 0;
|
bool is_proxy = (promo->flags_ & telegram_api::help_promoData::PROXY_MASK) != 0;
|
||||||
messages_manager_->on_get_sponsored_dialog(
|
messages_manager_->on_get_sponsored_dialog(
|
||||||
std::move(promo->peer_),
|
std::move(promo->peer_),
|
||||||
@ -3255,23 +3255,11 @@ void Td::on_get_promo_data(Result<telegram_api::object_ptr<telegram_api::help_Pr
|
|||||||
default:
|
default:
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
if (expires != 0) {
|
schedule_get_promo_data(expires_at == 0 ? 0 : expires_at - G()->unix_time());
|
||||||
expires -= G()->unix_time();
|
|
||||||
}
|
|
||||||
schedule_get_promo_data(expires);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Td::schedule_get_promo_data(int32 expires_in) {
|
void Td::schedule_get_promo_data(int32 expires_in) {
|
||||||
if (expires_in < 0) {
|
expires_in = clamp(expires_in, 60, 86400);
|
||||||
LOG(ERROR) << "Receive wrong expires_in: " << expires_in;
|
|
||||||
expires_in = 0;
|
|
||||||
}
|
|
||||||
if (expires_in != 0 && expires_in < 60) {
|
|
||||||
expires_in = 60;
|
|
||||||
}
|
|
||||||
if (expires_in > 86400) {
|
|
||||||
expires_in = 86400;
|
|
||||||
}
|
|
||||||
if (!close_flag_ && auth_manager_->is_authorized() && !auth_manager_->is_bot()) {
|
if (!close_flag_ && auth_manager_->is_authorized() && !auth_manager_->is_bot()) {
|
||||||
LOG(INFO) << "Schedule getPromoData in " << expires_in;
|
LOG(INFO) << "Schedule getPromoData in " << expires_in;
|
||||||
alarm_timeout_.set_timeout_in(PROMO_DATA_ALARM_ID, expires_in);
|
alarm_timeout_.set_timeout_in(PROMO_DATA_ALARM_ID, expires_in);
|
||||||
|
Loading…
Reference in New Issue
Block a user