mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Update API scheme and start invite links.
This commit is contained in:
parent
b58a977029
commit
02ad5f2772
11 changed files with 403 additions and 55 deletions
|
@ -145,6 +145,8 @@ PRIVATE
|
||||||
api/api_global_privacy.h
|
api/api_global_privacy.h
|
||||||
api/api_hash.cpp
|
api/api_hash.cpp
|
||||||
api/api_hash.h
|
api/api_hash.h
|
||||||
|
api/api_invite_links.cpp
|
||||||
|
api/api_invite_links.h
|
||||||
api/api_media.cpp
|
api/api_media.cpp
|
||||||
api/api_media.h
|
api/api_media.h
|
||||||
api/api_self_destruct.cpp
|
api/api_self_destruct.cpp
|
||||||
|
|
|
@ -932,6 +932,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_manage_peer_exceptions" = "Exceptions";
|
"lng_manage_peer_exceptions" = "Exceptions";
|
||||||
"lng_manage_peer_removed_users" = "Removed users";
|
"lng_manage_peer_removed_users" = "Removed users";
|
||||||
"lng_manage_peer_permissions" = "Permissions";
|
"lng_manage_peer_permissions" = "Permissions";
|
||||||
|
"lng_manage_peer_invite_links" = "Invite links";
|
||||||
|
|
||||||
|
|
||||||
"lng_manage_peer_group_type" = "Group type";
|
"lng_manage_peer_group_type" = "Group type";
|
||||||
"lng_manage_peer_channel_type" = "Channel type";
|
"lng_manage_peer_channel_type" = "Channel type";
|
||||||
|
|
|
@ -535,7 +535,7 @@ auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;
|
||||||
|
|
||||||
receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;
|
receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;
|
||||||
|
|
||||||
chatInviteExported#a9a847ea flags:# revoked:flags.0?true link:string admin_id:int date:int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int = ExportedChatInvite;
|
chatInviteExported#a9a847ea flags:# revoked:flags.0?true expired:flags.4?true permanent:flags.5?true link:string admin_id:int date:int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int = ExportedChatInvite;
|
||||||
|
|
||||||
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
|
chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
|
||||||
chatInvite#dfc2f58e flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:Photo participants_count:int participants:flags.4?Vector<User> = ChatInvite;
|
chatInvite#dfc2f58e flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true title:string photo:Photo participants_count:int participants:flags.4?Vector<User> = ChatInvite;
|
||||||
|
@ -1210,7 +1210,7 @@ chatInviteImporter#1e3e6680 user_id:int date:int = ChatInviteImporter;
|
||||||
|
|
||||||
messages.exportedChatInvites#bdc62dcc count:int invites:Vector<ExportedChatInvite> users:Vector<User> = messages.ExportedChatInvites;
|
messages.exportedChatInvites#bdc62dcc count:int invites:Vector<ExportedChatInvite> users:Vector<User> = messages.ExportedChatInvites;
|
||||||
|
|
||||||
messages.exportedChatInvite#97c5e3a9 invite:ExportedChatInvite recent_importers:Vector<int> users:Vector<User> = messages.ExportedChatInvite;
|
messages.exportedChatInvite#1871be50 invite:ExportedChatInvite users:Vector<User> = messages.ExportedChatInvite;
|
||||||
|
|
||||||
messages.chatInviteImporters#81b6b00a count:int importers:Vector<ChatInviteImporter> users:Vector<User> = messages.ChatInviteImporters;
|
messages.chatInviteImporters#81b6b00a count:int importers:Vector<ChatInviteImporter> users:Vector<User> = messages.ChatInviteImporters;
|
||||||
|
|
||||||
|
@ -1373,7 +1373,7 @@ messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages
|
||||||
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
messages.getStickers#43d4f2c emoticon:string hash:int = messages.Stickers;
|
||||||
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
messages.getAllStickers#1c9618b1 hash:int = messages.AllStickers;
|
||||||
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
|
||||||
messages.exportChatInvite#14b9bcd7 flags:# peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int = ExportedChatInvite;
|
messages.exportChatInvite#14b9bcd7 flags:# legacy_revoke_permanent:flags.2?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int = ExportedChatInvite;
|
||||||
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
|
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
|
||||||
messages.importChatInvite#6c50051c hash:string = Updates;
|
messages.importChatInvite#6c50051c hash:string = Updates;
|
||||||
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
|
messages.getStickerSet#2619a90e stickerset:InputStickerSet = messages.StickerSet;
|
||||||
|
@ -1463,9 +1463,8 @@ messages.getReplies#24b581ba peer:InputPeer msg_id:int offset_id:int offset_date
|
||||||
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
|
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
|
||||||
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
|
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
|
||||||
messages.unpinAllMessages#f025bc8b peer:InputPeer = messages.AffectedHistory;
|
messages.unpinAllMessages#f025bc8b peer:InputPeer = messages.AffectedHistory;
|
||||||
messages.getExportedChatInvites#6d9cae03 flags:# expired:flags.1?true peer:InputPeer admin_id:flags.0?InputUser offset_link:flags.2?string limit:int = messages.ExportedChatInvites;
|
messages.getExportedChatInvites#6d9cae03 flags:# peer:InputPeer admin_id:flags.0?InputUser offset_link:flags.2?string limit:int = messages.ExportedChatInvites;
|
||||||
messages.editExportedChatInvite#2e4ffbe flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int = messages.ExportedChatInvite;
|
messages.editExportedChatInvite#2e4ffbe flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int = messages.ExportedChatInvite;
|
||||||
messages.getExportedChatInvite#73746f5c peer:InputPeer link:string = messages.ExportedChatInvite;
|
|
||||||
messages.getChatInviteImporters#26fb7289 peer:InputPeer link:string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
|
messages.getChatInviteImporters#26fb7289 peer:InputPeer link:string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
|
||||||
|
|
||||||
updates.getState#edd4882a = updates.State;
|
updates.getState#edd4882a = updates.State;
|
||||||
|
|
206
Telegram/SourceFiles/api/api_invite_links.cpp
Normal file
206
Telegram/SourceFiles/api/api_invite_links.cpp
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "api/api_invite_links.h"
|
||||||
|
|
||||||
|
#include "data/data_peer.h"
|
||||||
|
#include "data/data_chat.h"
|
||||||
|
#include "data/data_channel.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_changes.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
|
||||||
|
namespace Api {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kFirstPage = 10;
|
||||||
|
constexpr auto kPerPage = 50;
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
InviteLinks::InviteLinks(not_null<ApiWrap*> api) : _api(api) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void InviteLinks::create(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
TimeId expireDate,
|
||||||
|
int usageLimit) {
|
||||||
|
if (_createRequests.contains(peer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Flag = MTPmessages_ExportChatInvite::Flag;
|
||||||
|
const auto requestId = _api->request(MTPmessages_ExportChatInvite(
|
||||||
|
MTP_flags((expireDate ? Flag::f_expire_date : Flag(0))
|
||||||
|
| (usageLimit ? Flag::f_usage_limit : Flag(0))),
|
||||||
|
peer->input,
|
||||||
|
MTP_int(expireDate),
|
||||||
|
MTP_int(usageLimit)
|
||||||
|
)).done([=](const MTPExportedChatInvite &result) {
|
||||||
|
_createRequests.erase(peer);
|
||||||
|
const auto link = (result.type() == mtpc_chatInviteExported)
|
||||||
|
? qs(result.c_chatInviteExported().vlink())
|
||||||
|
: QString();
|
||||||
|
if (!expireDate && !usageLimit) {
|
||||||
|
editPermanentLink(peer, QString(), link);
|
||||||
|
}
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_createRequests.erase(peer);
|
||||||
|
}).send();
|
||||||
|
_createRequests.emplace(peer, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InviteLinks::edit(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const QString &link,
|
||||||
|
TimeId expireDate,
|
||||||
|
int usageLimit) {
|
||||||
|
const auto key = EditKey{ peer, link };
|
||||||
|
if (_editRequests.contains(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Flag = MTPmessages_EditExportedChatInvite::Flag;
|
||||||
|
const auto requestId = _api->request(MTPmessages_EditExportedChatInvite(
|
||||||
|
MTP_flags((expireDate ? Flag::f_expire_date : Flag(0))
|
||||||
|
| (usageLimit ? Flag::f_usage_limit : Flag(0))),
|
||||||
|
peer->input,
|
||||||
|
MTP_string(link),
|
||||||
|
MTP_int(expireDate),
|
||||||
|
MTP_int(usageLimit)
|
||||||
|
)).done([=](const MTPmessages_ExportedChatInvite &result) {
|
||||||
|
_editRequests.erase(key);
|
||||||
|
result.match([&](const MTPDmessages_exportedChatInvite &data) {
|
||||||
|
_api->session().data().processUsers(data.vusers());
|
||||||
|
const auto &invite = data.vinvite();
|
||||||
|
const auto link = (invite.type() == mtpc_chatInviteExported)
|
||||||
|
? qs(invite.c_chatInviteExported().vlink())
|
||||||
|
: QString();
|
||||||
|
// #TODO links
|
||||||
|
});
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_editRequests.erase(key);
|
||||||
|
}).send();
|
||||||
|
_editRequests.emplace(key, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InviteLinks::revoke(not_null<PeerData*> peer, const QString &link) {
|
||||||
|
const auto key = EditKey{ peer, link };
|
||||||
|
if (_editRequests.contains(key)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto requestId = _api->request(MTPmessages_EditExportedChatInvite(
|
||||||
|
MTP_flags(MTPmessages_EditExportedChatInvite::Flag::f_revoked),
|
||||||
|
peer->input,
|
||||||
|
MTP_string(link),
|
||||||
|
MTPint(), // expire_date
|
||||||
|
MTPint() // usage_limit
|
||||||
|
)).done([=](const MTPmessages_ExportedChatInvite &result) {
|
||||||
|
_editRequests.erase(key);
|
||||||
|
result.match([&](const MTPDmessages_exportedChatInvite &data) {
|
||||||
|
_api->session().data().processUsers(data.vusers());
|
||||||
|
const auto &invite = data.vinvite();
|
||||||
|
const auto link = (invite.type() == mtpc_chatInviteExported)
|
||||||
|
? qs(invite.c_chatInviteExported().vlink())
|
||||||
|
: QString();
|
||||||
|
editPermanentLink(peer, key.link, link);
|
||||||
|
});
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_editRequests.erase(key);
|
||||||
|
}).send();
|
||||||
|
_editRequests.emplace(key, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InviteLinks::requestLinks(not_null<PeerData*> peer) {
|
||||||
|
if (_firstSliceRequests.contains(peer)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto requestId = _api->request(MTPmessages_GetExportedChatInvites(
|
||||||
|
MTP_flags(0),
|
||||||
|
peer->input,
|
||||||
|
MTPInputUser(), // admin_id
|
||||||
|
MTPstring(), // offset_link
|
||||||
|
MTP_int(kFirstPage)
|
||||||
|
)).done([=](const MTPmessages_ExportedChatInvites &result) {
|
||||||
|
_firstSliceRequests.remove(peer);
|
||||||
|
_firstSlices.emplace_or_assign(peer, parseSlice(peer, result));
|
||||||
|
peer->session().changes().peerUpdated(
|
||||||
|
peer,
|
||||||
|
Data::PeerUpdate::Flag::InviteLink);
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
_firstSliceRequests.remove(peer);
|
||||||
|
}).send();
|
||||||
|
_firstSliceRequests.emplace(peer, requestId);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto InviteLinks::links(not_null<PeerData*> peer) const -> Links {
|
||||||
|
const auto i = _firstSlices.find(peer);
|
||||||
|
return (i != end(_firstSlices)) ? i->second : Links();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto InviteLinks::parseSlice(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const MTPmessages_ExportedChatInvites &slice) const -> Links {
|
||||||
|
auto result = Links();
|
||||||
|
slice.match([&](const MTPDmessages_exportedChatInvites &data) {
|
||||||
|
auto &owner = peer->session().data();
|
||||||
|
owner.processUsers(data.vusers());
|
||||||
|
result.count = data.vcount().v;
|
||||||
|
for (const auto &invite : data.vinvites().v) {
|
||||||
|
invite.match([&](const MTPDchatInviteExported &data) {
|
||||||
|
result.links.push_back({
|
||||||
|
.link = qs(data.vlink()),
|
||||||
|
.admin = owner.user(data.vadmin_id().v),
|
||||||
|
.date = data.vdate().v,
|
||||||
|
.expireDate = data.vexpire_date().value_or_empty(),
|
||||||
|
.usageLimit = data.vusage_limit().value_or_empty(),
|
||||||
|
.usage = data.vusage().value_or_empty(),
|
||||||
|
.revoked = data.is_revoked(),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InviteLinks::requestMoreLinks(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const QString &last,
|
||||||
|
Fn<void(Links)> done) {
|
||||||
|
_api->request(MTPmessages_GetExportedChatInvites(
|
||||||
|
MTP_flags(MTPmessages_GetExportedChatInvites::Flag::f_offset_link),
|
||||||
|
peer->input,
|
||||||
|
MTPInputUser(), // admin_id,
|
||||||
|
MTP_string(last),
|
||||||
|
MTP_int(kPerPage)
|
||||||
|
)).done([=](const MTPmessages_ExportedChatInvites &result) {
|
||||||
|
done(parseSlice(peer, result));
|
||||||
|
}).fail([=](const RPCError &error) {
|
||||||
|
done(Links());
|
||||||
|
}).send();
|
||||||
|
}
|
||||||
|
|
||||||
|
void InviteLinks::editPermanentLink(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const QString &from,
|
||||||
|
const QString &to) {
|
||||||
|
if (const auto chat = peer->asChat()) {
|
||||||
|
if (chat->inviteLink() == from) {
|
||||||
|
chat->setInviteLink(to);
|
||||||
|
}
|
||||||
|
} else if (const auto channel = peer->asChannel()) {
|
||||||
|
if (channel->inviteLink() == from) {
|
||||||
|
channel->setInviteLink(to);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Unexpected("Peer in InviteLinks::editMainLink.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Api
|
85
Telegram/SourceFiles/api/api_invite_links.h
Normal file
85
Telegram/SourceFiles/api/api_invite_links.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class ApiWrap;
|
||||||
|
|
||||||
|
namespace Api {
|
||||||
|
|
||||||
|
struct InviteLink {
|
||||||
|
QString link;
|
||||||
|
not_null<UserData*> admin;
|
||||||
|
TimeId date;
|
||||||
|
TimeId expireDate = 0;
|
||||||
|
int usageLimit = 0;
|
||||||
|
int usage = 0;
|
||||||
|
bool revoked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PeerInviteLinks {
|
||||||
|
std::vector<InviteLink> links;
|
||||||
|
int count = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class InviteLinks final {
|
||||||
|
public:
|
||||||
|
explicit InviteLinks(not_null<ApiWrap*> api);
|
||||||
|
|
||||||
|
using Link = InviteLink;
|
||||||
|
using Links = PeerInviteLinks;
|
||||||
|
|
||||||
|
void create(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
TimeId expireDate = 0,
|
||||||
|
int usageLimit = 0);
|
||||||
|
void edit(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const QString &link,
|
||||||
|
TimeId expireDate,
|
||||||
|
int usageLimit);
|
||||||
|
void revoke(not_null<PeerData*> peer, const QString &link);
|
||||||
|
|
||||||
|
void requestLinks(not_null<PeerData*> peer);
|
||||||
|
[[nodiscard]] Links links(not_null<PeerData*> peer) const;
|
||||||
|
|
||||||
|
void requestMoreLinks(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const QString &last,
|
||||||
|
Fn<void(Links)> done);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct EditKey {
|
||||||
|
not_null<PeerData*> peer;
|
||||||
|
QString link;
|
||||||
|
|
||||||
|
friend inline bool operator<(const EditKey &a, const EditKey &b) {
|
||||||
|
return (a.peer == b.peer)
|
||||||
|
? (a.link < b.link)
|
||||||
|
: (a.peer < b.peer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void editPermanentLink(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const QString &from,
|
||||||
|
const QString &to);
|
||||||
|
[[nodiscard]] Links parseSlice(
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
const MTPmessages_ExportedChatInvites &slice) const;
|
||||||
|
|
||||||
|
const not_null<ApiWrap*> _api;
|
||||||
|
|
||||||
|
base::flat_map<not_null<PeerData*>, Links> _firstSlices;
|
||||||
|
base::flat_map<not_null<PeerData*>, mtpRequestId> _firstSliceRequests;
|
||||||
|
|
||||||
|
base::flat_map<not_null<PeerData*>, mtpRequestId> _createRequests;
|
||||||
|
base::flat_map<EditKey, mtpRequestId> _editRequests;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Api
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "api/api_authorizations.h"
|
#include "api/api_authorizations.h"
|
||||||
#include "api/api_attached_stickers.h"
|
#include "api/api_attached_stickers.h"
|
||||||
#include "api/api_hash.h"
|
#include "api/api_hash.h"
|
||||||
|
#include "api/api_invite_links.h"
|
||||||
#include "api/api_media.h"
|
#include "api/api_media.h"
|
||||||
#include "api/api_sending.h"
|
#include "api/api_sending.h"
|
||||||
#include "api/api_text_entities.h"
|
#include "api/api_text_entities.h"
|
||||||
|
@ -194,7 +195,8 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session)
|
||||||
, _attachedStickers(std::make_unique<Api::AttachedStickers>(this))
|
, _attachedStickers(std::make_unique<Api::AttachedStickers>(this))
|
||||||
, _selfDestruct(std::make_unique<Api::SelfDestruct>(this))
|
, _selfDestruct(std::make_unique<Api::SelfDestruct>(this))
|
||||||
, _sensitiveContent(std::make_unique<Api::SensitiveContent>(this))
|
, _sensitiveContent(std::make_unique<Api::SensitiveContent>(this))
|
||||||
, _globalPrivacy(std::make_unique<Api::GlobalPrivacy>(this)) {
|
, _globalPrivacy(std::make_unique<Api::GlobalPrivacy>(this))
|
||||||
|
, _inviteLinks(std::make_unique<Api::InviteLinks>(this)) {
|
||||||
crl::on_main(session, [=] {
|
crl::on_main(session, [=] {
|
||||||
// You can't use _session->lifetime() in the constructor,
|
// You can't use _session->lifetime() in the constructor,
|
||||||
// only queued, because it is not constructed yet.
|
// only queued, because it is not constructed yet.
|
||||||
|
@ -2120,36 +2122,6 @@ void ApiWrap::unblockPeer(not_null<PeerData*> peer, Fn<void()> onDone) {
|
||||||
_blockRequests.emplace(peer, requestId);
|
_blockRequests.emplace(peer, requestId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApiWrap::exportInviteLink(not_null<PeerData*> peer) {
|
|
||||||
if (_exportInviteRequests.find(peer) != end(_exportInviteRequests)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto requestId = [&] {
|
|
||||||
return request(MTPmessages_ExportChatInvite(
|
|
||||||
MTP_flags(0),
|
|
||||||
peer->input,
|
|
||||||
MTPint(), // expire_date
|
|
||||||
MTPint() // usage_limit
|
|
||||||
)).done([=](const MTPExportedChatInvite &result) {
|
|
||||||
_exportInviteRequests.erase(peer);
|
|
||||||
const auto link = (result.type() == mtpc_chatInviteExported)
|
|
||||||
? qs(result.c_chatInviteExported().vlink())
|
|
||||||
: QString();
|
|
||||||
if (const auto chat = peer->asChat()) {
|
|
||||||
chat->setInviteLink(link);
|
|
||||||
} else if (const auto channel = peer->asChannel()) {
|
|
||||||
channel->setInviteLink(link);
|
|
||||||
} else {
|
|
||||||
Unexpected("Peer in ApiWrap::exportInviteLink.");
|
|
||||||
}
|
|
||||||
}).fail([=](const RPCError &error) {
|
|
||||||
_exportInviteRequests.erase(peer);
|
|
||||||
}).send();
|
|
||||||
}();
|
|
||||||
_exportInviteRequests.emplace(peer, requestId);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ApiWrap::requestNotifySettings(const MTPInputNotifyPeer &peer) {
|
void ApiWrap::requestNotifySettings(const MTPInputNotifyPeer &peer) {
|
||||||
const auto key = [&] {
|
const auto key = [&] {
|
||||||
switch (peer.type()) {
|
switch (peer.type()) {
|
||||||
|
@ -5243,6 +5215,10 @@ Api::GlobalPrivacy &ApiWrap::globalPrivacy() {
|
||||||
return *_globalPrivacy;
|
return *_globalPrivacy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Api::InviteLinks &ApiWrap::inviteLinks() {
|
||||||
|
return *_inviteLinks;
|
||||||
|
}
|
||||||
|
|
||||||
void ApiWrap::createPoll(
|
void ApiWrap::createPoll(
|
||||||
const PollData &data,
|
const PollData &data,
|
||||||
const SendAction &action,
|
const SendAction &action,
|
||||||
|
|
|
@ -60,6 +60,7 @@ class AttachedStickers;
|
||||||
class SelfDestruct;
|
class SelfDestruct;
|
||||||
class SensitiveContent;
|
class SensitiveContent;
|
||||||
class GlobalPrivacy;
|
class GlobalPrivacy;
|
||||||
|
class InviteLinks;
|
||||||
|
|
||||||
namespace details {
|
namespace details {
|
||||||
|
|
||||||
|
@ -289,7 +290,6 @@ public:
|
||||||
void blockPeer(not_null<PeerData*> peer);
|
void blockPeer(not_null<PeerData*> peer);
|
||||||
void unblockPeer(not_null<PeerData*> peer, Fn<void()> onDone = nullptr);
|
void unblockPeer(not_null<PeerData*> peer, Fn<void()> onDone = nullptr);
|
||||||
|
|
||||||
void exportInviteLink(not_null<PeerData*> peer);
|
|
||||||
void requestNotifySettings(const MTPInputNotifyPeer &peer);
|
void requestNotifySettings(const MTPInputNotifyPeer &peer);
|
||||||
void updateNotifySettingsDelayed(not_null<const PeerData*> peer);
|
void updateNotifySettingsDelayed(not_null<const PeerData*> peer);
|
||||||
void saveDraftToCloudDelayed(not_null<History*> history);
|
void saveDraftToCloudDelayed(not_null<History*> history);
|
||||||
|
@ -464,6 +464,7 @@ public:
|
||||||
[[nodiscard]] Api::SelfDestruct &selfDestruct();
|
[[nodiscard]] Api::SelfDestruct &selfDestruct();
|
||||||
[[nodiscard]] Api::SensitiveContent &sensitiveContent();
|
[[nodiscard]] Api::SensitiveContent &sensitiveContent();
|
||||||
[[nodiscard]] Api::GlobalPrivacy &globalPrivacy();
|
[[nodiscard]] Api::GlobalPrivacy &globalPrivacy();
|
||||||
|
[[nodiscard]] Api::InviteLinks &inviteLinks();
|
||||||
|
|
||||||
void createPoll(
|
void createPoll(
|
||||||
const PollData &data,
|
const PollData &data,
|
||||||
|
@ -701,7 +702,6 @@ private:
|
||||||
|
|
||||||
QMap<ChannelData*, mtpRequestId> _channelAmInRequests;
|
QMap<ChannelData*, mtpRequestId> _channelAmInRequests;
|
||||||
base::flat_map<not_null<PeerData*>, mtpRequestId> _blockRequests;
|
base::flat_map<not_null<PeerData*>, mtpRequestId> _blockRequests;
|
||||||
base::flat_map<not_null<PeerData*>, mtpRequestId> _exportInviteRequests;
|
|
||||||
base::flat_map<PeerId, mtpRequestId> _notifySettingRequests;
|
base::flat_map<PeerId, mtpRequestId> _notifySettingRequests;
|
||||||
base::flat_map<not_null<History*>, mtpRequestId> _draftsSaveRequestIds;
|
base::flat_map<not_null<History*>, mtpRequestId> _draftsSaveRequestIds;
|
||||||
base::Timer _draftsSaveTimer;
|
base::Timer _draftsSaveTimer;
|
||||||
|
@ -828,6 +828,7 @@ private:
|
||||||
const std::unique_ptr<Api::SelfDestruct> _selfDestruct;
|
const std::unique_ptr<Api::SelfDestruct> _selfDestruct;
|
||||||
const std::unique_ptr<Api::SensitiveContent> _sensitiveContent;
|
const std::unique_ptr<Api::SensitiveContent> _sensitiveContent;
|
||||||
const std::unique_ptr<Api::GlobalPrivacy> _globalPrivacy;
|
const std::unique_ptr<Api::GlobalPrivacy> _globalPrivacy;
|
||||||
|
const std::unique_ptr<Api::InviteLinks> _inviteLinks;
|
||||||
|
|
||||||
base::flat_map<FullMsgId, mtpRequestId> _pollVotesRequestIds;
|
base::flat_map<FullMsgId, mtpRequestId> _pollVotesRequestIds;
|
||||||
base::flat_map<FullMsgId, mtpRequestId> _pollCloseRequestIds;
|
base::flat_map<FullMsgId, mtpRequestId> _pollCloseRequestIds;
|
||||||
|
|
|
@ -40,6 +40,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "api/api_invite_links.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
|
@ -942,7 +943,7 @@ void SetupChannelBox::mouseMoveEvent(QMouseEvent *e) {
|
||||||
void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
|
void SetupChannelBox::mousePressEvent(QMouseEvent *e) {
|
||||||
if (_linkOver) {
|
if (_linkOver) {
|
||||||
if (_channel->inviteLink().isEmpty()) {
|
if (_channel->inviteLink().isEmpty()) {
|
||||||
_channel->session().api().exportInviteLink(_channel);
|
_channel->session().api().inviteLinks().create(_channel);
|
||||||
} else {
|
} else {
|
||||||
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
||||||
Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now));
|
Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now));
|
||||||
|
|
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "api/api_invite_links.h"
|
||||||
#include "history/history.h"
|
#include "history/history.h"
|
||||||
#include "history/history_item.h"
|
#include "history/history_item.h"
|
||||||
#include "ui/widgets/checkbox.h"
|
#include "ui/widgets/checkbox.h"
|
||||||
|
@ -407,7 +408,7 @@ void MaxInviteBox::mousePressEvent(QMouseEvent *e) {
|
||||||
mouseMoveEvent(e);
|
mouseMoveEvent(e);
|
||||||
if (_linkOver) {
|
if (_linkOver) {
|
||||||
if (_channel->inviteLink().isEmpty()) {
|
if (_channel->inviteLink().isEmpty()) {
|
||||||
_channel->session().api().exportInviteLink(_channel);
|
_channel->session().api().inviteLinks().create(_channel);
|
||||||
} else {
|
} else {
|
||||||
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
QGuiApplication::clipboard()->setText(_channel->inviteLink());
|
||||||
Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now));
|
Ui::Toast::Show(tr::lng_create_channel_link_copied(tr::now));
|
||||||
|
|
|
@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "data/data_chat.h"
|
#include "data/data_chat.h"
|
||||||
#include "data/data_peer.h"
|
#include "data/data_peer.h"
|
||||||
#include "data/data_session.h"
|
#include "data/data_session.h"
|
||||||
|
#include "data/data_changes.h"
|
||||||
#include "history/admin_log/history_admin_log_section.h"
|
#include "history/admin_log/history_admin_log_section.h"
|
||||||
#include "info/profile/info_profile_values.h"
|
#include "info/profile/info_profile_values.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
|
@ -45,6 +46,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "info/profile/info_profile_icon.h"
|
#include "info/profile/info_profile_icon.h"
|
||||||
#include "app.h"
|
#include "app.h"
|
||||||
|
#include "apiwrap.h"
|
||||||
|
#include "api/api_invite_links.h"
|
||||||
#include "facades.h"
|
#include "facades.h"
|
||||||
#include "styles/style_layers.h"
|
#include "styles/style_layers.h"
|
||||||
#include "styles/style_boxes.h"
|
#include "styles/style_boxes.h"
|
||||||
|
@ -236,6 +239,49 @@ void ShowEditPermissions(
|
||||||
}, box->lifetime());
|
}, box->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShowEditInviteLinks(
|
||||||
|
not_null<Window::SessionNavigation*> navigation,
|
||||||
|
not_null<PeerData*> peer) {
|
||||||
|
const auto box = Ui::show(
|
||||||
|
Box<EditPeerPermissionsBox>(navigation, peer),
|
||||||
|
Ui::LayerOption::KeepOther);
|
||||||
|
const auto saving = box->lifetime().make_state<int>(0);
|
||||||
|
const auto save = [=](
|
||||||
|
not_null<PeerData*> peer,
|
||||||
|
EditPeerPermissionsBox::Result result) {
|
||||||
|
Expects(result.slowmodeSeconds == 0 || peer->isChannel());
|
||||||
|
|
||||||
|
const auto close = crl::guard(box, [=] { box->closeBox(); });
|
||||||
|
SaveDefaultRestrictions(
|
||||||
|
peer,
|
||||||
|
MTP_chatBannedRights(MTP_flags(result.rights), MTP_int(0)),
|
||||||
|
close);
|
||||||
|
if (const auto channel = peer->asChannel()) {
|
||||||
|
SaveSlowmodeSeconds(channel, result.slowmodeSeconds, close);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
box->saveEvents(
|
||||||
|
) | rpl::start_with_next([=](EditPeerPermissionsBox::Result result) {
|
||||||
|
if (*saving) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*saving = true;
|
||||||
|
|
||||||
|
const auto saveFor = peer->migrateToOrMe();
|
||||||
|
const auto chat = saveFor->asChat();
|
||||||
|
if (!result.slowmodeSeconds || !chat) {
|
||||||
|
save(saveFor, result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto api = &peer->session().api();
|
||||||
|
api->migrateChat(chat, [=](not_null<ChannelData*> channel) {
|
||||||
|
save(channel, result);
|
||||||
|
}, [=](const RPCError &error) {
|
||||||
|
*saving = false;
|
||||||
|
});
|
||||||
|
}, box->lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -868,6 +914,11 @@ void Controller::fillManageSection() {
|
||||||
? channel->canEditPermissions()
|
? channel->canEditPermissions()
|
||||||
: chat->canEditPermissions();
|
: chat->canEditPermissions();
|
||||||
}();
|
}();
|
||||||
|
const auto canEditInviteLinks = [&] {
|
||||||
|
return isChannel
|
||||||
|
? channel->canHaveInviteLink()
|
||||||
|
: chat->canHaveInviteLink();
|
||||||
|
}();
|
||||||
const auto canViewAdmins = [&] {
|
const auto canViewAdmins = [&] {
|
||||||
return isChannel
|
return isChannel
|
||||||
? channel->canViewAdmins()
|
? channel->canViewAdmins()
|
||||||
|
@ -949,6 +1000,26 @@ void Controller::fillManageSection() {
|
||||||
[=] { ShowEditPermissions(_navigation, _peer); },
|
[=] { ShowEditPermissions(_navigation, _peer); },
|
||||||
st::infoIconPermissions);
|
st::infoIconPermissions);
|
||||||
}
|
}
|
||||||
|
if (canEditInviteLinks) {
|
||||||
|
AddButtonWithCount(
|
||||||
|
_controls.buttonsLayout,
|
||||||
|
tr::lng_manage_peer_invite_links(),
|
||||||
|
Info::Profile::MigratedOrMeValue(
|
||||||
|
_peer
|
||||||
|
) | rpl::map([=](not_null<PeerData*> peer) {
|
||||||
|
peer->session().api().inviteLinks().requestLinks(peer);
|
||||||
|
return peer->session().changes().peerUpdates(
|
||||||
|
peer,
|
||||||
|
Data::PeerUpdate::Flag::InviteLink
|
||||||
|
) | rpl::map([=] {
|
||||||
|
return peer->session().api().inviteLinks().links(
|
||||||
|
peer).count;
|
||||||
|
});
|
||||||
|
}) | rpl::flatten_latest(
|
||||||
|
) | ToPositiveNumberString(),
|
||||||
|
[=] { ShowEditInviteLinks(_navigation, _peer); },
|
||||||
|
st::infoIconPermissions);
|
||||||
|
}
|
||||||
if (canViewAdmins) {
|
if (canViewAdmins) {
|
||||||
AddButtonWithCount(
|
AddButtonWithCount(
|
||||||
_controls.buttonsLayout,
|
_controls.buttonsLayout,
|
||||||
|
|
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "boxes/peers/edit_peer_type_box.h"
|
#include "boxes/peers/edit_peer_type_box.h"
|
||||||
|
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
|
#include "api/api_invite_links.h"
|
||||||
#include "main/main_session.h"
|
#include "main/main_session.h"
|
||||||
#include "boxes/add_contact_box.h"
|
#include "boxes/add_contact_box.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
|
@ -126,8 +127,7 @@ private:
|
||||||
void refreshEditInviteLink();
|
void refreshEditInviteLink();
|
||||||
void refreshCreateInviteLink();
|
void refreshCreateInviteLink();
|
||||||
void createInviteLink();
|
void createInviteLink();
|
||||||
void revokeInviteLink();
|
void revokeInviteLink(const QString &link);
|
||||||
void exportInviteLink(const QString &confirmation);
|
|
||||||
|
|
||||||
void fillPrivaciesButtons(
|
void fillPrivaciesButtons(
|
||||||
not_null<Ui::VerticalLayout*> parent,
|
not_null<Ui::VerticalLayout*> parent,
|
||||||
|
@ -536,22 +536,26 @@ void Controller::showUsernameResult(
|
||||||
}
|
}
|
||||||
|
|
||||||
void Controller::createInviteLink() {
|
void Controller::createInviteLink() {
|
||||||
exportInviteLink((_isGroup
|
|
||||||
? tr::lng_group_invite_about
|
|
||||||
: tr::lng_group_invite_about_channel)(tr::now));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::revokeInviteLink() {
|
|
||||||
exportInviteLink(tr::lng_group_invite_about_new(tr::now));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Controller::exportInviteLink(const QString &confirmation) {
|
|
||||||
const auto callback = crl::guard(this, [=](Fn<void()> &&close) {
|
const auto callback = crl::guard(this, [=](Fn<void()> &&close) {
|
||||||
close();
|
close();
|
||||||
_peer->session().api().exportInviteLink(_peer->migrateToOrMe());
|
_peer->session().api().inviteLinks().create(_peer->migrateToOrMe());
|
||||||
});
|
});
|
||||||
auto box = Box<ConfirmBox>(
|
auto box = Box<ConfirmBox>(
|
||||||
confirmation,
|
(_isGroup
|
||||||
|
? tr::lng_group_invite_about
|
||||||
|
: tr::lng_group_invite_about_channel)(tr::now),
|
||||||
|
std::move(callback));
|
||||||
|
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Controller::revokeInviteLink(const QString &link) {
|
||||||
|
const auto callback = crl::guard(this, [=](Fn<void()> &&close) {
|
||||||
|
close();
|
||||||
|
const auto peer = _peer->migrateToOrMe();
|
||||||
|
peer->session().api().inviteLinks().revoke(peer, link);
|
||||||
|
});
|
||||||
|
auto box = Box<ConfirmBox>(
|
||||||
|
tr::lng_group_invite_about_new(tr::now),
|
||||||
std::move(callback));
|
std::move(callback));
|
||||||
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
|
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
|
||||||
}
|
}
|
||||||
|
@ -623,7 +627,7 @@ object_ptr<Ui::RpWidget> Controller::createInviteLinkEdit() {
|
||||||
container,
|
container,
|
||||||
tr::lng_group_invite_create_new(tr::now),
|
tr::lng_group_invite_create_new(tr::now),
|
||||||
st::editPeerInviteLinkButton)
|
st::editPeerInviteLinkButton)
|
||||||
)->addClickHandler([=] { revokeInviteLink(); });
|
)->addClickHandler([=] { revokeInviteLink(inviteLinkText()); });
|
||||||
|
|
||||||
observeInviteLink();
|
observeInviteLink();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue