2020-11-26 11:47:20 +01:00
|
|
|
//
|
|
|
|
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2020
|
|
|
|
//
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
//
|
|
|
|
#pragma once
|
|
|
|
|
2020-12-13 12:52:07 +01:00
|
|
|
#include "td/telegram/DialogId.h"
|
2020-12-03 17:52:50 +01:00
|
|
|
#include "td/telegram/GroupCallId.h"
|
2020-12-11 15:43:23 +01:00
|
|
|
#include "td/telegram/GroupCallParticipant.h"
|
2020-11-26 11:47:20 +01:00
|
|
|
#include "td/telegram/InputGroupCallId.h"
|
|
|
|
#include "td/telegram/td_api.h"
|
|
|
|
#include "td/telegram/telegram_api.h"
|
2020-11-27 13:22:19 +01:00
|
|
|
#include "td/telegram/UserId.h"
|
2020-11-26 11:47:20 +01:00
|
|
|
|
|
|
|
#include "td/actor/actor.h"
|
|
|
|
#include "td/actor/PromiseFuture.h"
|
2020-12-04 15:06:37 +01:00
|
|
|
#include "td/actor/Timeout.h"
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
#include "td/utils/Status.h"
|
|
|
|
|
2020-11-26 11:47:20 +01:00
|
|
|
#include <unordered_map>
|
|
|
|
|
|
|
|
namespace td {
|
|
|
|
|
|
|
|
class Td;
|
|
|
|
|
|
|
|
class GroupCallManager : public Actor {
|
|
|
|
public:
|
|
|
|
GroupCallManager(Td *td, ActorShared<> parent);
|
2020-11-26 16:02:18 +01:00
|
|
|
GroupCallManager(const GroupCallManager &) = delete;
|
|
|
|
GroupCallManager &operator=(const GroupCallManager &) = delete;
|
|
|
|
GroupCallManager(GroupCallManager &&) = delete;
|
|
|
|
GroupCallManager &operator=(GroupCallManager &&) = delete;
|
|
|
|
~GroupCallManager() override;
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-13 12:52:07 +01:00
|
|
|
GroupCallId get_group_call_id(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
2020-12-03 17:52:50 +01:00
|
|
|
|
2020-12-13 13:18:33 +01:00
|
|
|
void create_voice_chat(DialogId dialog_id, Promise<GroupCallId> &&promise);
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
void get_group_call(GroupCallId group_call_id, Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
2020-12-03 00:00:46 +01:00
|
|
|
|
2020-12-16 14:38:06 +01:00
|
|
|
void reload_group_call(InputGroupCallId input_group_call_id,
|
|
|
|
Promise<td_api::object_ptr<td_api::groupCall>> &&promise);
|
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
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);
|
2020-11-26 12:32:29 +01:00
|
|
|
|
2020-12-08 15:51:37 +01:00
|
|
|
void toggle_group_call_mute_new_participants(GroupCallId group_call_id, bool mute_new_participants,
|
|
|
|
Promise<Unit> &&promise);
|
2020-11-26 23:58:36 +01:00
|
|
|
|
2020-12-08 15:51:37 +01:00
|
|
|
void invite_group_call_participants(GroupCallId group_call_id, vector<UserId> &&user_ids, Promise<Unit> &&promise);
|
2020-11-27 13:22:19 +01:00
|
|
|
|
2020-12-08 15:51:37 +01:00
|
|
|
void set_group_call_participant_is_speaking(GroupCallId group_call_id, int32 source, bool is_speaking,
|
2020-12-12 13:31:56 +01:00
|
|
|
Promise<Unit> &&promise, int32 date = 0);
|
2020-12-04 15:06:37 +01:00
|
|
|
|
2020-12-08 15:51:37 +01:00
|
|
|
void toggle_group_call_participant_is_muted(GroupCallId group_call_id, UserId user_id, bool is_muted,
|
|
|
|
Promise<Unit> &&promise);
|
2020-11-27 15:40:29 +01:00
|
|
|
|
2020-12-03 23:56:27 +01:00
|
|
|
void check_group_call_is_joined(GroupCallId group_call_id, Promise<Unit> &&promise);
|
2020-11-27 15:07:12 +01:00
|
|
|
|
2020-12-11 17:39:27 +01:00
|
|
|
void load_group_call_participants(GroupCallId group_call_id, int32 limit, Promise<Unit> &&promise);
|
|
|
|
|
2020-12-03 23:56:27 +01:00
|
|
|
void leave_group_call(GroupCallId group_call_id, Promise<Unit> &&promise);
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
void discard_group_call(GroupCallId group_call_id, Promise<Unit> &&promise);
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-13 12:52:07 +01:00
|
|
|
void on_update_group_call(tl_object_ptr<telegram_api::GroupCall> group_call_ptr, DialogId dialog_id);
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-06 22:38:23 +01:00
|
|
|
void on_user_speaking_in_group_call(GroupCallId group_call_id, UserId user_id, int32 date, bool recursive = false);
|
|
|
|
|
|
|
|
void on_get_group_call_participants(InputGroupCallId input_group_call_id,
|
2020-12-11 17:39:27 +01:00
|
|
|
tl_object_ptr<telegram_api::phone_groupParticipants> &&participants, bool is_load,
|
|
|
|
const string &offset);
|
2020-12-06 08:40:26 +01:00
|
|
|
|
2020-12-11 16:12:07 +01:00
|
|
|
void on_update_group_call_participants(InputGroupCallId input_group_call_id,
|
|
|
|
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
|
|
|
int32 version);
|
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
void process_join_group_call_response(InputGroupCallId input_group_call_id, uint64 generation,
|
2020-11-26 12:32:29 +01:00
|
|
|
tl_object_ptr<telegram_api::Updates> &&updates, Promise<Unit> &&promise);
|
|
|
|
|
2020-11-26 11:47:20 +01:00
|
|
|
private:
|
|
|
|
struct GroupCall;
|
2020-12-11 15:43:23 +01:00
|
|
|
struct GroupCallParticipants;
|
2020-12-06 08:40:26 +01:00
|
|
|
struct GroupCallRecentSpeakers;
|
2020-11-26 15:33:28 +01:00
|
|
|
struct PendingJoinRequest;
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-06 19:18:12 +01:00
|
|
|
static constexpr int32 RECENT_SPEAKER_TIMEOUT = 5 * 60;
|
|
|
|
|
2020-11-26 11:47:20 +01:00
|
|
|
void tear_down() override;
|
|
|
|
|
2020-12-04 15:06:37 +01:00
|
|
|
static void on_pending_send_speaking_action_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int);
|
|
|
|
|
|
|
|
void on_send_speaking_action_timeout(GroupCallId group_call_id);
|
|
|
|
|
2020-12-06 18:07:23 +01:00
|
|
|
static void on_recent_speaker_update_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int);
|
|
|
|
|
|
|
|
void on_recent_speaker_update_timeout(GroupCallId group_call_id);
|
|
|
|
|
2020-12-12 12:10:37 +01:00
|
|
|
static void on_sync_participants_timeout_callback(void *group_call_manager_ptr, int64 group_call_id_int);
|
|
|
|
|
|
|
|
void on_sync_participants_timeout(GroupCallId group_call_id);
|
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
Result<InputGroupCallId> get_input_group_call_id(GroupCallId group_call_id);
|
|
|
|
|
|
|
|
GroupCallId get_next_group_call_id(InputGroupCallId input_group_call_id);
|
|
|
|
|
2020-12-13 12:52:07 +01:00
|
|
|
GroupCall *add_group_call(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
2020-12-03 00:00:46 +01:00
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
const GroupCall *get_group_call(InputGroupCallId input_group_call_id) const;
|
|
|
|
GroupCall *get_group_call(InputGroupCallId input_group_call_id);
|
2020-12-03 00:00:46 +01:00
|
|
|
|
2020-12-17 00:07:05 +01:00
|
|
|
Status can_manage_group_calls(DialogId dialog_id) const;
|
|
|
|
|
|
|
|
bool can_manage_group_call(InputGroupCallId input_group_call_id) const;
|
2020-12-15 16:20:44 +01:00
|
|
|
|
2020-12-13 13:18:33 +01:00
|
|
|
void on_voice_chat_created(DialogId dialog_id, InputGroupCallId input_group_call_id, Promise<GroupCallId> &&promise);
|
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
void finish_get_group_call(InputGroupCallId input_group_call_id,
|
2020-12-03 00:00:46 +01:00
|
|
|
Result<tl_object_ptr<telegram_api::phone_groupCall>> &&result);
|
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
bool need_group_call_participants(InputGroupCallId input_group_call_id) const;
|
|
|
|
|
2020-12-12 13:00:37 +01:00
|
|
|
bool process_pending_group_call_participant_updates(InputGroupCallId input_group_call_id);
|
2020-12-12 12:10:37 +01:00
|
|
|
|
|
|
|
void sync_group_call_participants(InputGroupCallId input_group_call_id);
|
|
|
|
|
2020-12-15 10:41:26 +01:00
|
|
|
void on_sync_group_call_participants_failed(InputGroupCallId input_group_call_id);
|
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
void process_group_call_participants(InputGroupCallId group_call_id,
|
2020-12-11 21:31:46 +01:00
|
|
|
vector<tl_object_ptr<telegram_api::groupCallParticipant>> &&participants,
|
2020-12-15 10:41:26 +01:00
|
|
|
bool is_load, bool is_sync);
|
2020-12-11 21:03:50 +01:00
|
|
|
|
2020-12-17 00:07:05 +01:00
|
|
|
bool update_group_call_participant_can_be_muted(bool can_manage, const GroupCallParticipants *participants,
|
|
|
|
GroupCallParticipant &participant);
|
|
|
|
|
|
|
|
void update_group_call_participants_can_be_muted(InputGroupCallId input_group_call_id, bool can_manage,
|
|
|
|
GroupCallParticipants *participants);
|
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
int process_group_call_participant(InputGroupCallId group_call_id, GroupCallParticipant &&participant);
|
2020-12-06 22:38:23 +01:00
|
|
|
|
2020-12-16 18:30:52 +01:00
|
|
|
void try_load_group_call_administrators(InputGroupCallId input_group_call_id, DialogId dialog_id);
|
|
|
|
|
|
|
|
void finish_load_group_call_administrators(InputGroupCallId input_group_call_id, int64 random_id,
|
|
|
|
Result<Unit> &&result);
|
|
|
|
|
2020-12-06 12:33:15 +01:00
|
|
|
bool on_join_group_call_response(InputGroupCallId input_group_call_id, string json_response);
|
2020-11-26 12:32:29 +01:00
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
void finish_join_group_call(InputGroupCallId input_group_call_id, uint64 generation, Status error);
|
2020-11-26 12:32:29 +01:00
|
|
|
|
2020-12-16 18:30:52 +01:00
|
|
|
GroupCallParticipants *add_group_call_participants(InputGroupCallId input_group_call_id);
|
|
|
|
|
2020-12-17 15:24:07 +01:00
|
|
|
void on_group_call_left(InputGroupCallId input_group_call_id, int32 source, bool need_rejoin);
|
2020-12-03 23:56:27 +01:00
|
|
|
|
2020-12-17 15:24:07 +01:00
|
|
|
void on_group_call_left_impl(GroupCall *group_call, bool need_rejoin);
|
2020-12-15 15:06:11 +01:00
|
|
|
|
2020-12-13 12:52:07 +01:00
|
|
|
InputGroupCallId update_group_call(const tl_object_ptr<telegram_api::GroupCall> &group_call_ptr, DialogId dialog_id);
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-11 16:12:07 +01:00
|
|
|
void on_receive_group_call_version(InputGroupCallId input_group_call_id, int32 version);
|
|
|
|
|
2020-12-15 12:54:47 +01:00
|
|
|
void on_participant_speaking_in_group_call(InputGroupCallId input_group_call_id,
|
|
|
|
const GroupCallParticipant &participant);
|
|
|
|
|
2020-12-15 12:04:06 +01:00
|
|
|
void remove_recent_group_call_speaker(InputGroupCallId input_group_call_id, UserId user_id);
|
|
|
|
|
2020-12-06 18:07:23 +01:00
|
|
|
void on_group_call_recent_speakers_updated(const GroupCall *group_call, GroupCallRecentSpeakers *recent_speakers);
|
2020-12-06 08:40:26 +01:00
|
|
|
|
2020-12-14 23:42:16 +01:00
|
|
|
UserId set_group_call_participant_is_speaking_by_source(InputGroupCallId input_group_call_id, int32 source,
|
|
|
|
bool is_speaking, int32 date);
|
2020-12-07 00:56:13 +01:00
|
|
|
|
2020-11-26 12:32:29 +01:00
|
|
|
static Result<td_api::object_ptr<td_api::groupCallJoinResponse>> get_group_call_join_response_object(
|
|
|
|
string json_response);
|
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
void try_clear_group_call_participants(InputGroupCallId input_group_call_id);
|
|
|
|
|
2020-12-15 17:20:03 +01:00
|
|
|
void update_group_call_dialog(const GroupCall *group_call, const char *source);
|
|
|
|
|
2020-12-06 19:41:56 +01:00
|
|
|
vector<int32> get_recent_speaker_user_ids(const GroupCall *group_call, bool for_update);
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-06 19:41:56 +01:00
|
|
|
tl_object_ptr<td_api::updateGroupCall> get_update_group_call_object(const GroupCall *group_call,
|
|
|
|
vector<int32> recent_speaker_user_ids) const;
|
2020-11-26 11:47:20 +01:00
|
|
|
|
2020-12-06 19:41:56 +01:00
|
|
|
tl_object_ptr<td_api::groupCall> get_group_call_object(const GroupCall *group_call,
|
|
|
|
vector<int32> recent_speaker_user_ids) const;
|
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
tl_object_ptr<td_api::updateGroupCallParticipant> get_update_group_call_participant_object(
|
|
|
|
GroupCallId group_call_id, const GroupCallParticipant &participant);
|
|
|
|
|
2020-12-15 14:18:43 +01:00
|
|
|
void send_update_group_call(const GroupCall *group_call, const char *source);
|
2020-12-06 19:22:55 +01:00
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
void send_update_group_call_participant(GroupCallId group_call_id, const GroupCallParticipant &participant);
|
|
|
|
|
|
|
|
void send_update_group_call_participant(InputGroupCallId input_group_call_id,
|
|
|
|
const GroupCallParticipant &participant);
|
|
|
|
|
2020-11-26 11:47:20 +01:00
|
|
|
Td *td_;
|
|
|
|
ActorShared<> parent_;
|
|
|
|
|
2020-12-03 17:52:50 +01:00
|
|
|
GroupCallId max_group_call_id_;
|
|
|
|
|
|
|
|
vector<InputGroupCallId> input_group_call_ids_;
|
|
|
|
|
2020-11-26 11:47:20 +01:00
|
|
|
std::unordered_map<InputGroupCallId, unique_ptr<GroupCall>, InputGroupCallIdHash> group_calls_;
|
2020-11-26 12:32:29 +01:00
|
|
|
|
2020-12-11 15:43:23 +01:00
|
|
|
std::unordered_map<InputGroupCallId, unique_ptr<GroupCallParticipants>, InputGroupCallIdHash>
|
|
|
|
group_call_participants_;
|
|
|
|
|
2020-12-06 08:40:26 +01:00
|
|
|
std::unordered_map<GroupCallId, unique_ptr<GroupCallRecentSpeakers>, GroupCallIdHash> group_call_recent_speakers_;
|
|
|
|
|
2020-12-03 00:00:46 +01:00
|
|
|
std::unordered_map<InputGroupCallId, vector<Promise<td_api::object_ptr<td_api::groupCall>>>, InputGroupCallIdHash>
|
|
|
|
load_group_call_queries_;
|
|
|
|
|
2020-11-26 15:33:28 +01:00
|
|
|
std::unordered_map<InputGroupCallId, unique_ptr<PendingJoinRequest>, InputGroupCallIdHash> pending_join_requests_;
|
2020-11-26 12:32:29 +01:00
|
|
|
uint64 join_group_request_generation_ = 0;
|
2020-12-04 15:06:37 +01:00
|
|
|
|
|
|
|
MultiTimeout pending_send_speaking_action_timeout_{"PendingSendSpeakingActionTimeout"};
|
2020-12-06 19:41:56 +01:00
|
|
|
MultiTimeout recent_speaker_update_timeout_{"RecentSpeakerUpdateTimeout"};
|
2020-12-12 12:10:37 +01:00
|
|
|
MultiTimeout sync_participants_timeout_{"SyncParticipantsTimeout"};
|
2020-11-26 11:47:20 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace td
|