2020-04-28 20:35:52 +00:00
/*
* Squawk messenger .
* Copyright ( C ) 2019 Yury Gubich < blue @ macaw . me >
*
* This program is free software : you can redistribute it and / or modify
* 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 .
*
* This program is distributed in the hope that it will be useful ,
* 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 this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "messagehandler.h"
# include "core/account.h"
Core : : MessageHandler : : MessageHandler ( Core : : Account * account ) :
QObject ( ) ,
acc ( account ) ,
pendingStateMessages ( ) ,
uploadingSlotsQueue ( )
{
}
void Core : : MessageHandler : : onMessageReceived ( const QXmppMessage & msg )
{
2023-01-29 17:26:54 +00:00
# if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 5, 0)
# ifdef WITH_OMEMO
switch ( msg . encryptionMethod ( ) ) {
case QXmpp : : NoEncryption :
break ; //just do nothing
case QXmpp : : UnknownEncryption :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received a message with unknown encryption type " ;
break ; //let it go the way it is, there is nothing I can do here
case QXmpp : : Otr :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received an OTR encrypted message, not supported yet " ;
break ; //let it go the way it is, there is nothing I can do yet
case QXmpp : : LegacyOpenPgp :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received an LegacyOpenPgp encrypted message, not supported yet " ;
break ; //let it go the way it is, there is nothing I can do yet
case QXmpp : : Ox :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received an Ox encrypted message, not supported yet " ;
break ; //let it go the way it is, there is nothing I can do yet
case QXmpp : : Omemo0 :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received an Omemo0 encrypted message, not supported yet " ;
break ; //let it go the way it is, there is nothing I can do yet
case QXmpp : : Omemo1 :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received an Omemo1 encrypted message, not supported yet " ;
break ; //let it go the way it is, there is nothing I can do yet
case QXmpp : : Omemo2 :
qDebug ( ) < < " Account " < < acc - > getName ( ) < < " received an Omemo2 encrypted message, not supported yet " ;
break ; //let it go the way it is, there is nothing I can do yet
}
# endif
# endif
2020-04-28 20:35:52 +00:00
bool handled = false ;
switch ( msg . type ( ) ) {
case QXmppMessage : : Normal :
qDebug ( ) < < " received a message with type \" Normal \" , not sure what to do with it now, skipping " ;
break ;
case QXmppMessage : : Chat :
handled = handleChatMessage ( msg ) ;
break ;
case QXmppMessage : : GroupChat :
handled = handleGroupMessage ( msg ) ;
break ;
case QXmppMessage : : Error : {
2022-03-28 20:25:33 +00:00
std : : tuple < bool , QString , QString > ids = getOriginalPendingMessageId ( msg . id ( ) ) ;
if ( std : : get < 0 > ( ids ) ) {
QString id = std : : get < 1 > ( ids ) ;
QString jid = std : : get < 2 > ( ids ) ;
2020-06-14 21:23:43 +00:00
RosterItem * cnt = acc - > rh - > getRosterItem ( jid ) ;
2020-04-28 20:35:52 +00:00
QMap < QString , QVariant > cData = {
{ " state " , static_cast < uint > ( Shared : : Message : : State : : error ) } ,
{ " errorText " , msg . error ( ) . text ( ) }
} ;
if ( cnt ! = 0 ) {
cnt - > changeMessage ( id , cData ) ;
}
emit acc - > changeMessage ( jid , id , cData ) ;
handled = true ;
} else {
qDebug ( ) < < " received a message with type \" Error \" , not sure what to do with it now, skipping " ;
}
}
break ;
case QXmppMessage : : Headline :
qDebug ( ) < < " received a message with type \" Headline \" , not sure what to do with it now, skipping " ;
break ;
}
if ( ! handled ) {
logMessage ( msg ) ;
}
}
bool Core : : MessageHandler : : handleChatMessage ( const QXmppMessage & msg , bool outgoing , bool forwarded , bool guessing )
{
2021-05-22 22:03:14 +00:00
if ( msg . body ( ) . size ( ) ! = 0 | | msg . outOfBandUrl ( ) . size ( ) > 0 ) {
2020-04-28 20:35:52 +00:00
Shared : : Message sMsg ( Shared : : Message : : chat ) ;
initializeMessage ( sMsg , msg , outgoing , forwarded , guessing ) ;
QString jid = sMsg . getPenPalJid ( ) ;
2020-06-14 21:23:43 +00:00
Contact * cnt = acc - > rh - > getContact ( jid ) ;
if ( cnt = = 0 ) {
cnt = acc - > rh - > addOutOfRosterContact ( jid ) ;
2022-01-15 12:36:49 +00:00
qDebug ( ) < < " appending message " < < sMsg . getId ( ) < < " to an out of roster contact " ;
2020-04-28 20:35:52 +00:00
}
if ( outgoing ) {
if ( forwarded ) {
sMsg . setState ( Shared : : Message : : State : : sent ) ;
}
} else {
sMsg . setState ( Shared : : Message : : State : : delivered ) ;
}
QString oId = msg . replaceId ( ) ;
if ( oId . size ( ) > 0 ) {
QMap < QString , QVariant > cData = {
{ " body " , sMsg . getBody ( ) } ,
{ " stamp " , sMsg . getTime ( ) }
} ;
cnt - > correctMessageInArchive ( oId , sMsg ) ;
emit acc - > changeMessage ( jid , oId , cData ) ;
} else {
cnt - > appendMessageToArchive ( sMsg ) ;
emit acc - > message ( sMsg ) ;
}
return true ;
}
return false ;
}
bool Core : : MessageHandler : : handleGroupMessage ( const QXmppMessage & msg , bool outgoing , bool forwarded , bool guessing )
{
const QString & body ( msg . body ( ) ) ;
if ( body . size ( ) ! = 0 ) {
Shared : : Message sMsg ( Shared : : Message : : groupChat ) ;
initializeMessage ( sMsg , msg , outgoing , forwarded , guessing ) ;
QString jid = sMsg . getPenPalJid ( ) ;
2020-06-14 21:23:43 +00:00
Conference * cnt = acc - > rh - > getConference ( jid ) ;
if ( cnt = = 0 ) {
2020-04-28 20:35:52 +00:00
return false ;
}
2022-03-28 20:25:33 +00:00
std : : tuple < bool , QString , QString > ids = getOriginalPendingMessageId ( msg . id ( ) ) ;
if ( std : : get < 0 > ( ids ) ) {
2020-04-28 20:35:52 +00:00
QMap < QString , QVariant > cData = { { " state " , static_cast < uint > ( Shared : : Message : : State : : delivered ) } } ;
2022-03-28 20:25:33 +00:00
cnt - > changeMessage ( std : : get < 1 > ( ids ) , cData ) ;
emit acc - > changeMessage ( std : : get < 2 > ( ids ) , std : : get < 1 > ( ids ) , cData ) ;
2020-04-28 20:35:52 +00:00
} else {
QString oId = msg . replaceId ( ) ;
if ( oId . size ( ) > 0 ) {
QMap < QString , QVariant > cData = {
{ " body " , sMsg . getBody ( ) } ,
{ " stamp " , sMsg . getTime ( ) }
} ;
cnt - > correctMessageInArchive ( oId , sMsg ) ;
emit acc - > changeMessage ( jid , oId , cData ) ;
} else {
cnt - > appendMessageToArchive ( sMsg ) ;
QDateTime minAgo = QDateTime : : currentDateTimeUtc ( ) . addSecs ( - 60 ) ;
if ( sMsg . getTime ( ) > minAgo ) { //otherwise it's considered a delayed delivery, most probably MUC history receipt
emit acc - > message ( sMsg ) ;
} else {
//qDebug() << "Delayed delivery: ";
}
}
}
return true ;
2020-05-21 15:42:40 +00:00
}
2020-04-28 20:35:52 +00:00
return false ;
}
void Core : : MessageHandler : : initializeMessage ( Shared : : Message & target , const QXmppMessage & source , bool outgoing , bool forwarded , bool guessing ) const
{
const QDateTime & time ( source . stamp ( ) ) ;
QString id ;
# if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 3, 0)
id = source . originId ( ) ;
if ( id . size ( ) = = 0 ) {
id = source . id ( ) ;
}
2020-05-21 15:42:40 +00:00
target . setStanzaId ( source . stanzaId ( ) ) ;
2022-01-15 12:36:49 +00:00
qDebug ( ) < < " initializing message with originId: " < < source . originId ( ) < < " , id: " < < source . id ( ) < < " , stansaId: " < < source . stanzaId ( ) ;
2020-04-28 20:35:52 +00:00
# else
id = source . id ( ) ;
# endif
2020-05-21 15:42:40 +00:00
target . setId ( id ) ;
2021-04-18 12:49:20 +00:00
QString messageId = target . getId ( ) ;
if ( messageId . size ( ) = = 0 ) {
2020-05-21 15:42:40 +00:00
target . generateRandomId ( ) ; //TODO out of desperation, I need at least a random ID
2021-04-18 12:49:20 +00:00
messageId = target . getId ( ) ;
2022-01-15 12:36:49 +00:00
qDebug ( ) < < " Had do initialize a message with no id, assigning autogenerated " < < messageId ;
2020-04-28 20:35:52 +00:00
}
target . setFrom ( source . from ( ) ) ;
target . setTo ( source . to ( ) ) ;
target . setBody ( source . body ( ) ) ;
target . setForwarded ( forwarded ) ;
2021-04-18 12:49:20 +00:00
2020-04-28 20:35:52 +00:00
if ( guessing ) {
2022-04-08 16:18:15 +00:00
if ( target . getFromJid ( ) = = acc - > getBareJid ( ) ) {
2020-04-28 20:35:52 +00:00
outgoing = true ;
} else {
outgoing = false ;
}
}
target . setOutgoing ( outgoing ) ;
if ( time . isValid ( ) ) {
target . setTime ( time ) ;
} else {
target . setCurrentTime ( ) ;
}
2021-04-18 12:49:20 +00:00
QString o ob = source . outOfBandUrl ( ) ;
if ( oob . size ( ) > 0 ) {
target . setAttachPath ( acc - > network - > addMessageAndCheckForPath ( oob , acc - > getName ( ) , target . getPenPalJid ( ) , messageId ) ) ;
}
target . setOutOfBandUrl ( oob ) ;
2020-04-28 20:35:52 +00:00
}
void Core : : MessageHandler : : logMessage ( const QXmppMessage & msg , const QString & reason )
{
qDebug ( ) < < reason ;
qDebug ( ) < < " - from: " < < msg . from ( ) ;
qDebug ( ) < < " - to: " < < msg . to ( ) ;
qDebug ( ) < < " - body: " < < msg . body ( ) ;
qDebug ( ) < < " - type: " < < msg . type ( ) ;
qDebug ( ) < < " - state: " < < msg . state ( ) ;
qDebug ( ) < < " - stamp: " < < msg . stamp ( ) ;
qDebug ( ) < < " - id: " < < msg . id ( ) ;
2020-05-21 15:42:40 +00:00
# if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 3, 0)
qDebug ( ) < < " - stanzaId: " < < msg . stanzaId ( ) ;
# endif
2020-04-28 20:35:52 +00:00
qDebug ( ) < < " - outOfBandUrl: " < < msg . outOfBandUrl ( ) ;
qDebug ( ) < < " ============================== " ;
}
void Core : : MessageHandler : : onCarbonMessageReceived ( const QXmppMessage & msg )
{
handleChatMessage ( msg , false , true ) ;
}
void Core : : MessageHandler : : onCarbonMessageSent ( const QXmppMessage & msg )
{
handleChatMessage ( msg , true , true ) ;
}
2022-03-28 20:25:33 +00:00
std : : tuple < bool , QString , QString > Core : : MessageHandler : : getOriginalPendingMessageId ( const QString & id )
2020-04-28 20:35:52 +00:00
{
2022-03-28 20:25:33 +00:00
std : : tuple < bool , QString , QString > result ( { false , " " , " " } ) ;
2020-04-28 20:35:52 +00:00
std : : map < QString , QString > : : const_iterator itr = pendingStateMessages . find ( id ) ;
if ( itr ! = pendingStateMessages . end ( ) ) {
2022-03-28 20:25:33 +00:00
std : : get < 0 > ( result ) = true ;
std : : get < 2 > ( result ) = itr - > second ;
std : : map < QString , QString > : : const_iterator itrC = pendingCorrectionMessages . find ( id ) ;
if ( itrC ! = pendingCorrectionMessages . end ( ) ) {
2022-03-31 21:32:22 +00:00
if ( itrC - > second . size ( ) > 0 ) {
std : : get < 1 > ( result ) = itrC - > second ;
} else {
std : : get < 1 > ( result ) = itr - > first ;
}
2022-03-28 20:25:33 +00:00
pendingCorrectionMessages . erase ( itrC ) ;
} else {
std : : get < 1 > ( result ) = itr - > first ;
}
pendingStateMessages . erase ( itr ) ;
}
return result ;
}
void Core : : MessageHandler : : onReceiptReceived ( const QString & jid , const QString & id )
{
std : : tuple < bool , QString , QString > ids = getOriginalPendingMessageId ( id ) ;
if ( std : : get < 0 > ( ids ) ) {
2020-04-28 20:35:52 +00:00
QMap < QString , QVariant > cData = { { " state " , static_cast < uint > ( Shared : : Message : : State : : delivered ) } } ;
2022-03-28 20:25:33 +00:00
RosterItem * ri = acc - > rh - > getRosterItem ( std : : get < 2 > ( ids ) ) ;
2020-04-28 20:35:52 +00:00
if ( ri ! = 0 ) {
2022-03-28 20:25:33 +00:00
ri - > changeMessage ( std : : get < 1 > ( ids ) , cData ) ;
2020-04-28 20:35:52 +00:00
}
2022-03-28 20:25:33 +00:00
emit acc - > changeMessage ( std : : get < 2 > ( ids ) , std : : get < 1 > ( ids ) , cData ) ;
2020-04-28 20:35:52 +00:00
}
}
2022-03-28 20:25:33 +00:00
void Core : : MessageHandler : : sendMessage ( const Shared : : Message & data , bool newMessage , QString originalId )
2021-02-07 17:02:11 +00:00
{
if ( data . getOutOfBandUrl ( ) . size ( ) = = 0 & & data . getAttachPath ( ) . size ( ) > 0 ) {
2022-03-28 20:25:33 +00:00
pendingCorrectionMessages . insert ( std : : make_pair ( data . getId ( ) , originalId ) ) ;
2021-05-22 22:03:14 +00:00
prepareUpload ( data , newMessage ) ;
2021-02-07 17:02:11 +00:00
} else {
2022-03-28 20:25:33 +00:00
performSending ( data , originalId , newMessage ) ;
2021-02-07 17:02:11 +00:00
}
}
2022-03-28 20:25:33 +00:00
void Core : : MessageHandler : : performSending ( Shared : : Message data , const QString & originalId , bool newMessage )
2020-04-28 20:35:52 +00:00
{
QString jid = data . getPenPalJid ( ) ;
QString id = data . getId ( ) ;
2022-03-28 20:25:33 +00:00
qDebug ( ) < < " Sending message with id: " < < id ;
if ( originalId . size ( ) > 0 ) {
qDebug ( ) < < " To replace one with id: " < < originalId ;
}
2020-06-14 21:23:43 +00:00
RosterItem * ri = acc - > rh - > getRosterItem ( jid ) ;
2021-05-07 18:26:02 +00:00
bool sent = false ;
2022-03-28 20:25:33 +00:00
if ( newMessage & & originalId . size ( ) > 0 ) {
newMessage = false ;
}
2021-05-22 22:03:14 +00:00
QDateTime sendTime = QDateTime : : currentDateTimeUtc ( ) ;
2020-04-28 20:35:52 +00:00
if ( acc - > state = = Shared : : ConnectionState : : connected ) {
2022-03-28 20:25:33 +00:00
QXmppMessage msg ( createPacket ( data , sendTime , originalId ) ) ;
2020-04-28 20:35:52 +00:00
2021-05-07 18:26:02 +00:00
sent = acc - > client . sendPacket ( msg ) ;
2020-04-28 20:35:52 +00:00
if ( sent ) {
data . setState ( Shared : : Message : : State : : sent ) ;
} else {
data . setState ( Shared : : Message : : State : : error ) ;
2021-05-07 18:26:02 +00:00
data . setErrorText ( " Couldn't send message: internal QXMPP library error, probably need to check out the logs " ) ;
2020-04-28 20:35:52 +00:00
}
} else {
data . setState ( Shared : : Message : : State : : error ) ;
data . setErrorText ( " You are is offline or reconnecting " ) ;
}
2022-03-28 20:25:33 +00:00
QMap < QString , QVariant > changes ( getChanges ( data , sendTime , newMessage , originalId ) ) ;
QString realId ;
if ( originalId . size ( ) > 0 ) {
realId = originalId ;
} else {
realId = id ;
}
if ( ri ! = 0 ) {
if ( newMessage ) {
ri - > appendMessageToArchive ( data ) ;
} else {
ri - > changeMessage ( realId , changes ) ;
}
if ( sent ) {
pendingStateMessages . insert ( std : : make_pair ( id , jid ) ) ;
if ( originalId . size ( ) > 0 ) {
pendingCorrectionMessages . insert ( std : : make_pair ( id , originalId ) ) ;
}
} else {
pendingStateMessages . erase ( id ) ;
pendingCorrectionMessages . erase ( id ) ;
}
}
emit acc - > changeMessage ( jid , realId , changes ) ;
}
QMap < QString , QVariant > Core : : MessageHandler : : getChanges ( Shared : : Message & data , const QDateTime & time , bool newMessage , const QString & originalId ) const
{
QMap < QString , QVariant > changes ;
QString oob = data . getOutOfBandUrl ( ) ;
2021-04-23 11:53:48 +00:00
Shared : : Message : : State mstate = data . getState ( ) ;
changes . insert ( " state " , static_cast < uint > ( mstate ) ) ;
if ( mstate = = Shared : : Message : : State : : error ) {
changes . insert ( " errorText " , data . getErrorText ( ) ) ;
}
if ( oob . size ( ) > 0 ) {
changes . insert ( " outOfBandUrl " , oob ) ;
}
2021-05-22 22:03:14 +00:00
if ( newMessage ) {
2022-03-28 20:25:33 +00:00
data . setTime ( time ) ;
}
if ( originalId . size ( ) > 0 ) {
changes . insert ( " body " , data . getBody ( ) ) ;
2021-05-07 18:26:02 +00:00
}
2022-03-28 20:25:33 +00:00
changes . insert ( " stamp " , time ) ;
2022-02-18 21:27:09 +00:00
//sometimes (when the image is pasted with ctrl+v)
//I start sending message with one path, then copy it to downloads directory
//so, the final path changes. Let's assume it changes always since it costs me close to nothing
QString attachPath = data . getAttachPath ( ) ;
if ( attachPath . size ( ) > 0 ) {
2022-02-19 18:31:49 +00:00
QString squawkified = Shared : : squawkifyPath ( attachPath ) ;
changes . insert ( " attachPath " , squawkified ) ;
if ( attachPath ! = squawkified ) {
data . setAttachPath ( squawkified ) ;
}
2022-02-18 21:27:09 +00:00
}
2022-03-28 20:25:33 +00:00
return changes ;
}
QXmppMessage Core : : MessageHandler : : createPacket ( const Shared : : Message & data , const QDateTime & time , const QString & originalId ) const
{
QXmppMessage msg ( acc - > getFullJid ( ) , data . getTo ( ) , data . getBody ( ) , data . getThread ( ) ) ;
QString id ( data . getId ( ) ) ;
if ( originalId . size ( ) > 0 ) {
msg . setReplaceId ( originalId ) ;
2021-05-07 18:26:02 +00:00
}
2022-03-28 20:25:33 +00:00
# if (QXMPP_VERSION) >= QT_VERSION_CHECK(1, 3, 0)
msg . setOriginId ( id ) ;
# endif
msg . setId ( id ) ;
msg . setType ( static_cast < QXmppMessage : : Type > ( data . getType ( ) ) ) ; //it is safe here, my type is compatible
msg . setOutOfBandUrl ( data . getOutOfBandUrl ( ) ) ;
msg . setReceiptRequested ( true ) ;
msg . setStamp ( time ) ;
return msg ;
2020-04-28 20:35:52 +00:00
}
2021-05-22 22:03:14 +00:00
void Core : : MessageHandler : : prepareUpload ( const Shared : : Message & data , bool newMessage )
2020-04-28 20:35:52 +00:00
{
if ( acc - > state = = Shared : : ConnectionState : : connected ) {
2021-05-07 18:26:02 +00:00
QString jid = data . getPenPalJid ( ) ;
QString id = data . getId ( ) ;
RosterItem * ri = acc - > rh - > getRosterItem ( jid ) ;
if ( ! ri ) {
qDebug ( ) < < " An attempt to initialize upload in " < < acc - > name < < " for pal " < < jid < < " but the object for this pal wasn't found, something went terrebly wrong, skipping send " ;
return ;
}
2021-02-07 17:02:11 +00:00
QString path = data . getAttachPath ( ) ;
2020-04-28 20:35:52 +00:00
QString url = acc - > network - > getFileRemoteUrl ( path ) ;
if ( url . size ( ) ! = 0 ) {
2021-05-22 22:03:14 +00:00
sendMessageWithLocalUploadedFile ( data , url , newMessage ) ;
2020-04-28 20:35:52 +00:00
} else {
2021-05-22 22:03:14 +00:00
pendingStateMessages . insert ( std : : make_pair ( id , jid ) ) ;
if ( newMessage ) {
2021-05-07 18:26:02 +00:00
ri - > appendMessageToArchive ( data ) ;
2020-04-28 20:35:52 +00:00
} else {
2021-05-22 22:03:14 +00:00
QMap < QString , QVariant > changes ( {
{ " state " , ( uint ) Shared : : Message : : State : : pending }
} ) ;
ri - > changeMessage ( id , changes ) ;
emit acc - > changeMessage ( jid , id , changes ) ;
}
//this checks if the file is already uploading, and if so it subscribes to it's success, so, i need to do stuff only if the network knows nothing of this file
if ( ! acc - > network - > checkAndAddToUploading ( acc - > getName ( ) , jid , id , path ) ) {
2020-04-28 20:35:52 +00:00
if ( acc - > um - > serviceFound ( ) ) {
QFileInfo file ( path ) ;
if ( file . exists ( ) & & file . isReadable ( ) ) {
2021-05-07 18:26:02 +00:00
pendingStateMessages . insert ( std : : make_pair ( id , jid ) ) ;
uploadingSlotsQueue . emplace_back ( path , id ) ;
2020-04-28 20:35:52 +00:00
if ( uploadingSlotsQueue . size ( ) = = 1 ) {
acc - > um - > requestUploadSlot ( file ) ;
}
} else {
2021-05-07 18:26:02 +00:00
handleUploadError ( jid , id , " Uploading file no longer exists or your system user has no permission to read it " ) ;
2020-04-28 20:35:52 +00:00
qDebug ( ) < < " Requested upload slot in account " < < acc - > name < < " for file " < < path < < " but the file doesn't exist or is not readable " ;
}
} else {
2021-05-07 18:26:02 +00:00
handleUploadError ( jid , id , " Your server doesn't support file upload service, or it's prohibited for your account " ) ;
2020-04-28 20:35:52 +00:00
qDebug ( ) < < " Requested upload slot in account " < < acc - > name < < " for file " < < path < < " but upload manager didn't discover any upload services " ;
}
}
}
} else {
2021-04-18 12:49:20 +00:00
handleUploadError ( data . getPenPalJid ( ) , data . getId ( ) , " Account is offline or reconnecting " ) ;
2020-04-28 20:35:52 +00:00
qDebug ( ) < < " An attempt to send message with not connected account " < < acc - > name < < " , skipping " ;
}
}
void Core : : MessageHandler : : onUploadSlotReceived ( const QXmppHttpUploadSlotIq & slot )
{
if ( uploadingSlotsQueue . size ( ) = = 0 ) {
qDebug ( ) < < " HTTP Upload manager of account " < < acc - > name < < " reports about success requesting upload slot, but none was requested " ;
} else {
2021-05-07 18:26:02 +00:00
const std : : pair < QString , QString > & pair = uploadingSlotsQueue . front ( ) ;
const QString & mId = pair . second ;
QString palJid = pendingStateMessages . at ( mId ) ;
acc - > network - > uploadFile ( { acc - > name , palJid , mId } , pair . first , slot . putUrl ( ) , slot . getUrl ( ) , slot . putHeaders ( ) ) ;
2020-04-28 20:35:52 +00:00
2021-04-18 12:49:20 +00:00
uploadingSlotsQueue . pop_front ( ) ;
2020-04-28 20:35:52 +00:00
if ( uploadingSlotsQueue . size ( ) > 0 ) {
acc - > um - > requestUploadSlot ( uploadingSlotsQueue . front ( ) . first ) ;
}
}
}
void Core : : MessageHandler : : onUploadSlotRequestFailed ( const QXmppHttpUploadRequestIq & request )
{
2021-04-18 12:49:20 +00:00
QString err ( request . error ( ) . text ( ) ) ;
2020-04-28 20:35:52 +00:00
if ( uploadingSlotsQueue . size ( ) = = 0 ) {
qDebug ( ) < < " HTTP Upload manager of account " < < acc - > name < < " reports about an error requesting upload slot, but none was requested " ;
2021-04-18 12:49:20 +00:00
qDebug ( ) < < err ;
2020-04-28 20:35:52 +00:00
} else {
2021-05-07 18:26:02 +00:00
const std : : pair < QString , QString > & pair = uploadingSlotsQueue . front ( ) ;
2021-04-18 12:49:20 +00:00
qDebug ( ) < < " Error requesting upload slot for file " < < pair . first < < " in account " < < acc - > name < < " : " < < err ;
2021-05-07 18:26:02 +00:00
handleUploadError ( pendingStateMessages . at ( pair . second ) , pair . second , err ) ;
2020-04-28 20:35:52 +00:00
2021-04-18 12:49:20 +00:00
uploadingSlotsQueue . pop_front ( ) ;
2020-04-28 20:35:52 +00:00
if ( uploadingSlotsQueue . size ( ) > 0 ) {
acc - > um - > requestUploadSlot ( uploadingSlotsQueue . front ( ) . first ) ;
}
}
}
2021-04-18 12:49:20 +00:00
void Core : : MessageHandler : : onDownloadFileComplete ( const std : : list < Shared : : MessageInfo > & msgs , const QString & path )
2020-04-28 20:35:52 +00:00
{
2021-04-18 12:49:20 +00:00
QMap < QString , QVariant > cData = {
{ " attachPath " , path }
} ;
for ( const Shared : : MessageInfo & info : msgs ) {
if ( info . account = = acc - > getName ( ) ) {
2021-04-22 22:41:32 +00:00
RosterItem * cnt = acc - > rh - > getRosterItem ( info . jid ) ;
2021-04-18 12:49:20 +00:00
if ( cnt ! = 0 ) {
if ( cnt - > changeMessage ( info . messageId , cData ) ) {
emit acc - > changeMessage ( info . jid , info . messageId , cData ) ;
}
}
}
2020-04-28 20:35:52 +00:00
}
}
2021-04-18 12:49:20 +00:00
void Core : : MessageHandler : : onLoadFileError ( const std : : list < Shared : : MessageInfo > & msgs , const QString & text , bool up )
{
if ( up ) {
for ( const Shared : : MessageInfo & info : msgs ) {
if ( info . account = = acc - > getName ( ) ) {
handleUploadError ( info . jid , info . messageId , text ) ;
}
}
}
}
void Core : : MessageHandler : : handleUploadError ( const QString & jid , const QString & messageId , const QString & errorText )
2020-04-28 20:35:52 +00:00
{
2021-05-07 18:26:02 +00:00
emit acc - > uploadFileError ( jid , messageId , " Error requesting slot to upload file: " + errorText ) ;
2022-03-28 20:25:33 +00:00
pendingStateMessages . erase ( messageId ) ;
pendingCorrectionMessages . erase ( messageId ) ;
2021-05-07 18:26:02 +00:00
requestChangeMessage ( jid , messageId , {
{ " state " , static_cast < uint > ( Shared : : Message : : State : : error ) } ,
{ " errorText " , errorText }
} ) ;
2021-04-18 12:49:20 +00:00
}
2022-02-18 21:27:09 +00:00
void Core : : MessageHandler : : onUploadFileComplete ( const std : : list < Shared : : MessageInfo > & msgs , const QString & url , const QString & path )
2021-04-18 12:49:20 +00:00
{
for ( const Shared : : MessageInfo & info : msgs ) {
if ( info . account = = acc - > getName ( ) ) {
2021-05-07 18:26:02 +00:00
RosterItem * ri = acc - > rh - > getRosterItem ( info . jid ) ;
if ( ri ! = 0 ) {
Shared : : Message msg = ri - > getMessage ( info . messageId ) ;
2022-02-18 21:27:09 +00:00
msg . setAttachPath ( path ) ;
sendMessageWithLocalUploadedFile ( msg , url , false ) ;
2021-05-07 18:26:02 +00:00
} else {
qDebug ( ) < < " A signal received about complete upload to " < < acc - > name < < " for pal " < < info . jid < < " but the object for this pal wasn't found, something went terrebly wrong, skipping send " ;
2021-04-18 12:49:20 +00:00
}
}
2020-04-28 20:35:52 +00:00
}
}
2021-05-07 18:26:02 +00:00
void Core : : MessageHandler : : sendMessageWithLocalUploadedFile ( Shared : : Message msg , const QString & url , bool newMessage )
2020-04-28 20:35:52 +00:00
{
msg . setOutOfBandUrl ( url ) ;
2021-05-07 18:26:02 +00:00
if ( msg . getBody ( ) . size ( ) = = 0 ) { //not sure why, but most messages do that
msg . setBody ( url ) ; //they duplicate oob in body, some of them wouldn't even show an attachment if you don't do that
}
2022-03-28 20:25:33 +00:00
performSending ( msg , pendingCorrectionMessages . at ( msg . getId ( ) ) , newMessage ) ;
2020-04-28 20:35:52 +00:00
//TODO removal/progress update
}
2021-04-28 20:26:19 +00:00
2022-03-28 20:25:33 +00:00
static const std : : set < QString > allowedToChangeKeys ( {
2021-05-07 18:26:02 +00:00
" attachPath " ,
" outOfBandUrl " ,
" state " ,
" errorText "
} ) ;
2021-04-28 20:26:19 +00:00
void Core : : MessageHandler : : requestChangeMessage ( const QString & jid , const QString & messageId , const QMap < QString , QVariant > & data )
{
RosterItem * cnt = acc - > rh - > getRosterItem ( jid ) ;
if ( cnt ! = 0 ) {
2021-05-07 18:26:02 +00:00
bool allSupported = true ;
QString unsupportedString ;
2022-03-28 20:25:33 +00:00
for ( QMap < QString , QVariant > : : const_iterator itr = data . begin ( ) ; itr ! = data . end ( ) ; + + itr ) { //I need all this madness
if ( allowedToChangeKeys . count ( itr . key ( ) ) ! = 1 ) { //to not allow this method
allSupported = false ; //to make a message to look like if it was edited
unsupportedString = itr . key ( ) ; //basically I needed to control who exaclty calls this method
break ; //because the underlying tech assumes that
} //the change is initiated by user, not by system
2021-05-07 18:26:02 +00:00
}
if ( allSupported ) {
2021-04-28 20:26:19 +00:00
cnt - > changeMessage ( messageId , data ) ;
emit acc - > changeMessage ( jid , messageId , data ) ;
} else {
qDebug ( ) < < " A request to change message " < < messageId < < " of conversation " < < jid < < " with following data " < < data ;
2021-05-07 18:26:02 +00:00
qDebug ( ) < < " only limited set of dataFields are supported yet here, and " < < unsupportedString < < " isn't one of them, skipping " ;
2021-04-28 20:26:19 +00:00
}
}
}
2021-05-22 22:03:14 +00:00
void Core : : MessageHandler : : resendMessage ( const QString & jid , const QString & id )
{
RosterItem * cnt = acc - > rh - > getRosterItem ( jid ) ;
if ( cnt ! = 0 ) {
try {
Shared : : Message msg = cnt - > getMessage ( id ) ;
if ( msg . getState ( ) = = Shared : : Message : : State : : error ) {
2022-03-28 20:25:33 +00:00
if ( msg . getEdited ( ) ) {
QString originalId = msg . getId ( ) ;
msg . generateRandomId ( ) ;
sendMessage ( msg , false , originalId ) ;
} else {
sendMessage ( msg , false ) ;
}
2021-05-22 22:03:14 +00:00
} else {
qDebug ( ) < < " An attempt to resend a message to " < < jid < < " by account " < < acc - > getName ( ) < < " , but this message seems to have been normally sent, this method was made to retry sending failed to be sent messages, skipping " ;
}
} catch ( const Archive : : NotFound & err ) {
qDebug ( ) < < " An attempt to resend a message to " < < jid < < " by account " < < acc - > getName ( ) < < " , but this message wasn't found in history, skipping " ;
}
} else {
qDebug ( ) < < " An attempt to resend a message to " < < jid < < " by account " < < acc - > getName ( ) < < " , but this jid isn't present in account roster, skipping " ;
}
}