2020-08-10 15:17:29 +03:00
/*
2020-10-19 20:34:47 +03:00
Copyright ( C ) 2020 Sebastian J . Wolf and other contributors
2020-08-10 15:17:29 +03:00
This file is part of Fernschreiber .
2020-08-13 18:08:14 +03:00
Fernschreiber is free software : you can redistribute it and / or modify
2020-08-10 15:17:29 +03:00
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
2020-08-13 18:08:14 +03:00
Fernschreiber is distributed in the hope that it will be useful ,
2020-08-10 15:17:29 +03:00
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Fernschreiber . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "tdlibwrapper.h"
2020-08-13 00:51:09 +03:00
# include "tdlibsecrets.h"
# include <QDir>
2020-08-25 00:02:08 +03:00
# include <QFile>
# include <QFileInfo>
2020-08-13 00:51:09 +03:00
# include <QLocale>
2020-08-25 00:02:08 +03:00
# include <QProcess>
2020-08-13 00:51:09 +03:00
# include <QSysInfo>
2020-10-06 04:40:12 +03:00
# include <QDebug>
# include <QJsonDocument>
2020-08-25 00:02:08 +03:00
# include <QStandardPaths>
2020-08-28 11:41:18 +03:00
# include <QDBusConnection>
# include <QDBusInterface>
2020-08-10 15:17:29 +03:00
2020-10-04 00:48:09 +03:00
# define LOG(x) qDebug() << "[TDLibWrapper]" << x
2020-10-06 00:08:47 +03:00
# if defined (QT_DEBUG) || defined (DEBUG)
2020-10-04 00:48:09 +03:00
# define VERBOSE(x) LOG(x)
# else
# define VERBOSE(x)
# endif
2020-10-04 04:27:49 +03:00
namespace {
const QString STATUS ( " status " ) ;
2020-11-05 02:02:27 +03:00
const QString ID ( " id " ) ;
const QString TYPE ( " type " ) ;
2020-10-04 04:27:49 +03:00
const QString _TYPE ( " @type " ) ;
2020-10-19 13:20:02 +03:00
const QString _EXTRA ( " @extra " ) ;
2020-10-04 04:27:49 +03:00
}
2020-10-06 04:40:12 +03:00
TDLibWrapper : : TDLibWrapper ( QObject * parent ) : QObject ( parent )
2020-08-10 15:17:29 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Initializing TD Lib... " ) ;
2020-08-10 15:17:29 +03:00
this - > tdLibClient = td_json_client_create ( ) ;
2020-08-10 21:17:13 +03:00
this - > tdLibReceiver = new TDLibReceiver ( this - > tdLibClient , this ) ;
2020-08-12 11:50:01 +03:00
2020-08-13 00:51:09 +03:00
QString tdLibDatabaseDirectoryPath = QStandardPaths : : writableLocation ( QStandardPaths : : AppDataLocation ) + " /tdlib " ;
QDir tdLibDatabaseDirectory ( tdLibDatabaseDirectoryPath ) ;
if ( ! tdLibDatabaseDirectory . exists ( ) ) {
tdLibDatabaseDirectory . mkpath ( tdLibDatabaseDirectoryPath ) ;
}
2020-09-15 00:43:21 +03:00
this - > dbusInterface = new DBusInterface ( this ) ;
this - > initializeOpenWith ( ) ;
2020-08-12 11:50:01 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( versionDetected ( QString ) ) , this , SLOT ( handleVersionDetected ( QString ) ) ) ;
2020-10-01 01:55:26 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( authorizationStateChanged ( QString , QVariantMap ) ) , this , SLOT ( handleAuthorizationStateChanged ( QString , QVariantMap ) ) ) ;
2020-08-13 00:51:09 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( optionUpdated ( QString , QVariant ) ) , this , SLOT ( handleOptionUpdated ( QString , QVariant ) ) ) ;
2020-08-13 01:20:28 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( connectionStateChanged ( QString ) ) , this , SLOT ( handleConnectionStateChanged ( QString ) ) ) ;
2020-08-13 18:08:14 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( userUpdated ( QVariantMap ) ) , this , SLOT ( handleUserUpdated ( QVariantMap ) ) ) ;
2020-08-22 15:06:26 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( userStatusUpdated ( QString , QVariantMap ) ) , this , SLOT ( handleUserStatusUpdated ( QString , QVariantMap ) ) ) ;
2020-08-14 11:33:42 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( fileUpdated ( QVariantMap ) ) , this , SLOT ( handleFileUpdated ( QVariantMap ) ) ) ;
2020-08-16 18:38:51 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( newChatDiscovered ( QVariantMap ) ) , this , SLOT ( handleNewChatDiscovered ( QVariantMap ) ) ) ;
2020-08-17 00:31:20 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( unreadMessageCountUpdated ( QVariantMap ) ) , this , SLOT ( handleUnreadMessageCountUpdated ( QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( unreadChatCountUpdated ( QVariantMap ) ) , this , SLOT ( handleUnreadChatCountUpdated ( QVariantMap ) ) ) ;
2020-10-24 03:24:26 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( chatLastMessageUpdated ( QString , QString , QVariantMap ) ) , this , SIGNAL ( chatLastMessageUpdated ( QString , QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatOrderUpdated ( QString , QString ) ) , this , SIGNAL ( chatOrderUpdated ( QString , QString ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatReadInboxUpdated ( QString , QString , int ) ) , this , SIGNAL ( chatReadInboxUpdated ( QString , QString , int ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatReadOutboxUpdated ( QString , QString ) ) , this , SIGNAL ( chatReadOutboxUpdated ( QString , QString ) ) ) ;
2020-10-04 04:27:49 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( basicGroupUpdated ( qlonglong , QVariantMap ) ) , this , SLOT ( handleBasicGroupUpdated ( qlonglong , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( superGroupUpdated ( qlonglong , QVariantMap ) ) , this , SLOT ( handleSuperGroupUpdated ( qlonglong , QVariantMap ) ) ) ;
2020-10-24 03:24:26 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( chatOnlineMemberCountUpdated ( QString , int ) ) , this , SIGNAL ( chatOnlineMemberCountUpdated ( QString , int ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( messagesReceived ( QVariantList , int ) ) , this , SIGNAL ( messagesReceived ( QVariantList , int ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( newMessageReceived ( QString , QVariantMap ) ) , this , SIGNAL ( newMessageReceived ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( messageInformation ( QString , QVariantMap ) ) , this , SIGNAL ( receivedMessage ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( messageSendSucceeded ( QString , QString , QVariantMap ) ) , this , SIGNAL ( messageSendSucceeded ( QString , QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( activeNotificationsUpdated ( QVariantList ) ) , this , SIGNAL ( activeNotificationsUpdated ( QVariantList ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( notificationGroupUpdated ( QVariantMap ) ) , this , SIGNAL ( notificationGroupUpdated ( QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( notificationUpdated ( QVariantMap ) ) , this , SIGNAL ( notificationUpdated ( QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatNotificationSettingsUpdated ( QString , QVariantMap ) ) , this , SIGNAL ( chatNotificationSettingsUpdated ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( messageContentUpdated ( QString , QString , QVariantMap ) ) , this , SIGNAL ( messageContentUpdated ( QString , QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( messagesDeleted ( QString , QVariantList ) ) , this , SIGNAL ( messagesDeleted ( QString , QVariantList ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chats ( QVariantMap ) ) , this , SIGNAL ( chatsReceived ( QVariantMap ) ) ) ;
2020-11-05 02:02:27 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( chat ( QVariantMap ) ) , this , SLOT ( handleChatReceived ( QVariantMap ) ) ) ;
2020-10-24 03:24:26 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( recentStickersUpdated ( QVariantList ) ) , this , SIGNAL ( recentStickersUpdated ( QVariantList ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( stickers ( QVariantList ) ) , this , SIGNAL ( stickersReceived ( QVariantList ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( installedStickerSetsUpdated ( QVariantList ) ) , this , SIGNAL ( installedStickerSetsUpdated ( QVariantList ) ) ) ;
2020-10-06 00:08:47 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( stickerSets ( QVariantList ) ) , this , SLOT ( handleStickerSets ( QVariantList ) ) ) ;
2020-10-24 03:24:26 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( stickerSet ( QVariantMap ) ) , this , SIGNAL ( stickerSetReceived ( QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatMembers ( QString , QVariantList , int ) ) , this , SIGNAL ( chatMembersReceived ( QString , QVariantList , int ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( userFullInfo ( QVariantMap ) ) , this , SIGNAL ( userFullInfoReceived ( QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( userFullInfoUpdated ( QString , QVariantMap ) ) , this , SIGNAL ( userFullInfoUpdated ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( basicGroupFullInfo ( QString , QVariantMap ) ) , this , SIGNAL ( basicGroupFullInfoReceived ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( basicGroupFullInfoUpdated ( QString , QVariantMap ) ) , this , SIGNAL ( basicGroupFullInfoUpdated ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( supergroupFullInfo ( QString , QVariantMap ) ) , this , SIGNAL ( supergroupFullInfoReceived ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( supergroupFullInfoUpdated ( QString , QVariantMap ) ) , this , SIGNAL ( supergroupFullInfoUpdated ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( userProfilePhotos ( QString , QVariantList , int ) ) , this , SIGNAL ( userProfilePhotosReceived ( QString , QVariantList , int ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatPermissionsUpdated ( QString , QVariantMap ) ) , this , SIGNAL ( chatPermissionsUpdated ( QString , QVariantMap ) ) ) ;
connect ( this - > tdLibReceiver , SIGNAL ( chatTitleUpdated ( QString , QString ) ) , this , SIGNAL ( chatTitleUpdated ( QString , QString ) ) ) ;
2020-10-24 20:28:20 +03:00
connect ( this - > tdLibReceiver , SIGNAL ( usersReceived ( QString , QVariantList , int ) ) , this , SIGNAL ( usersReceived ( QString , QVariantList , int ) ) ) ;
2020-08-12 11:50:01 +03:00
2020-10-18 19:57:01 +03:00
connect ( & emojiSearchWorker , SIGNAL ( searchCompleted ( QString , QVariantList ) ) , this , SLOT ( handleEmojiSearchCompleted ( QString , QVariantList ) ) ) ;
2020-08-10 21:17:13 +03:00
this - > tdLibReceiver - > start ( ) ;
2020-08-14 11:33:42 +03:00
this - > setLogVerbosityLevel ( ) ;
2020-09-02 00:14:59 +03:00
this - > setOptionInteger ( " notification_group_count_max " , 5 ) ;
2020-08-10 15:17:29 +03:00
}
TDLibWrapper : : ~ TDLibWrapper ( )
{
2020-10-04 00:48:09 +03:00
LOG ( " Destroying TD Lib... " ) ;
2020-08-10 21:17:13 +03:00
this - > tdLibReceiver - > setActive ( false ) ;
while ( this - > tdLibReceiver - > isRunning ( ) ) {
QCoreApplication : : processEvents ( QEventLoop : : AllEvents , 1000 ) ;
}
2020-10-04 04:27:49 +03:00
qDeleteAll ( basicGroups . values ( ) ) ;
qDeleteAll ( superGroups . values ( ) ) ;
2020-08-10 15:17:29 +03:00
td_json_client_destroy ( this - > tdLibClient ) ;
}
2020-08-13 00:51:09 +03:00
void TDLibWrapper : : sendRequest ( const QVariantMap & requestObject )
{
2020-10-04 04:27:49 +03:00
LOG ( " Sending request to TD Lib, object type name: " < < requestObject . value ( _TYPE ) . toString ( ) ) ;
2020-08-13 00:51:09 +03:00
QJsonDocument requestDocument = QJsonDocument : : fromVariant ( requestObject ) ;
2020-10-04 00:48:09 +03:00
VERBOSE ( requestDocument . toJson ( ) . constData ( ) ) ;
2020-08-13 00:51:09 +03:00
td_json_client_send ( this - > tdLibClient , requestDocument . toJson ( ) . constData ( ) ) ;
}
2020-08-12 11:50:01 +03:00
QString TDLibWrapper : : getVersion ( )
{
return this - > version ;
}
2020-08-13 00:51:09 +03:00
TDLibWrapper : : AuthorizationState TDLibWrapper : : getAuthorizationState ( )
2020-08-12 11:50:01 +03:00
{
return this - > authorizationState ;
}
2020-10-01 01:55:26 +03:00
QVariantMap TDLibWrapper : : getAuthorizationStateData ( )
{
return this - > authorizationStateData ;
}
2020-08-13 01:20:28 +03:00
TDLibWrapper : : ConnectionState TDLibWrapper : : getConnectionState ( )
{
return this - > connectionState ;
}
2020-08-13 11:15:26 +03:00
void TDLibWrapper : : setAuthenticationPhoneNumber ( const QString & phoneNumber )
{
2020-10-04 00:48:09 +03:00
LOG ( " Set authentication phone number " < < phoneNumber ) ;
2020-08-13 11:15:26 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " setAuthenticationPhoneNumber " ) ;
2020-08-13 11:15:26 +03:00
requestObject . insert ( " phone_number " , phoneNumber ) ;
QVariantMap phoneNumberSettings ;
phoneNumberSettings . insert ( " allow_flash_call " , false ) ;
phoneNumberSettings . insert ( " is_current_phone_number " , true ) ;
requestObject . insert ( " settings " , phoneNumberSettings ) ;
this - > sendRequest ( requestObject ) ;
}
2020-08-13 16:35:43 +03:00
void TDLibWrapper : : setAuthenticationCode ( const QString & authenticationCode )
{
2020-10-04 00:48:09 +03:00
LOG ( " Set authentication code " < < authenticationCode ) ;
2020-08-13 16:35:43 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " checkAuthenticationCode " ) ;
2020-08-13 16:35:43 +03:00
requestObject . insert ( " code " , authenticationCode ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-16 23:36:43 +03:00
void TDLibWrapper : : setAuthenticationPassword ( const QString & authenticationPassword )
{
2020-10-04 00:48:09 +03:00
LOG ( " Set authentication password " < < authenticationPassword ) ;
2020-09-16 23:36:43 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " checkAuthenticationPassword " ) ;
2020-09-16 23:36:43 +03:00
requestObject . insert ( " password " , authenticationPassword ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-01 01:55:26 +03:00
void TDLibWrapper : : registerUser ( const QString & firstName , const QString & lastName )
{
qDebug ( ) < < " [TDLibWrapper] Register User " < < firstName < < lastName ;
QVariantMap requestObject ;
requestObject . insert ( " @type " , " registerUser " ) ;
requestObject . insert ( " first_name " , firstName ) ;
requestObject . insert ( " last_name " , lastName ) ;
this - > sendRequest ( requestObject ) ;
}
2020-08-13 23:32:35 +03:00
void TDLibWrapper : : getChats ( )
{
2020-10-04 00:48:09 +03:00
LOG ( " Getting chats " ) ;
2020-08-13 23:32:35 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " getChats " ) ;
2020-08-16 18:38:51 +03:00
requestObject . insert ( " limit " , 5 ) ;
2020-08-13 23:32:35 +03:00
this - > sendRequest ( requestObject ) ;
}
2020-08-14 11:33:42 +03:00
void TDLibWrapper : : downloadFile ( const QString & fileId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Downloading file " < < fileId ) ;
2020-08-14 11:33:42 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " downloadFile " ) ;
2020-08-14 11:33:42 +03:00
requestObject . insert ( " file_id " , fileId ) ;
requestObject . insert ( " synchronous " , false ) ;
requestObject . insert ( " offset " , 0 ) ;
requestObject . insert ( " limit " , 0 ) ;
requestObject . insert ( " priority " , 1 ) ;
this - > sendRequest ( requestObject ) ;
}
2020-08-21 15:47:08 +03:00
void TDLibWrapper : : openChat ( const QString & chatId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Opening chat " < < chatId ) ;
2020-08-21 15:47:08 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " openChat " ) ;
2020-08-21 15:47:08 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : closeChat ( const QString & chatId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Closing chat " < < chatId ) ;
2020-08-21 15:47:08 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " closeChat " ) ;
2020-08-21 15:47:08 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
this - > sendRequest ( requestObject ) ;
}
2020-11-07 22:29:44 +03:00
void TDLibWrapper : : joinChat ( const QString & chatId )
{
LOG ( " Joining chat " < < chatId ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " joinChat " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-19 13:20:02 +03:00
void TDLibWrapper : : leaveChat ( const QString & chatId )
{
LOG ( " Leaving chat " < < chatId ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " leaveChat " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : getChatHistory ( const QString & chatId , const qlonglong & fromMessageId , int offset , int limit , bool onlyLocal )
2020-08-22 18:30:02 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Retrieving chat history " < < chatId < < fromMessageId < < offset < < limit < < onlyLocal ) ;
2020-08-22 18:30:02 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " getChatHistory " ) ;
2020-08-22 18:30:02 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " from_message_id " , fromMessageId ) ;
requestObject . insert ( " offset " , offset ) ;
requestObject . insert ( " limit " , limit ) ;
requestObject . insert ( " only_local " , onlyLocal ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : viewMessage ( const QString & chatId , const QString & messageId , bool force )
2020-08-23 00:05:45 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Mark message as viewed " < < chatId < < messageId ) ;
2020-08-23 00:05:45 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " viewMessages " ) ;
2020-08-23 00:05:45 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
2020-10-19 16:30:03 +03:00
requestObject . insert ( " force_read " , force ) ;
2020-08-23 00:05:45 +03:00
QVariantList messageIds ;
messageIds . append ( messageId ) ;
requestObject . insert ( " message_ids " , messageIds ) ;
this - > sendRequest ( requestObject ) ;
}
2020-08-28 18:40:25 +03:00
void TDLibWrapper : : sendTextMessage ( const QString & chatId , const QString & message , const QString & replyToMessageId )
2020-08-23 01:17:34 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Sending text message " < < chatId < < message < < replyToMessageId ) ;
2020-08-23 01:17:34 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " sendMessage " ) ;
2020-08-23 01:17:34 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
2020-08-28 18:40:25 +03:00
if ( replyToMessageId ! = " 0 " ) {
requestObject . insert ( " reply_to_message_id " , replyToMessageId ) ;
}
2020-08-23 01:17:34 +03:00
QVariantMap inputMessageContent ;
2020-10-04 04:27:49 +03:00
inputMessageContent . insert ( _TYPE , " inputMessageText " ) ;
2020-08-23 01:17:34 +03:00
QVariantMap formattedText ;
formattedText . insert ( " text " , message ) ;
2020-10-04 04:27:49 +03:00
formattedText . insert ( _TYPE , " formattedText " ) ;
2020-08-23 01:17:34 +03:00
inputMessageContent . insert ( " text " , formattedText ) ;
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-27 14:49:06 +03:00
void TDLibWrapper : : sendPhotoMessage ( const QString & chatId , const QString & filePath , const QString & message , const QString & replyToMessageId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Sending photo message " < < chatId < < filePath < < message < < replyToMessageId ) ;
2020-09-27 14:49:06 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " sendMessage " ) ;
2020-09-27 14:49:06 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
if ( replyToMessageId ! = " 0 " ) {
requestObject . insert ( " reply_to_message_id " , replyToMessageId ) ;
}
QVariantMap inputMessageContent ;
2020-10-04 04:27:49 +03:00
inputMessageContent . insert ( _TYPE , " inputMessagePhoto " ) ;
2020-09-27 14:49:06 +03:00
QVariantMap formattedText ;
formattedText . insert ( " text " , message ) ;
2020-10-04 04:27:49 +03:00
formattedText . insert ( _TYPE , " formattedText " ) ;
2020-09-27 14:49:06 +03:00
inputMessageContent . insert ( " caption " , formattedText ) ;
QVariantMap photoInputFile ;
2020-10-04 04:27:49 +03:00
photoInputFile . insert ( _TYPE , " inputFileLocal " ) ;
2020-09-27 14:49:06 +03:00
photoInputFile . insert ( " path " , filePath ) ;
inputMessageContent . insert ( " photo " , photoInputFile ) ;
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-28 00:24:22 +03:00
void TDLibWrapper : : sendVideoMessage ( const QString & chatId , const QString & filePath , const QString & message , const QString & replyToMessageId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Sending video message " < < chatId < < filePath < < message < < replyToMessageId ) ;
2020-09-28 00:24:22 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " sendMessage " ) ;
2020-09-28 00:24:22 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
if ( replyToMessageId ! = " 0 " ) {
requestObject . insert ( " reply_to_message_id " , replyToMessageId ) ;
}
QVariantMap inputMessageContent ;
2020-10-04 04:27:49 +03:00
inputMessageContent . insert ( _TYPE , " inputMessageVideo " ) ;
2020-09-28 00:24:22 +03:00
QVariantMap formattedText ;
formattedText . insert ( " text " , message ) ;
2020-10-04 04:27:49 +03:00
formattedText . insert ( _TYPE , " formattedText " ) ;
2020-09-28 00:24:22 +03:00
inputMessageContent . insert ( " caption " , formattedText ) ;
QVariantMap videoInputFile ;
2020-10-04 04:27:49 +03:00
videoInputFile . insert ( _TYPE , " inputFileLocal " ) ;
2020-09-28 00:24:22 +03:00
videoInputFile . insert ( " path " , filePath ) ;
inputMessageContent . insert ( " video " , videoInputFile ) ;
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : sendDocumentMessage ( const QString & chatId , const QString & filePath , const QString & message , const QString & replyToMessageId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Sending document message " < < chatId < < filePath < < message < < replyToMessageId ) ;
2020-09-28 00:24:22 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " sendMessage " ) ;
2020-09-28 00:24:22 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
if ( replyToMessageId ! = " 0 " ) {
requestObject . insert ( " reply_to_message_id " , replyToMessageId ) ;
}
QVariantMap inputMessageContent ;
2020-10-04 04:27:49 +03:00
inputMessageContent . insert ( _TYPE , " inputMessageDocument " ) ;
2020-09-28 00:24:22 +03:00
QVariantMap formattedText ;
formattedText . insert ( " text " , message ) ;
2020-10-04 04:27:49 +03:00
formattedText . insert ( _TYPE , " formattedText " ) ;
2020-09-28 00:24:22 +03:00
inputMessageContent . insert ( " caption " , formattedText ) ;
QVariantMap documentInputFile ;
2020-10-04 04:27:49 +03:00
documentInputFile . insert ( _TYPE , " inputFileLocal " ) ;
2020-09-28 00:24:22 +03:00
documentInputFile . insert ( " path " , filePath ) ;
inputMessageContent . insert ( " document " , documentInputFile ) ;
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-16 00:43:55 +03:00
void TDLibWrapper : : sendStickerMessage ( const QString & chatId , const QString & fileId , const QString & replyToMessageId )
2020-10-12 23:44:21 +03:00
{
2020-10-16 00:43:55 +03:00
LOG ( " Sending sticker message " < < chatId < < fileId < < replyToMessageId ) ;
2020-10-12 23:44:21 +03:00
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " sendMessage " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
if ( replyToMessageId ! = " 0 " ) {
requestObject . insert ( " reply_to_message_id " , replyToMessageId ) ;
}
QVariantMap inputMessageContent ;
inputMessageContent . insert ( _TYPE , " inputMessageSticker " ) ;
2020-10-15 00:25:56 +03:00
QVariantMap stickerInputFile ;
2020-10-16 00:43:55 +03:00
stickerInputFile . insert ( _TYPE , " inputFileRemote " ) ;
stickerInputFile . insert ( " id " , fileId ) ;
2020-10-15 00:25:56 +03:00
inputMessageContent . insert ( " sticker " , stickerInputFile ) ;
2020-10-12 23:44:21 +03:00
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-23 11:29:50 +03:00
void TDLibWrapper : : sendPollMessage ( const QString & chatId , const QString & question , const QVariantList & options , const bool & anonymous , const int & correctOption , const bool & multiple , const QString & replyToMessageId )
{
LOG ( " Sending poll message " < < chatId < < question < < replyToMessageId ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " sendMessage " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
if ( replyToMessageId ! = " 0 " ) {
requestObject . insert ( " reply_to_message_id " , replyToMessageId ) ;
}
QVariantMap inputMessageContent ;
inputMessageContent . insert ( _TYPE , " inputMessagePoll " ) ;
QVariantMap pollType ;
if ( correctOption > - 1 ) {
pollType . insert ( _TYPE , " pollTypeQuiz " ) ;
pollType . insert ( " correct_option_id " , correctOption ) ;
} else {
pollType . insert ( _TYPE , " pollTypeRegular " ) ;
pollType . insert ( " allow_multiple_answers " , multiple ) ;
}
inputMessageContent . insert ( " type " , pollType ) ;
inputMessageContent . insert ( " question " , question ) ;
inputMessageContent . insert ( " options " , options ) ;
inputMessageContent . insert ( " is_anonymous " , anonymous ) ;
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
2020-08-25 17:42:46 +03:00
void TDLibWrapper : : getMessage ( const QString & chatId , const QString & messageId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Retrieving message " < < chatId < < messageId ) ;
2020-08-25 17:42:46 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " getMessage " ) ;
2020-08-25 17:42:46 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " message_id " , messageId ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : setOptionInteger ( const QString & optionName , int optionValue )
2020-09-02 00:14:59 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Setting integer option " < < optionName < < optionValue ) ;
2020-09-02 00:14:59 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " setOption " ) ;
2020-09-02 00:14:59 +03:00
requestObject . insert ( " name " , optionName ) ;
QVariantMap optionValueMap ;
2020-10-04 04:27:49 +03:00
optionValueMap . insert ( _TYPE , " optionValueInteger " ) ;
2020-09-02 00:14:59 +03:00
optionValueMap . insert ( " value " , optionValue ) ;
requestObject . insert ( " value " , optionValueMap ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-16 01:15:43 +03:00
void TDLibWrapper : : setChatNotificationSettings ( const QString & chatId , const QVariantMap & notificationSettings )
{
2020-10-04 00:48:09 +03:00
LOG ( " Notification settings for chat " < < chatId < < notificationSettings ) ;
2020-09-16 01:15:43 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " setChatNotificationSettings " ) ;
2020-09-16 01:15:43 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " notification_settings " , notificationSettings ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-19 21:33:51 +03:00
void TDLibWrapper : : editMessageText ( const QString & chatId , const QString & messageId , const QString & message )
{
2020-10-04 00:48:09 +03:00
LOG ( " Editing message text " < < chatId < < messageId ) ;
2020-09-19 21:33:51 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " editMessageText " ) ;
2020-09-19 21:33:51 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " message_id " , messageId ) ;
QVariantMap inputMessageContent ;
2020-10-04 04:27:49 +03:00
inputMessageContent . insert ( _TYPE , " inputMessageText " ) ;
2020-09-19 21:33:51 +03:00
QVariantMap formattedText ;
formattedText . insert ( " text " , message ) ;
inputMessageContent . insert ( " text " , formattedText ) ;
requestObject . insert ( " input_message_content " , inputMessageContent ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-20 01:13:42 +03:00
void TDLibWrapper : : deleteMessages ( const QString & chatId , const QVariantList messageIds )
{
2020-10-04 00:48:09 +03:00
LOG ( " Deleting some messages " < < chatId < < messageIds ) ;
2020-09-20 01:13:42 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " deleteMessages " ) ;
2020-09-20 01:13:42 +03:00
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " message_ids " , messageIds ) ;
requestObject . insert ( " revoke " , true ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : getMapThumbnailFile ( const QString & chatId , double latitude , double longitude , int width , int height )
2020-09-28 23:58:11 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Getting Map Thumbnail File " < < chatId ) ;
2020-09-28 23:58:11 +03:00
QVariantMap location ;
location . insert ( " latitude " , latitude ) ;
location . insert ( " longitude " , longitude ) ;
// ensure dimensions are in bounds (16 - 1024)
int boundsWidth = std : : min ( std : : max ( width , 16 ) , 1024 ) ;
int boundsHeight = std : : min ( std : : max ( height , 16 ) , 1024 ) ;
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " getMapThumbnailFile " ) ;
2020-09-28 23:58:11 +03:00
requestObject . insert ( " location " , location ) ;
requestObject . insert ( " zoom " , 17 ) ; //13-20
requestObject . insert ( " width " , boundsWidth ) ;
requestObject . insert ( " height " , boundsHeight ) ;
requestObject . insert ( " scale " , 1 ) ; // 1-3
requestObject . insert ( " chat_id " , chatId ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-06 00:08:47 +03:00
void TDLibWrapper : : getRecentStickers ( )
{
LOG ( " Retrieving recent stickers " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getRecentStickers " ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : getInstalledStickerSets ( )
{
LOG ( " Retrieving installed sticker sets " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getInstalledStickerSets " ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-15 00:25:56 +03:00
void TDLibWrapper : : getStickerSet ( const QString & setId )
{
LOG ( " Retrieving sticker set " < < setId ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getStickerSet " ) ;
requestObject . insert ( " set_id " , setId ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : getSupergroupMembers ( const QString & groupId , int limit , int offset )
2020-10-19 13:20:02 +03:00
{
LOG ( " Retrieving SupergroupMembers " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getSupergroupMembers " ) ;
requestObject . insert ( _EXTRA , groupId ) ;
requestObject . insert ( " supergroup_id " , groupId ) ;
requestObject . insert ( " offset " , offset ) ;
requestObject . insert ( " limit " , limit ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : getGroupFullInfo ( const QString & groupId , bool isSuperGroup )
2020-10-19 13:20:02 +03:00
{
LOG ( " Retrieving GroupFullInfo " ) ;
QVariantMap requestObject ;
if ( isSuperGroup ) {
requestObject . insert ( _TYPE , " getSupergroupFullInfo " ) ;
requestObject . insert ( " supergroup_id " , groupId ) ;
} else {
requestObject . insert ( _TYPE , " getBasicGroupFullInfo " ) ;
requestObject . insert ( " basic_group_id " , groupId ) ;
}
requestObject . insert ( _EXTRA , groupId ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : getUserFullInfo ( const QString & userId )
{
LOG ( " Retrieving UserFullInfo " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getUserFullInfo " ) ;
requestObject . insert ( _EXTRA , userId ) ;
requestObject . insert ( " user_id " , userId ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : createPrivateChat ( const QString & userId )
{
LOG ( " Creating Private Chat " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " createPrivateChat " ) ;
requestObject . insert ( " user_id " , userId ) ;
requestObject . insert ( _EXTRA , " openDirectly " ) ; //gets matched in qml
this - > sendRequest ( requestObject ) ;
}
2020-11-05 02:02:27 +03:00
void TDLibWrapper : : createSupergroupChat ( const QString & supergroupId )
{
LOG ( " Creating Supergroup Chat " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " createSupergroupChat " ) ;
requestObject . insert ( " supergroup_id " , supergroupId ) ;
requestObject . insert ( _EXTRA , " openDirectly " ) ; //gets matched in qml
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : createBasicGroupChat ( const QString & basicGroupId )
{
LOG ( " Creating Basic Group Chat " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " createBasicGroupChat " ) ;
requestObject . insert ( " basic_group_id " , basicGroupId ) ;
requestObject . insert ( _EXTRA , " openDirectly " ) ; //gets matched in qml
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : getGroupsInCommon ( const QString & userId , int limit , int offset )
2020-10-19 13:20:02 +03:00
{
LOG ( " Retrieving Groups in Common " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getGroupsInCommon " ) ;
requestObject . insert ( _EXTRA , userId ) ;
requestObject . insert ( " user_id " , userId ) ;
requestObject . insert ( " offset " , offset ) ;
requestObject . insert ( " limit " , limit ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : getUserProfilePhotos ( const QString & userId , int limit , int offset )
2020-10-19 13:20:02 +03:00
{
LOG ( " Retrieving User Profile Photos " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getUserProfilePhotos " ) ;
requestObject . insert ( _EXTRA , userId ) ;
requestObject . insert ( " user_id " , userId ) ;
requestObject . insert ( " offset " , offset ) ;
requestObject . insert ( " limit " , limit ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : setChatPermissions ( const QString & chatId , const QVariantMap & chatPermissions )
{
LOG ( " Setting Chat Permissions " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " setChatPermissions " ) ;
requestObject . insert ( _EXTRA , chatId ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " permissions " , chatPermissions ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : setChatSlowModeDelay ( const QString & chatId , int delay )
2020-10-19 13:20:02 +03:00
{
LOG ( " Setting Chat Slow Mode Delay " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " setChatSlowModeDelay " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " slow_mode_delay " , delay ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : setChatDescription ( const QString & chatId , const QString & description )
{
LOG ( " Setting Chat Description " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " setChatDescription " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " description " , description ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : setChatTitle ( const QString & chatId , const QString & title )
{
LOG ( " Setting Chat Title " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " setChatTitle " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " title " , title ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : setBio ( const QString & bio )
{
LOG ( " Setting Bio " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " setBio " ) ;
requestObject . insert ( " bio " , bio ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : toggleSupergroupIsAllHistoryAvailable ( const QString & groupId , bool isAllHistoryAvailable )
2020-10-19 13:20:02 +03:00
{
LOG ( " Toggling SupergroupIsAllHistoryAvailable " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " toggleSupergroupIsAllHistoryAvailable " ) ;
requestObject . insert ( " supergroup_id " , groupId ) ;
requestObject . insert ( " is_all_history_available " , isAllHistoryAvailable ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-15 00:25:56 +03:00
2020-10-23 11:29:50 +03:00
void TDLibWrapper : : setPollAnswer ( const QString & chatId , const qlonglong & messageId , QVariantList optionIds )
{
LOG ( " Setting Poll Answer " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " setPollAnswer " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " message_id " , messageId ) ;
requestObject . insert ( " option_ids " , optionIds ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : stopPoll ( const QString & chatId , const qlonglong & messageId )
{
LOG ( " Stopping Poll " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " stopPoll " ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " message_id " , messageId ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : getPollVoters ( const QString & chatId , const qlonglong & messageId , const int & optionId , const int & limit , const int & offset , const QString & extra )
{
LOG ( " Retrieving Poll Voters " ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " getPollVoters " ) ;
requestObject . insert ( _EXTRA , extra ) ;
requestObject . insert ( " chat_id " , chatId ) ;
requestObject . insert ( " message_id " , messageId ) ;
requestObject . insert ( " option_id " , optionId ) ;
requestObject . insert ( " offset " , offset ) ;
requestObject . insert ( " limit " , limit ) ; //max 50
this - > sendRequest ( requestObject ) ;
}
2020-11-04 01:39:09 +03:00
void TDLibWrapper : : searchPublicChat ( const QString & userName )
{
LOG ( " Search public chat " < < userName ) ;
2020-11-05 02:02:27 +03:00
this - > activeChatSearchName = userName ;
2020-11-04 01:39:09 +03:00
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " searchPublicChat " ) ;
requestObject . insert ( " username " , userName ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : joinChatByInviteLink ( const QString & inviteLink )
{
LOG ( " Join chat by invite link " < < inviteLink ) ;
QVariantMap requestObject ;
requestObject . insert ( _TYPE , " joinChatByInviteLink " ) ;
requestObject . insert ( " invite_link " , inviteLink ) ;
this - > sendRequest ( requestObject ) ;
}
2020-10-18 19:57:01 +03:00
void TDLibWrapper : : searchEmoji ( const QString & queryString )
{
LOG ( " Searching emoji " < < queryString ) ;
while ( this - > emojiSearchWorker . isRunning ( ) ) {
this - > emojiSearchWorker . requestInterruption ( ) ;
}
this - > emojiSearchWorker . setParameters ( queryString ) ;
this - > emojiSearchWorker . start ( ) ;
}
2020-08-13 23:32:35 +03:00
QVariantMap TDLibWrapper : : getUserInformation ( )
{
return this - > userInformation ;
}
2020-08-16 18:38:51 +03:00
QVariantMap TDLibWrapper : : getUserInformation ( const QString & userId )
{
2020-10-04 00:48:09 +03:00
// LOG("Returning user information for ID" << userId);
2020-08-20 01:24:24 +03:00
return this - > allUsers . value ( userId ) . toMap ( ) ;
2020-08-16 18:38:51 +03:00
}
2020-11-04 00:21:01 +03:00
QVariantMap TDLibWrapper : : getUserInformationByName ( const QString & userName )
{
return this - > allUserNames . value ( userName ) . toMap ( ) ;
}
2020-08-17 00:31:20 +03:00
QVariantMap TDLibWrapper : : getUnreadMessageInformation ( )
{
return this - > unreadMessageInformation ;
}
QVariantMap TDLibWrapper : : getUnreadChatInformation ( )
{
return this - > unreadChatInformation ;
}
2020-10-04 04:27:49 +03:00
QVariantMap TDLibWrapper : : getBasicGroup ( qlonglong groupId ) const
2020-08-21 19:03:51 +03:00
{
2020-10-04 04:27:49 +03:00
const Group * group = basicGroups . value ( groupId ) ;
if ( group ) {
LOG ( " Returning basic group information for ID " < < groupId ) ;
return group - > groupInfo ;
} else {
LOG ( " No super group information for ID " < < groupId ) ;
return QVariantMap ( ) ;
}
2020-08-21 19:03:51 +03:00
}
2020-10-04 04:27:49 +03:00
QVariantMap TDLibWrapper : : getSuperGroup ( qlonglong groupId ) const
2020-08-21 19:03:51 +03:00
{
2020-10-04 04:27:49 +03:00
const Group * group = superGroups . value ( groupId ) ;
if ( group ) {
LOG ( " Returning super group information for ID " < < groupId ) ;
return group - > groupInfo ;
} else {
LOG ( " No super group information for ID " < < groupId ) ;
return QVariantMap ( ) ;
}
2020-08-21 19:03:51 +03:00
}
2020-09-15 22:17:44 +03:00
QVariantMap TDLibWrapper : : getChat ( const QString & chatId )
{
2020-10-04 00:48:09 +03:00
LOG ( " Returning chat information for ID " < < chatId ) ;
2020-09-15 22:17:44 +03:00
return this - > chats . value ( chatId ) . toMap ( ) ;
}
2020-11-04 01:39:09 +03:00
QString TDLibWrapper : : getOptionString ( const QString & optionName )
{
return this - > options . value ( optionName ) . toString ( ) ;
}
2020-08-28 12:43:51 +03:00
void TDLibWrapper : : copyFileToDownloads ( const QString & filePath )
2020-08-25 00:02:08 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Copy file to downloads " < < filePath ) ;
2020-08-25 00:02:08 +03:00
QFileInfo fileInfo ( filePath ) ;
if ( fileInfo . exists ( ) ) {
QString downloadFilePath = QStandardPaths : : writableLocation ( QStandardPaths : : DownloadLocation ) + " / " + fileInfo . fileName ( ) ;
2020-10-18 23:14:48 +03:00
if ( QFile : : exists ( downloadFilePath ) ) {
2020-08-25 00:02:08 +03:00
emit copyToDownloadsSuccessful ( fileInfo . fileName ( ) , downloadFilePath ) ;
} else {
2020-10-18 23:14:48 +03:00
if ( QFile : : copy ( filePath , downloadFilePath ) ) {
emit copyToDownloadsSuccessful ( fileInfo . fileName ( ) , downloadFilePath ) ;
} else {
emit copyToDownloadsError ( fileInfo . fileName ( ) , downloadFilePath ) ;
}
2020-08-25 00:02:08 +03:00
}
} else {
emit copyToDownloadsError ( fileInfo . fileName ( ) , filePath ) ;
}
}
2020-08-28 17:18:33 +03:00
void TDLibWrapper : : openFileOnDevice ( const QString & filePath )
2020-08-25 00:02:08 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Open file on device: " < < filePath ) ;
2020-08-25 00:02:08 +03:00
QStringList argumentsList ;
2020-08-28 17:18:33 +03:00
argumentsList . append ( filePath ) ;
2020-08-25 00:02:08 +03:00
bool successfullyStarted = QProcess : : startDetached ( " xdg-open " , argumentsList ) ;
if ( successfullyStarted ) {
2020-08-28 17:18:33 +03:00
qDebug ( ) < < " Successfully opened file " < < filePath ;
2020-08-25 00:02:08 +03:00
} else {
2020-08-28 17:18:33 +03:00
qDebug ( ) < < " Error opening file " < < filePath ;
2020-08-25 00:02:08 +03:00
}
}
2020-10-24 02:05:49 +03:00
void TDLibWrapper : : controlScreenSaver ( bool enabled )
2020-08-28 11:41:18 +03:00
{
2020-10-04 00:48:09 +03:00
LOG ( " Controlling device screen saver " < < enabled ) ;
2020-08-28 11:41:18 +03:00
QDBusConnection dbusConnection = QDBusConnection : : connectToBus ( QDBusConnection : : SystemBus , " system " ) ;
QDBusInterface dbusInterface ( " com.nokia.mce " , " /com/nokia/mce/request " , " com.nokia.mce.request " , dbusConnection ) ;
if ( enabled ) {
qDebug ( ) < < " Enabling screensaver " ;
dbusInterface . call ( " req_display_cancel_blanking_pause " ) ;
} else {
qDebug ( ) < < " Disabling screensaver " ;
dbusInterface . call ( " req_display_blanking_pause " ) ;
}
}
2020-09-15 00:43:21 +03:00
DBusAdaptor * TDLibWrapper : : getDBusAdaptor ( )
{
return this - > dbusInterface - > getDBusAdaptor ( ) ;
}
2020-08-12 11:50:01 +03:00
void TDLibWrapper : : handleVersionDetected ( const QString & version )
{
this - > version = version ;
emit versionDetected ( version ) ;
}
2020-10-01 01:55:26 +03:00
void TDLibWrapper : : handleAuthorizationStateChanged ( const QString & authorizationState , const QVariantMap authorizationStateData )
2020-08-12 11:50:01 +03:00
{
2020-08-13 01:20:28 +03:00
if ( authorizationState = = " authorizationStateClosed " ) {
2020-08-13 00:51:09 +03:00
this - > authorizationState = AuthorizationState : : Closed ;
}
if ( authorizationState = = " authorizationStateClosing " ) {
this - > authorizationState = AuthorizationState : : Closing ;
}
if ( authorizationState = = " authorizationStateLoggingOut " ) {
this - > authorizationState = AuthorizationState : : LoggingOut ;
}
if ( authorizationState = = " authorizationStateReady " ) {
2020-08-13 11:15:26 +03:00
this - > authorizationState = AuthorizationState : : AuthorizationReady ;
2020-08-13 00:51:09 +03:00
}
if ( authorizationState = = " authorizationStateWaitCode " ) {
this - > authorizationState = AuthorizationState : : WaitCode ;
}
if ( authorizationState = = " authorizationStateWaitEncryptionKey " ) {
this - > setEncryptionKey ( ) ;
this - > authorizationState = AuthorizationState : : WaitEncryptionKey ;
}
if ( authorizationState = = " authorizationStateWaitOtherDeviceConfirmation " ) {
this - > authorizationState = AuthorizationState : : WaitOtherDeviceConfirmation ;
}
if ( authorizationState = = " authorizationStateWaitPassword " ) {
this - > authorizationState = AuthorizationState : : WaitPassword ;
}
if ( authorizationState = = " authorizationStateWaitPhoneNumber " ) {
this - > authorizationState = AuthorizationState : : WaitPhoneNumber ;
}
if ( authorizationState = = " authorizationStateWaitRegistration " ) {
this - > authorizationState = AuthorizationState : : WaitRegistration ;
}
if ( authorizationState = = " authorizationStateWaitTdlibParameters " ) {
this - > setInitialParameters ( ) ;
this - > authorizationState = AuthorizationState : : WaitTdlibParameters ;
}
2020-10-01 01:55:26 +03:00
this - > authorizationStateData = authorizationStateData ;
emit authorizationStateChanged ( this - > authorizationState , this - > authorizationStateData ) ;
2020-08-13 00:51:09 +03:00
}
void TDLibWrapper : : handleOptionUpdated ( const QString & optionName , const QVariant & optionValue )
{
this - > options . insert ( optionName , optionValue ) ;
emit optionUpdated ( optionName , optionValue ) ;
2020-08-20 01:24:24 +03:00
if ( optionName = = " my_id " ) {
emit ownUserIdFound ( optionValue . toString ( ) ) ;
}
2020-08-13 00:51:09 +03:00
}
2020-08-13 01:20:28 +03:00
void TDLibWrapper : : handleConnectionStateChanged ( const QString & connectionState )
{
if ( connectionState = = " connectionStateConnecting " ) {
this - > connectionState = ConnectionState : : Connecting ;
}
if ( connectionState = = " connectionStateConnectingToProxy " ) {
this - > connectionState = ConnectionState : : ConnectingToProxy ;
}
if ( connectionState = = " connectionStateReady " ) {
2020-08-13 11:15:26 +03:00
this - > connectionState = ConnectionState : : ConnectionReady ;
2020-08-13 01:20:28 +03:00
}
if ( connectionState = = " connectionStateUpdating " ) {
this - > connectionState = ConnectionState : : Updating ;
}
if ( connectionState = = " connectionStateWaitingForNetwork " ) {
this - > connectionState = ConnectionState : : WaitingForNetwork ;
}
emit connectionStateChanged ( this - > connectionState ) ;
}
2020-08-13 18:08:14 +03:00
void TDLibWrapper : : handleUserUpdated ( const QVariantMap & userInformation )
{
2020-08-16 18:38:51 +03:00
QString updatedUserId = userInformation . value ( " id " ) . toString ( ) ;
if ( updatedUserId = = this - > options . value ( " my_id " ) . toString ( ) ) {
2020-10-04 00:48:09 +03:00
LOG ( " Own user information updated :) " ) ;
2020-08-13 18:08:14 +03:00
this - > userInformation = userInformation ;
}
2020-10-04 00:48:09 +03:00
LOG ( " User information updated: " < < userInformation . value ( " username " ) . toString ( ) < < userInformation . value ( " first_name " ) . toString ( ) < < userInformation . value ( " last_name " ) . toString ( ) ) ;
2020-08-20 01:24:24 +03:00
this - > allUsers . insert ( updatedUserId , userInformation ) ;
2020-11-04 00:21:01 +03:00
this - > allUserNames . insert ( userInformation . value ( " username " ) . toString ( ) , userInformation ) ;
2020-08-21 19:03:51 +03:00
emit userUpdated ( updatedUserId , userInformation ) ;
2020-08-13 18:08:14 +03:00
}
2020-08-22 15:06:26 +03:00
void TDLibWrapper : : handleUserStatusUpdated ( const QString & userId , const QVariantMap & userStatusInformation )
{
if ( userId = = this - > options . value ( " my_id " ) . toString ( ) ) {
2020-10-04 00:48:09 +03:00
LOG ( " Own user status information updated :) " ) ;
2020-08-22 15:06:26 +03:00
this - > userInformation . insert ( " status " , userStatusInformation ) ;
}
2020-10-04 04:27:49 +03:00
LOG ( " User status information updated: " < < userId < < userStatusInformation . value ( _TYPE ) . toString ( ) ) ;
2020-08-22 15:06:26 +03:00
QVariantMap updatedUserInformation = this - > allUsers . value ( userId ) . toMap ( ) ;
updatedUserInformation . insert ( " status " , userStatusInformation ) ;
this - > allUsers . insert ( userId , updatedUserInformation ) ;
2020-11-04 00:21:01 +03:00
this - > allUserNames . insert ( userInformation . value ( " username " ) . toString ( ) , userInformation ) ;
2020-08-22 15:06:26 +03:00
emit userUpdated ( userId , updatedUserInformation ) ;
}
2020-08-16 18:38:51 +03:00
void TDLibWrapper : : handleFileUpdated ( const QVariantMap & fileInformation )
{
emit fileUpdated ( fileInformation . value ( " id " ) . toInt ( ) , fileInformation ) ;
}
void TDLibWrapper : : handleNewChatDiscovered ( const QVariantMap & chatInformation )
2020-08-14 11:33:42 +03:00
{
2020-08-16 18:38:51 +03:00
QString chatId = chatInformation . value ( " id " ) . toString ( ) ;
this - > chats . insert ( chatId , chatInformation ) ;
emit newChatDiscovered ( chatId , chatInformation ) ;
2020-08-14 11:33:42 +03:00
}
2020-11-05 02:02:27 +03:00
void TDLibWrapper : : handleChatReceived ( const QVariantMap & chatInformation )
{
emit chatReceived ( chatInformation ) ;
if ( ! this - > activeChatSearchName . isEmpty ( ) ) {
QVariantMap chatType = chatInformation . value ( TYPE ) . toMap ( ) ;
ChatType receivedChatType = chatTypeFromString ( chatType . value ( _TYPE ) . toString ( ) ) ;
if ( receivedChatType = = ChatTypeBasicGroup ) {
LOG ( " Found basic group for active search " < < this - > activeChatSearchName ) ;
this - > activeChatSearchName . clear ( ) ;
this - > createBasicGroupChat ( chatType . value ( " basic_group_id " ) . toString ( ) ) ;
}
if ( receivedChatType = = ChatTypeSupergroup ) {
LOG ( " Found supergroup for active search " < < this - > activeChatSearchName ) ;
this - > activeChatSearchName . clear ( ) ;
this - > createSupergroupChat ( chatType . value ( " supergroup_id " ) . toString ( ) ) ;
}
}
}
2020-08-17 00:31:20 +03:00
void TDLibWrapper : : handleUnreadMessageCountUpdated ( const QVariantMap & messageCountInformation )
{
2020-08-18 00:44:37 +03:00
if ( messageCountInformation . value ( " chat_list_type " ) . toString ( ) = = " chatListMain " ) {
this - > unreadMessageInformation = messageCountInformation ;
emit unreadMessageCountUpdated ( messageCountInformation ) ;
}
2020-08-17 00:31:20 +03:00
}
void TDLibWrapper : : handleUnreadChatCountUpdated ( const QVariantMap & chatCountInformation )
{
2020-08-18 00:44:37 +03:00
if ( chatCountInformation . value ( " chat_list_type " ) . toString ( ) = = " chatListMain " ) {
this - > unreadChatInformation = chatCountInformation ;
emit unreadChatCountUpdated ( chatCountInformation ) ;
}
2020-08-17 00:31:20 +03:00
}
2020-10-04 04:27:49 +03:00
void TDLibWrapper : : handleBasicGroupUpdated ( qlonglong groupId , const QVariantMap & groupInformation )
2020-08-21 19:03:51 +03:00
{
2020-10-04 04:27:49 +03:00
emit basicGroupUpdated ( updateGroup ( groupId , groupInformation , & basicGroups ) - > groupId ) ;
2020-11-05 02:02:27 +03:00
if ( ! this - > activeChatSearchName . isEmpty ( ) & & this - > activeChatSearchName = = groupInformation . value ( " username " ) . toString ( ) ) {
LOG ( " Found basic group for active search " < < this - > activeChatSearchName ) ;
this - > activeChatSearchName . clear ( ) ;
this - > createBasicGroupChat ( groupInformation . value ( ID ) . toString ( ) ) ;
}
2020-08-21 19:03:51 +03:00
}
2020-10-04 04:27:49 +03:00
void TDLibWrapper : : handleSuperGroupUpdated ( qlonglong groupId , const QVariantMap & groupInformation )
2020-08-21 19:03:51 +03:00
{
2020-10-04 04:27:49 +03:00
emit superGroupUpdated ( updateGroup ( groupId , groupInformation , & superGroups ) - > groupId ) ;
2020-11-05 02:02:27 +03:00
if ( ! this - > activeChatSearchName . isEmpty ( ) & & this - > activeChatSearchName = = groupInformation . value ( " username " ) . toString ( ) ) {
LOG ( " Found supergroup for active search " < < this - > activeChatSearchName ) ;
this - > activeChatSearchName . clear ( ) ;
this - > createSupergroupChat ( groupInformation . value ( ID ) . toString ( ) ) ;
}
2020-08-21 19:03:51 +03:00
}
2020-10-06 00:08:47 +03:00
void TDLibWrapper : : handleStickerSets ( const QVariantList & stickerSets )
{
2020-10-15 00:25:56 +03:00
QListIterator < QVariant > stickerSetIterator ( stickerSets ) ;
while ( stickerSetIterator . hasNext ( ) ) {
QVariantMap stickerSet = stickerSetIterator . next ( ) . toMap ( ) ;
this - > getStickerSet ( stickerSet . value ( " id " ) . toString ( ) ) ;
}
2020-10-06 00:08:47 +03:00
emit this - > stickerSetsReceived ( stickerSets ) ;
}
2020-10-18 19:57:01 +03:00
void TDLibWrapper : : handleEmojiSearchCompleted ( const QString & queryString , const QVariantList & resultList )
{
LOG ( " Emoji search completed " < < queryString ) ;
emit emojiSearchSuccessful ( resultList ) ;
}
2020-08-13 00:51:09 +03:00
void TDLibWrapper : : setInitialParameters ( )
{
2020-10-04 00:48:09 +03:00
LOG ( " Sending initial parameters to TD Lib " ) ;
2020-08-13 00:51:09 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " setTdlibParameters " ) ;
2020-08-13 00:51:09 +03:00
QVariantMap initialParameters ;
initialParameters . insert ( " api_id " , TDLIB_API_ID ) ;
initialParameters . insert ( " api_hash " , TDLIB_API_HASH ) ;
initialParameters . insert ( " database_directory " , QStandardPaths : : writableLocation ( QStandardPaths : : AppDataLocation ) + " /tdlib " ) ;
2020-08-13 18:08:14 +03:00
initialParameters . insert ( " use_file_database " , true ) ;
initialParameters . insert ( " use_chat_info_database " , true ) ;
2020-08-13 00:51:09 +03:00
initialParameters . insert ( " use_message_database " , true ) ;
initialParameters . insert ( " use_secret_chats " , false ) ;
initialParameters . insert ( " system_language_code " , QLocale : : system ( ) . name ( ) ) ;
QSettings hardwareSettings ( " /etc/hw-release " , QSettings : : NativeFormat ) ;
initialParameters . insert ( " device_model " , hardwareSettings . value ( " NAME " , " Unknown Mobile Device " ) . toString ( ) ) ;
initialParameters . insert ( " system_version " , QSysInfo : : prettyProductName ( ) ) ;
2020-10-19 20:51:33 +03:00
initialParameters . insert ( " application_version " , " 0.4 " ) ;
2020-10-18 17:29:34 +03:00
// initialParameters.insert("use_test_dc", true);
2020-08-13 00:51:09 +03:00
requestObject . insert ( " parameters " , initialParameters ) ;
this - > sendRequest ( requestObject ) ;
}
void TDLibWrapper : : setEncryptionKey ( )
{
2020-10-04 00:48:09 +03:00
LOG ( " Setting database encryption key " ) ;
2020-08-13 00:51:09 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " checkDatabaseEncryptionKey " ) ;
2020-08-13 00:51:09 +03:00
// see https://github.com/tdlib/td/issues/188#issuecomment-379536139
requestObject . insert ( " encryption_key " , " " ) ;
this - > sendRequest ( requestObject ) ;
2020-08-12 11:50:01 +03:00
}
2020-08-14 11:33:42 +03:00
void TDLibWrapper : : setLogVerbosityLevel ( )
{
2020-10-04 00:48:09 +03:00
LOG ( " Setting log verbosity level to something less chatty " ) ;
2020-08-14 11:33:42 +03:00
QVariantMap requestObject ;
2020-10-04 04:27:49 +03:00
requestObject . insert ( _TYPE , " setLogVerbosityLevel " ) ;
2020-08-14 11:33:42 +03:00
requestObject . insert ( " new_verbosity_level " , 2 ) ;
this - > sendRequest ( requestObject ) ;
}
2020-09-15 00:43:21 +03:00
void TDLibWrapper : : initializeOpenWith ( )
{
2020-10-04 00:48:09 +03:00
LOG ( " Initialize open-with " ) ;
2020-09-15 00:43:21 +03:00
QString dbusPathName = QStandardPaths : : writableLocation ( QStandardPaths : : GenericDataLocation ) + " /dbus-1/services " ;
QDir dbusPath ( dbusPathName ) ;
if ( ! dbusPath . exists ( ) ) {
2020-10-04 00:48:09 +03:00
LOG ( " Creating D-Bus directory " < < dbusPathName ) ;
2020-09-15 00:43:21 +03:00
dbusPath . mkpath ( dbusPathName ) ;
}
QString dbusServiceFileName = dbusPathName + " /de.ygriega.fernschreiber.service " ;
QFile dbusServiceFile ( dbusServiceFileName ) ;
if ( ! dbusServiceFile . exists ( ) ) {
2020-10-04 00:48:09 +03:00
LOG ( " Creating D-Bus service file at " < < dbusServiceFile . fileName ( ) ) ;
2020-09-15 00:43:21 +03:00
if ( dbusServiceFile . open ( QIODevice : : WriteOnly | QIODevice : : Text ) ) {
QTextStream fileOut ( & dbusServiceFile ) ;
fileOut . setCodec ( " UTF-8 " ) ;
fileOut < < QString ( " [D-BUS Service] " ) . toUtf8 ( ) < < " \n " ;
fileOut < < QString ( " Name=de.ygriega.fernschreiber " ) . toUtf8 ( ) < < " \n " ;
fileOut < < QString ( " Exec=/usr/bin/invoker -s --type=silica-qt5 /usr/bin/harbour-fernschreiber " ) . toUtf8 ( ) < < " \n " ;
fileOut . flush ( ) ;
dbusServiceFile . close ( ) ;
}
}
}
2020-10-04 04:27:49 +03:00
const TDLibWrapper : : Group * TDLibWrapper : : updateGroup ( qlonglong groupId , const QVariantMap & groupInfo , QHash < qlonglong , Group * > * groups )
{
Group * group = groups - > value ( groupId ) ;
if ( ! group ) {
group = new Group ( groupId ) ;
groups - > insert ( groupId , group ) ;
}
group - > groupInfo = groupInfo ;
return group ;
}
const TDLibWrapper : : Group * TDLibWrapper : : getGroup ( qlonglong groupId ) const
{
if ( groupId ) {
const Group * group = superGroups . value ( groupId ) ;
return group ? group : basicGroups . value ( groupId ) ;
}
return Q_NULLPTR ;
}
2020-10-31 22:18:12 +03:00
TDLibWrapper : : ChatType TDLibWrapper : : chatTypeFromString ( const QString & type )
{
return ( type = = QStringLiteral ( " chatTypePrivate " ) ) ? ChatTypePrivate :
( type = = QStringLiteral ( " chatTypeBasicGroup " ) ) ? ChatTypeBasicGroup :
( type = = QStringLiteral ( " chatTypeSupergroup " ) ) ? ChatTypeSupergroup :
( type = = QStringLiteral ( " chatTypeSecret " ) ) ? ChatTypeSecret :
ChatTypeUnknown ;
}
2020-10-04 04:27:49 +03:00
TDLibWrapper : : ChatMemberStatus TDLibWrapper : : chatMemberStatusFromString ( const QString & status )
{
// Most common ones first
return ( status = = QStringLiteral ( " chatMemberStatusMember " ) ) ? ChatMemberStatusMember :
( status = = QStringLiteral ( " chatMemberStatusLeft " ) ) ? ChatMemberStatusLeft :
( status = = QStringLiteral ( " chatMemberStatusCreator " ) ) ? ChatMemberStatusCreator :
( status = = QStringLiteral ( " chatMemberStatusAdministrator " ) ) ? ChatMemberStatusAdministrator :
( status = = QStringLiteral ( " chatMemberStatusRestricted " ) ) ? ChatMemberStatusRestricted :
( status = = QStringLiteral ( " chatMemberStatusBanned " ) ) ? ChatMemberStatusBanned :
ChatMemberStatusUnknown ;
}
TDLibWrapper : : ChatMemberStatus TDLibWrapper : : Group : : chatMemberStatus ( ) const
{
const QString statusType ( groupInfo . value ( STATUS ) . toMap ( ) . value ( _TYPE ) . toString ( ) ) ;
return statusType . isEmpty ( ) ? ChatMemberStatusUnknown : chatMemberStatusFromString ( statusType ) ;
}