mirror of
https://github.com/ars3niy/tdlib-purple
synced 2025-09-01 06:25:10 +00:00
Implemented configuring two-step authentication
This commit is contained in:
@@ -25,7 +25,7 @@ add_library(telegram-tdlib SHARED
|
|||||||
td-client.cpp
|
td-client.cpp
|
||||||
transceiver.cpp
|
transceiver.cpp
|
||||||
account-data.cpp
|
account-data.cpp
|
||||||
chat-info.cpp
|
purple-info.cpp
|
||||||
config.cpp
|
config.cpp
|
||||||
client-utils.cpp
|
client-utils.cpp
|
||||||
format.cpp
|
format.cpp
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
#include "client-utils.h"
|
#include "client-utils.h"
|
||||||
#include "chat-info.h"
|
#include "purple-info.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
|
#include "td-client.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@@ -58,4 +58,6 @@ void setChatMembers(PurpleConvChat *purpleChat, const td::td_api::basicGroupFull
|
|||||||
void transmitMessage(int64_t chatId, const char *message, TdTransceiver &transceiver,
|
void transmitMessage(int64_t chatId, const char *message, TdTransceiver &transceiver,
|
||||||
TdAccountData &account, TdTransceiver::ResponseCb response);
|
TdAccountData &account, TdTransceiver::ResponseCb response);
|
||||||
|
|
||||||
|
void requestRecoveryEmailConfirmation(PurpleConnection *gc, const char *emailInfo);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
#include "chat-info.h"
|
#include "purple-info.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _CHAT_INFO_H
|
#ifndef _PURPLE_INFO_H
|
||||||
#define _CHAT_INFO_H
|
#define _PURPLE_INFO_H
|
||||||
|
|
||||||
#include <purple.h>
|
#include <purple.h>
|
||||||
#include <td/telegram/td_api.h>
|
#include <td/telegram/td_api.h>
|
100
td-client.cpp
100
td-client.cpp
@@ -1,5 +1,5 @@
|
|||||||
#include "td-client.h"
|
#include "td-client.h"
|
||||||
#include "chat-info.h"
|
#include "purple-info.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@@ -532,7 +532,7 @@ void PurpleTdClient::requestMissingPrivateChats()
|
|||||||
|
|
||||||
void PurpleTdClient::loginCreatePrivateChatResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
void PurpleTdClient::loginCreatePrivateChatResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
||||||
{
|
{
|
||||||
if (object->get_id() == td::td_api::chat::ID) {
|
if (object && (object->get_id() == td::td_api::chat::ID)) {
|
||||||
td::td_api::object_ptr<td::td_api::chat> chat = td::move_tl_object_as<td::td_api::chat>(object);
|
td::td_api::object_ptr<td::td_api::chat> chat = td::move_tl_object_as<td::td_api::chat>(object);
|
||||||
purple_debug_misc(config::pluginId, "Requested private chat received: id %" G_GINT64_FORMAT "\n",
|
purple_debug_misc(config::pluginId, "Requested private chat received: id %" G_GINT64_FORMAT "\n",
|
||||||
chat->id_);
|
chat->id_);
|
||||||
@@ -1254,7 +1254,7 @@ void PurpleTdClient::importContactResponse(uint64_t requestId, td::td_api::objec
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
int32_t userId = 0;
|
int32_t userId = 0;
|
||||||
if (object->get_id() == td::td_api::importedContacts::ID) {
|
if (object && (object->get_id() == td::td_api::importedContacts::ID)) {
|
||||||
td::td_api::object_ptr<td::td_api::importedContacts> reply =
|
td::td_api::object_ptr<td::td_api::importedContacts> reply =
|
||||||
td::move_tl_object_as<td::td_api::importedContacts>(object);
|
td::move_tl_object_as<td::td_api::importedContacts>(object);
|
||||||
if (!reply->user_ids_.empty())
|
if (!reply->user_ids_.empty())
|
||||||
@@ -1276,7 +1276,7 @@ void PurpleTdClient::addContactResponse(uint64_t requestId, td::td_api::object_p
|
|||||||
if (!request)
|
if (!request)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (object->get_id() == td::td_api::ok::ID) {
|
if (object && (object->get_id() == td::td_api::ok::ID)) {
|
||||||
td::td_api::object_ptr<td::td_api::createPrivateChat> createChat =
|
td::td_api::object_ptr<td::td_api::createPrivateChat> createChat =
|
||||||
td::td_api::make_object<td::td_api::createPrivateChat>(request->userId, false);
|
td::td_api::make_object<td::td_api::createPrivateChat>(request->userId, false);
|
||||||
uint64_t newRequestId = m_transceiver.sendQuery(std::move(createChat),
|
uint64_t newRequestId = m_transceiver.sendQuery(std::move(createChat),
|
||||||
@@ -1528,3 +1528,95 @@ void PurpleTdClient::removeTempFile(int64_t messageId)
|
|||||||
remove(path.c_str());
|
remove(path.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PurpleTdClient::setTwoStepAuth(const char *oldPassword, const char *newPassword,
|
||||||
|
const char *hint, const char *email)
|
||||||
|
{
|
||||||
|
auto setPassword = td::td_api::make_object<td::td_api::setPassword>();
|
||||||
|
if (oldPassword)
|
||||||
|
setPassword->old_password_ = oldPassword;
|
||||||
|
if (newPassword)
|
||||||
|
setPassword->new_password_ = newPassword;
|
||||||
|
if (hint)
|
||||||
|
setPassword->new_hint_ = hint;
|
||||||
|
setPassword->set_recovery_email_address_ = (email && *email);
|
||||||
|
if (email)
|
||||||
|
setPassword->new_recovery_email_address_ = email;
|
||||||
|
|
||||||
|
m_transceiver.sendQuery(std::move(setPassword), &PurpleTdClient::setTwoStepAuthResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void inputCancelled(void *data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PurpleTdClient::requestRecoveryEmailConfirmation(const std::string &emailInfo)
|
||||||
|
{
|
||||||
|
std::string secondary = "Password will be changed after new e-mail is confirmed\n" + emailInfo;
|
||||||
|
PurpleConnection *gc = purple_account_get_connection(m_account);
|
||||||
|
purple_request_input(gc, _("Two-factor authentication"),
|
||||||
|
_("Enter verification code received in the e-mail"), secondary.c_str(),
|
||||||
|
NULL, // default value
|
||||||
|
FALSE, // multiline input
|
||||||
|
FALSE, // masked input
|
||||||
|
NULL,
|
||||||
|
_("OK"), G_CALLBACK(PurpleTdClient::verifyRecoveryEmail),
|
||||||
|
_("Cancel"), G_CALLBACK(inputCancelled),
|
||||||
|
purple_connection_get_account(gc),
|
||||||
|
NULL, // buddy
|
||||||
|
NULL, // conversation
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void notifyPasswordChangeSuccess(PurpleAccount *account, const td::td_api::passwordState &passwordState)
|
||||||
|
{
|
||||||
|
purple_notify_info(account, _("Two-step authentication"),
|
||||||
|
passwordState.has_password_ ? _("Password set") : _("Password cleared"),
|
||||||
|
passwordState.has_recovery_email_address_ ? _("Recovery e-mail is configured") :
|
||||||
|
_("No recovery e-mail configured"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void PurpleTdClient::setTwoStepAuthResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
||||||
|
{
|
||||||
|
if (object && (object->get_id() == td::td_api::passwordState::ID)) {
|
||||||
|
const td::td_api::passwordState &passwordState = static_cast<const td::td_api::passwordState &>(*object);
|
||||||
|
if (passwordState.recovery_email_address_code_info_) {
|
||||||
|
std::string emailInfo = formatMessage(_("Code sent to {} (length: {})"),
|
||||||
|
{passwordState.recovery_email_address_code_info_->email_address_pattern_,
|
||||||
|
std::to_string(passwordState.recovery_email_address_code_info_->length_)});
|
||||||
|
requestRecoveryEmailConfirmation(emailInfo);
|
||||||
|
} else
|
||||||
|
notifyPasswordChangeSuccess(m_account, passwordState);
|
||||||
|
} else {
|
||||||
|
std::string errorMessage = getDisplayedError(object);
|
||||||
|
purple_notify_error(m_account, _("Two-step authentication"), _("Failed to set password"), errorMessage.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PurpleTdClient::verifyRecoveryEmail(PurpleTdClient *self, const char *code)
|
||||||
|
{
|
||||||
|
auto checkCode = td::td_api::make_object<td::td_api::checkRecoveryEmailAddressCode>();
|
||||||
|
if (code)
|
||||||
|
checkCode->code_ = code;
|
||||||
|
self->m_transceiver.sendQuery(std::move(checkCode), &PurpleTdClient::verifyRecoveryEmailResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PurpleTdClient::verifyRecoveryEmailResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object)
|
||||||
|
{
|
||||||
|
if (object && (object->get_id() == td::td_api::passwordState::ID)) {
|
||||||
|
const td::td_api::passwordState &passwordState = static_cast<const td::td_api::passwordState &>(*object);
|
||||||
|
if (passwordState.recovery_email_address_code_info_) {
|
||||||
|
if (passwordState.recovery_email_address_code_info_->length_ > 0) {
|
||||||
|
std::string emailInfo = formatMessage(_("E-mail address: {}"),
|
||||||
|
passwordState.recovery_email_address_code_info_->email_address_pattern_);
|
||||||
|
purple_notify_info(m_account, _("Two-step authentication"),
|
||||||
|
_("For some reason, new confirmation code was sent"), emailInfo.c_str());
|
||||||
|
} else
|
||||||
|
purple_notify_error(m_account, _("Two-step authentication"), _("Looks like the code was wrong"), NULL);
|
||||||
|
} else
|
||||||
|
notifyPasswordChangeSuccess(m_account, passwordState);
|
||||||
|
} else {
|
||||||
|
std::string errorMessage = getDisplayedError(object);
|
||||||
|
purple_notify_error(m_account, _("Two-step authentication"), _("Failed to verify recovery e-mail"), errorMessage.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -32,6 +32,9 @@ public:
|
|||||||
BasicGroupMembership getBasicGroupMembership(const char *purpleChatName);
|
BasicGroupMembership getBasicGroupMembership(const char *purpleChatName);
|
||||||
void leaveGroup(const std::string &purpleChatName, bool deleteSupergroup);
|
void leaveGroup(const std::string &purpleChatName, bool deleteSupergroup);
|
||||||
int sendGroupMessage(int purpleChatId, const char *message);
|
int sendGroupMessage(int purpleChatId, const char *message);
|
||||||
|
|
||||||
|
void setTwoStepAuth(const char *oldPassword, const char *newPassword, const char *hint,
|
||||||
|
const char *email);
|
||||||
private:
|
private:
|
||||||
using TdObjectPtr = td::td_api::object_ptr<td::td_api::Object>;
|
using TdObjectPtr = td::td_api::object_ptr<td::td_api::Object>;
|
||||||
using ResponseCb = void (PurpleTdClient::*)(uint64_t requestId, TdObjectPtr object);
|
using ResponseCb = void (PurpleTdClient::*)(uint64_t requestId, TdObjectPtr object);
|
||||||
@@ -118,6 +121,11 @@ private:
|
|||||||
void sendMessageResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
void sendMessageResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
||||||
void removeTempFile(int64_t messageId);
|
void removeTempFile(int64_t messageId);
|
||||||
|
|
||||||
|
void setTwoStepAuthResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
||||||
|
void requestRecoveryEmailConfirmation(const std::string &emailInfo);
|
||||||
|
static void verifyRecoveryEmail(PurpleTdClient *self, const char *code);
|
||||||
|
void verifyRecoveryEmailResponse(uint64_t requestId, td::td_api::object_ptr<td::td_api::Object> object);
|
||||||
|
|
||||||
PurpleAccount *m_account;
|
PurpleAccount *m_account;
|
||||||
TdTransceiver m_transceiver;
|
TdTransceiver m_transceiver;
|
||||||
TdAccountData m_data;
|
TdAccountData m_data;
|
||||||
|
103
tdlib-purple.cpp
103
tdlib-purple.cpp
@@ -1,6 +1,6 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "td-client.h"
|
#include "td-client.h"
|
||||||
#include "chat-info.h"
|
#include "purple-info.h"
|
||||||
#include "format.h"
|
#include "format.h"
|
||||||
#include <purple.h>
|
#include <purple.h>
|
||||||
|
|
||||||
@@ -84,6 +84,8 @@ static GList *tgprpl_status_types (PurpleAccount *acct)
|
|||||||
struct RequestData {
|
struct RequestData {
|
||||||
PurpleAccount *account;
|
PurpleAccount *account;
|
||||||
std::string stringData;
|
std::string stringData;
|
||||||
|
|
||||||
|
RequestData(PurpleAccount *account) : account(account) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
static void cancelRequest(RequestData *data, int action)
|
static void cancelRequest(RequestData *data, int action)
|
||||||
@@ -119,8 +121,7 @@ static void leaveGroup(PurpleBlistNode *node, gpointer data)
|
|||||||
PurpleTdClient *tdClient = getTdClient(account);
|
PurpleTdClient *tdClient = getTdClient(account);
|
||||||
if (tdClient) {
|
if (tdClient) {
|
||||||
const char *chatName = getChatName(purple_chat_get_components(chat));
|
const char *chatName = getChatName(purple_chat_get_components(chat));
|
||||||
RequestData *request = new RequestData;
|
RequestData *request = new RequestData(account);
|
||||||
request->account = account;
|
|
||||||
request->stringData = chatName ? chatName : "";
|
request->stringData = chatName ? chatName : "";
|
||||||
|
|
||||||
if (tdClient->getBasicGroupMembership(chatName) == BasicGroupMembership::Creator)
|
if (tdClient->getBasicGroupMembership(chatName) == BasicGroupMembership::Creator)
|
||||||
@@ -152,8 +153,7 @@ static void deleteGroup(PurpleBlistNode *node, gpointer data)
|
|||||||
purple_notify_error(account, _("Error"), _("Cannot delete group"),
|
purple_notify_error(account, _("Error"), _("Cannot delete group"),
|
||||||
_("Cannot delete basic group created by someone else"));
|
_("Cannot delete basic group created by someone else"));
|
||||||
else {
|
else {
|
||||||
RequestData *request = new RequestData;
|
RequestData *request = new RequestData(account);
|
||||||
request->account = account;
|
|
||||||
request->stringData = chatName ? chatName : "";
|
request->stringData = chatName ? chatName : "";
|
||||||
purple_request_action(purple_account_get_connection(account), _("Deleting group"),
|
purple_request_action(purple_account_get_connection(account), _("Deleting group"),
|
||||||
_("Delete the group?"), NULL,
|
_("Delete the group?"), NULL,
|
||||||
@@ -295,8 +295,7 @@ static void tgprpl_request_delete_contact (PurpleConnection *gc, PurpleBuddy *bu
|
|||||||
{
|
{
|
||||||
g_return_if_fail(buddy);
|
g_return_if_fail(buddy);
|
||||||
|
|
||||||
RequestData *data = new RequestData;
|
RequestData *data = new RequestData(purple_connection_get_account(gc));
|
||||||
data->account = purple_connection_get_account(gc);
|
|
||||||
data->stringData = purple_buddy_get_name(buddy);
|
data->stringData = purple_buddy_get_name(buddy);
|
||||||
|
|
||||||
purple_request_yes_no(gc, _("Remove contact"), _("Remove contact"),
|
purple_request_yes_no(gc, _("Remove contact"), _("Remove contact"),
|
||||||
@@ -335,11 +334,6 @@ static void create_group_chat_cb (RequestData *data, PurpleRequestFields* fields
|
|||||||
tdClient->createGroup(request->stringData.c_str(), GROUP_TYPE_BASIC, members);
|
tdClient->createGroup(request->stringData.c_str(), GROUP_TYPE_BASIC, members);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cancel_group_chat_cb (RequestData *data)
|
|
||||||
{
|
|
||||||
delete data;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void requestCreateBasicGroup(PurpleConnection *gc, const char *name)
|
static void requestCreateBasicGroup(PurpleConnection *gc, const char *name)
|
||||||
{
|
{
|
||||||
// Telegram doesn't allow to create chats with only one user, so we need to force
|
// Telegram doesn't allow to create chats with only one user, so we need to force
|
||||||
@@ -362,11 +356,10 @@ static void requestCreateBasicGroup(PurpleConnection *gc, const char *name)
|
|||||||
|
|
||||||
purple_request_fields_add_group (fields, group);
|
purple_request_fields_add_group (fields, group);
|
||||||
|
|
||||||
RequestData *data = new RequestData;
|
RequestData *data = new RequestData(purple_connection_get_account(gc));
|
||||||
data->account = purple_connection_get_account(gc);
|
|
||||||
data->stringData = name;
|
data->stringData = name;
|
||||||
purple_request_fields (gc, _("Create group chat"), _("Invite users"), NULL, fields, _("OK"),
|
purple_request_fields (gc, _("Create group chat"), _("Invite users"), NULL, fields, _("OK"),
|
||||||
G_CALLBACK(create_group_chat_cb), _("Cancel"), G_CALLBACK(cancel_group_chat_cb),
|
G_CALLBACK(create_group_chat_cb), _("Cancel"), G_CALLBACK(cancelRequest),
|
||||||
purple_connection_get_account(gc), NULL, NULL, data);
|
purple_connection_get_account(gc), NULL, NULL, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -603,9 +596,87 @@ static void tgprpl_init (PurplePlugin *plugin)
|
|||||||
PurpleTdClient::setLogLevel(1);
|
PurpleTdClient::setLogLevel(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setTwoStepAuth(RequestData *data, PurpleRequestFields* fields);
|
||||||
|
|
||||||
|
static void requestTwoStepAuth(PurpleConnection *gc, const char *primaryText, const char *email)
|
||||||
|
{
|
||||||
|
PurpleRequestFields *fields = purple_request_fields_new();
|
||||||
|
PurpleRequestFieldGroup *group = purple_request_field_group_new(NULL);
|
||||||
|
|
||||||
|
PurpleRequestField *field = purple_request_field_string_new ("oldpw", _("Current password"), NULL, FALSE);
|
||||||
|
purple_request_field_string_set_masked(field, TRUE);
|
||||||
|
purple_request_field_group_add_field (group, field);
|
||||||
|
|
||||||
|
field = purple_request_field_string_new ("pw1", _("New password"), NULL, FALSE);
|
||||||
|
purple_request_field_string_set_masked(field, TRUE);
|
||||||
|
purple_request_field_group_add_field (group, field);
|
||||||
|
|
||||||
|
field = purple_request_field_string_new ("pw2", _("Repeat password"), NULL, FALSE);
|
||||||
|
purple_request_field_string_set_masked(field, TRUE);
|
||||||
|
purple_request_field_group_add_field (group, field);
|
||||||
|
|
||||||
|
field = purple_request_field_string_new ("hint", _("Password hint"), NULL, FALSE);
|
||||||
|
purple_request_field_group_add_field (group, field);
|
||||||
|
|
||||||
|
field = purple_request_field_string_new ("email", _("Recovery e-mail"), email, FALSE);
|
||||||
|
purple_request_field_group_add_field (group, field);
|
||||||
|
|
||||||
|
purple_request_fields_add_group (fields, group);
|
||||||
|
|
||||||
|
RequestData *data = new RequestData(purple_connection_get_account(gc));
|
||||||
|
data->account = purple_connection_get_account(gc);
|
||||||
|
purple_request_fields (gc, _("Two-step authentication"), primaryText, NULL, fields, _("OK"),
|
||||||
|
G_CALLBACK(setTwoStepAuth), _("Cancel"), G_CALLBACK(cancelRequest),
|
||||||
|
purple_connection_get_account(gc), NULL, NULL, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reRequestTwoStepAuth(gpointer user_data)
|
||||||
|
{
|
||||||
|
std::unique_ptr<RequestData> request(static_cast<RequestData *>(user_data));
|
||||||
|
requestTwoStepAuth(purple_account_get_connection(request->account),
|
||||||
|
_("Please enter same password twice"), request->stringData.c_str());
|
||||||
|
return FALSE; // this idle handler will not be called again
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setTwoStepAuth(RequestData *data, PurpleRequestFields* fields)
|
||||||
|
{
|
||||||
|
std::unique_ptr<RequestData> request(data);
|
||||||
|
PurpleTdClient *tdClient = getTdClient(request->account);
|
||||||
|
|
||||||
|
if (tdClient) {
|
||||||
|
const char *oldPass = purple_request_fields_get_string(fields, "oldpw");
|
||||||
|
const char *password1 = purple_request_fields_get_string(fields, "pw1");
|
||||||
|
const char *password2 = purple_request_fields_get_string(fields, "pw2");
|
||||||
|
const char *hint = purple_request_fields_get_string(fields, "hint");
|
||||||
|
const char *email = purple_request_fields_get_string(fields, "email");
|
||||||
|
|
||||||
|
if ((password1 != password2) && (!password1 || !password2 || strcmp(password1, password2))) {
|
||||||
|
// Calling purple_request_fields synchronously causes glitch in pidgin
|
||||||
|
RequestData *newRequest = new RequestData(request->account);
|
||||||
|
if (email)
|
||||||
|
newRequest->stringData = email;
|
||||||
|
g_idle_add(reRequestTwoStepAuth, newRequest);
|
||||||
|
} else if (tdClient)
|
||||||
|
tdClient->setTwoStepAuth(oldPass, password1, hint, email);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void configureTwoStepAuth(PurplePluginAction *action)
|
||||||
|
{
|
||||||
|
PurpleConnection *gc = static_cast<PurpleConnection *>(action->context);
|
||||||
|
requestTwoStepAuth(gc, _("Enter new password and recovery e-mail address"), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static GList *tgprpl_actions (PurplePlugin *plugin, gpointer context)
|
static GList *tgprpl_actions (PurplePlugin *plugin, gpointer context)
|
||||||
{
|
{
|
||||||
return (GList *)NULL;
|
GList *actionsList = NULL;
|
||||||
|
PurplePluginAction *action;
|
||||||
|
|
||||||
|
action = purple_plugin_action_new(_("Configure two-step authentication..."),
|
||||||
|
configureTwoStepAuth);
|
||||||
|
actionsList = g_list_append(actionsList, action);
|
||||||
|
|
||||||
|
return actionsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PurplePluginInfo plugin_info = {
|
static PurplePluginInfo plugin_info = {
|
||||||
|
@@ -19,7 +19,7 @@ add_executable(tests EXCLUDE_FROM_ALL
|
|||||||
../td-client.cpp
|
../td-client.cpp
|
||||||
../transceiver.cpp
|
../transceiver.cpp
|
||||||
../account-data.cpp
|
../account-data.cpp
|
||||||
../chat-info.cpp
|
../purple-info.cpp
|
||||||
../config.cpp
|
../config.cpp
|
||||||
../client-utils.cpp
|
../client-utils.cpp
|
||||||
../format.cpp
|
../format.cpp
|
||||||
|
@@ -924,6 +924,11 @@ void purple_request_field_set_type_hint(PurpleRequestField *field,
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void purple_request_field_string_set_masked(PurpleRequestField *field,
|
||||||
|
gboolean masked)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
|
void purple_request_field_group_add_field(PurpleRequestFieldGroup *group,
|
||||||
PurpleRequestField *field)
|
PurpleRequestField *field)
|
||||||
{
|
{
|
||||||
@@ -967,4 +972,9 @@ void purple_menu_action_free(PurpleMenuAction *act)
|
|||||||
delete act;
|
delete act;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PurplePluginAction *purple_plugin_action_new(const char* label, void (*callback)(PurplePluginAction *))
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Reference in New Issue
Block a user