2
0
mirror of https://github.com/ars3niy/tdlib-purple synced 2025-08-31 14:05:10 +00:00

Implemented adding users to groups

This commit is contained in:
Arseniy Lartsev
2020-06-07 14:07:58 +02:00
parent 1e0a45ceb7
commit 648314d106
8 changed files with 153 additions and 35 deletions

View File

@@ -154,11 +154,16 @@ public:
: PendingRequest(requestId), username(username), fileUpload(upload) {}
};
class KickRequest: public PendingRequest {
class ChatActionRequest: public PendingRequest {
public:
enum class Type: uint8_t {
Kick,
Invite
};
Type type;
int64_t chatId;
KickRequest(uint64_t requestId, int64_t chatId)
: PendingRequest(requestId), chatId(chatId) {}
ChatActionRequest(uint64_t requestId, Type type, int64_t chatId)
: PendingRequest(requestId), type(type), chatId(chatId) {}
};
class TdAccountData {

View File

@@ -377,6 +377,15 @@ void removeGroupChat(PurpleAccount *purpleAccount, const td::td_api::chat &chat)
purple_blist_remove_chat(purpleChat);
}
static PurpleMessageFlags getNotificationFlags(PurpleMessageFlags extraFlags)
{
unsigned flags = (extraFlags & PURPLE_MESSAGE_ERROR) | (extraFlags & PURPLE_MESSAGE_NO_LOG);
if (flags == 0)
flags = PURPLE_MESSAGE_SYSTEM;
return (PurpleMessageFlags)flags;
}
void showMessageTextIm(TdAccountData &account, const char *purpleUserName, const char *text,
const char *notification, time_t timestamp, PurpleMessageFlags flags)
{
@@ -400,8 +409,7 @@ void showMessageTextIm(TdAccountData &account, const char *purpleUserName, const
if (conv == NULL)
conv = getImConversation(account.purpleAccount, purpleUserName);
purple_conv_im_write(purple_conversation_get_im_data(conv), nullptr, notification,
(flags & PURPLE_MESSAGE_ERROR) ? PURPLE_MESSAGE_ERROR : PURPLE_MESSAGE_SYSTEM,
timestamp);
getNotificationFlags(flags), timestamp);
}
}
@@ -428,8 +436,7 @@ static void showMessageTextChat(TdAccountData &account, const td::td_api::chat &
if (notification) {
if (conv)
purple_conv_chat_write(conv, "", notification,
PURPLE_MESSAGE_SYSTEM, message.timestamp);
purple_conv_chat_write(conv, "", notification, getNotificationFlags(flags), message.timestamp);
}
}
@@ -543,6 +550,16 @@ void showMessageText(TdAccountData &account, const td::td_api::chat &chat, const
showMessageTextChat(account, chat, message, text, notification, flags);
}
void showChatNotification(TdAccountData &account, const td::td_api::chat &chat,
const char *notification, PurpleMessageFlags flags)
{
TgMessageInfo messageInfo;
messageInfo.type = TgMessageInfo::Type::Other;
messageInfo.timestamp = (flags == PURPLE_MESSAGE_NO_LOG) ? 0 : time(NULL);
messageInfo.outgoing = true;
showMessageText(account, chat, messageInfo, NULL, notification, flags);
}
std::string getSenderPurpleName(const td::td_api::chat &chat, const td::td_api::message &message,
TdAccountData &account)
{

View File

@@ -39,6 +39,8 @@ void showMessageText(TdAccountData &account, const td::td_api::chat &chat, const
const char *text, const char *notification, uint32_t extraFlags = 0);
void showMessageTextIm(TdAccountData &account, const char *purpleUserName, const char *text,
const char *notification, time_t timestamp, PurpleMessageFlags flags);
void showChatNotification(TdAccountData &account, const td::td_api::chat &chat,
const char *notification, PurpleMessageFlags extraFlags = (PurpleMessageFlags)0);
void showGenericFile(const td::td_api::chat &chat, const TgMessageInfo &message,
const std::string &filePath, const std::string &fileDescription,
TdAccountData &account);

View File

@@ -1274,13 +1274,8 @@ void PurpleTdClient::sendMessageResponse(uint64_t requestId, td::td_api::object_
} else {
std::string errorMessage = formatMessage(_("Failed to send message: {}"), getDisplayedError(object));
const td::td_api::chat *chat = m_data.getChat(request->chatId);
if (chat) {
TgMessageInfo messageInfo;
messageInfo.type = TgMessageInfo::Type::Other;
messageInfo.outgoing = true;
messageInfo.timestamp = time(NULL);
showMessageText(m_data, *chat, messageInfo, NULL, errorMessage.c_str());
}
if (chat)
showChatNotification(m_data, *chat, errorMessage.c_str());
}
}
@@ -1922,10 +1917,11 @@ void PurpleTdClient::kickUserFromChat(PurpleConversation *conv, const char *name
std::vector<const td::td_api::user *> users = getUsersByPurpleName(name, m_data, "kick user");
if (users.size() != 1) {
const char *message = users.empty() ? _("User not found") :
const char *reason = users.empty() ? _("User not found") :
// Unlikely error message not worth translating
"More than one user found with this name";
purple_conversation_write(conv, NULL, message, PURPLE_MESSAGE_NO_LOG, 0);
std::string message = formatMessage(_("Cannot kick user: {}"), std::string(reason));
purple_conversation_write(conv, NULL, message.c_str(), PURPLE_MESSAGE_NO_LOG, 0);
return;
}
@@ -1934,23 +1930,54 @@ void PurpleTdClient::kickUserFromChat(PurpleConversation *conv, const char *name
setStatusRequest->user_id_ = users[0]->id_;
setStatusRequest->status_ = td::td_api::make_object<td::td_api::chatMemberStatusLeft>();
uint64_t requestId = m_transceiver.sendQuery(std::move(setStatusRequest), &PurpleTdClient::kickUserResponse);
m_data.addPendingRequest<KickRequest>(requestId, chat->id_);
uint64_t requestId = m_transceiver.sendQuery(std::move(setStatusRequest), &PurpleTdClient::chatActionResponse);
m_data.addPendingRequest<ChatActionRequest>(requestId, ChatActionRequest::Type::Kick, chat->id_);
}
void PurpleTdClient::kickUserResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
void PurpleTdClient::chatActionResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
{
if (!object || (object->get_id() != td::td_api::ok::ID)) {
std::unique_ptr<KickRequest> request = m_data.getPendingRequest<KickRequest>(requestId);
std::unique_ptr<ChatActionRequest> request = m_data.getPendingRequest<ChatActionRequest>(requestId);
const td::td_api::chat *chat = request ? m_data.getChat(request->chatId) : nullptr;
if (chat) {
TgMessageInfo messageInfo;
messageInfo.type = TgMessageInfo::Type::Other;
messageInfo.timestamp = time(NULL);
messageInfo.outgoing = true;
std::string message = formatMessage(_("Failed to kick user: {}"), getDisplayedError(object));
showMessageText(m_data, *chat, messageInfo, NULL, message.c_str(), PURPLE_MESSAGE_SYSTEM);
std::string message = getDisplayedError(object);
switch (request->type) {
case ChatActionRequest::Type::Kick:
message = formatMessage(_("Cannot kick user: {}"), message);
break;
case ChatActionRequest::Type::Invite:
message = formatMessage(_("Cannot add user to group: {}"), message);
break;
}
showChatNotification(m_data, *chat, message.c_str());
}
}
}
void PurpleTdClient::addUserToChat(int purpleChatId, const char *name)
{
const td::td_api::chat *chat = m_data.getChatByPurpleId(purpleChatId);
if (!chat) {
purple_debug_warning(config::pluginId, "Unknown libpurple chat id %d\n", purpleChatId);
return;
}
std::vector<const td::td_api::user *> users = getUsersByPurpleName(name, m_data, "kick user");
if (users.size() != 1) {
const char *reason = users.empty() ? _("User not found") :
// Unlikely error message not worth translating
"More than one user found with this name";
std::string message = formatMessage(_("Cannot add user to group: {}"), std::string(reason));
showChatNotification(m_data, *chat, message.c_str(), PURPLE_MESSAGE_NO_LOG);
return;
}
if (getBasicGroupId(*chat) || getSupergroupId(*chat)) {
auto request = td::td_api::make_object<td::td_api::addChatMember>();
request->chat_id_ = chat->id_;
request->user_id_ = users[0]->id_;
uint64_t requestId = m_transceiver.sendQuery(std::move(request), &PurpleTdClient::chatActionResponse);
m_data.addPendingRequest<ChatActionRequest>(requestId, ChatActionRequest::Type::Invite, chat->id_);
}
}

View File

@@ -37,6 +37,7 @@ public:
int sendGroupMessage(int purpleChatId, const char *message);
void setGroupDescription(int purpleChatId, const char *description);
void kickUserFromChat(PurpleConversation *conv, const char *name);
void addUserToChat(int purpleChatId, const char *name);
void setTwoFactorAuth(const char *oldPassword, const char *newPassword, const char *hint,
const char *email);
@@ -121,7 +122,7 @@ private:
void joinChatByLinkResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void deleteSupergroupResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void setGroupDescriptionResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void kickUserResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void chatActionResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void showFile(const td::td_api::chat &chat, TgMessageInfo &message,
const td::td_api::file &file, const char *caption, const std::string &fileDesc,
@@ -151,9 +152,7 @@ private:
td::td_api::object_ptr<td::td_api::file> thumbnail);
void sendMessageCreatePrivateChatResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void uploadResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void updateFile(const td::td_api::file &file);
bool sendMessage(int64_t chatId, const char *message);
void sendMessageResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
void removeTempFile(int64_t messageId);

View File

@@ -412,6 +412,9 @@ static char *tgprpl_get_chat_name (GHashTable * data)
static void tgprpl_chat_invite (PurpleConnection *gc, int id, const char *message, const char *who)
{
PurpleTdClient *tdClient = static_cast<PurpleTdClient *>(purple_connection_get_protocol_data(gc));
if (tdClient)
tdClient->addUserToChat(id, who);
}
static int tgprpl_send_chat (PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)

View File

@@ -1065,14 +1065,14 @@ TEST_F(GroupChatTest, Kick)
prpl.runCommand("kick", conv, {purpleUserName(1)});
prpl.verifyEvents(ConversationWriteEvent(
groupChatPurpleName, "",
"User not found",
"Cannot kick user: User not found",
PURPLE_MESSAGE_NO_LOG, 0
));
prpl.runCommand("kick", conv, {userFirstNames[1] + " " + userLastNames[1]});
prpl.verifyEvents(ConversationWriteEvent(
groupChatPurpleName, "",
"User not found",
"Cannot kick user: User not found",
PURPLE_MESSAGE_NO_LOG, 0
));
@@ -1084,7 +1084,7 @@ TEST_F(GroupChatTest, Kick)
tgl.reply(make_object<error>(100, "error"));
prpl.verifyEvents(ConversationWriteEvent(
groupChatPurpleName, "",
"Failed to kick user: code 100 (error)",
"Cannot kick user: code 100 (error)",
PURPLE_MESSAGE_SYSTEM, 0
));
@@ -1095,3 +1095,60 @@ TEST_F(GroupChatTest, Kick)
));
tgl.reply(make_object<ok>());
}
TEST_F(GroupChatTest, Invite)
{
constexpr int purpleChatId = 1;
loginWithBasicGroup();
tgl.update(standardUpdateUserNoPhone(0));
GHashTable *components = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
g_hash_table_insert(components, (char *)"id", g_strdup((groupChatPurpleName).c_str()));
pluginInfo().join_chat(connection, components);
g_hash_table_destroy(components);
prpl.verifyEvents(
ServGotJoinedChatEvent(connection, purpleChatId, groupChatPurpleName, groupChatTitle),
PresentConversationEvent(groupChatPurpleName)
);
pluginInfo().chat_invite(
connection, purpleChatId, NULL,
purpleUserName(1).c_str()
);
prpl.verifyEvents(ConversationWriteEvent(
groupChatPurpleName, "",
"Cannot add user to group: User not found",
PURPLE_MESSAGE_NO_LOG, 0
));
pluginInfo().chat_invite(
connection, purpleChatId, NULL,
(userFirstNames[1] + " " + userLastNames[1]).c_str()
);
prpl.verifyEvents(ConversationWriteEvent(
groupChatPurpleName, "",
"Cannot add user to group: User not found",
PURPLE_MESSAGE_NO_LOG, 0
));
pluginInfo().chat_invite(
connection, purpleChatId, NULL,
purpleUserName(0).c_str()
);
tgl.verifyRequest(addChatMember(groupChatId, userIds[0], 0));
tgl.reply(make_object<error>(100, "error"));
prpl.verifyEvents(ConversationWriteEvent(
groupChatPurpleName, "",
"Cannot add user to group: code 100 (error)",
PURPLE_MESSAGE_SYSTEM, 0
));
pluginInfo().chat_invite(
connection, purpleChatId, NULL,
(userFirstNames[0] + " " + userLastNames[0]).c_str()
);
tgl.verifyRequest(addChatMember(groupChatId, userIds[0], 0));
tgl.reply(make_object<ok>());
}

View File

@@ -389,6 +389,13 @@ static void compare(const setChatMemberStatus &actual, const setChatMemberStatus
}
}
static void compare(const addChatMember &actual, const addChatMember &expected)
{
COMPARE(chat_id_);
COMPARE(user_id_);
COMPARE(forward_limit_);
}
static void compareRequests(const Function &actual, const Function &expected,
std::vector<std::string> &m_inputPhotoPaths)
{
@@ -434,6 +441,7 @@ static void compareRequests(const Function &actual, const Function &expected,
C(getSupergroupFullInfo)
C(cancelDownloadFile)
C(setChatMemberStatus)
C(addChatMember)
default: ASSERT_TRUE(false) << "Unsupported request " << requestToString(actual);
}
}