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:
@@ -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 {
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
@@ -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_);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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>());
|
||||
}
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user