2 wlmchatsession.cpp - MSN Message Manager
4 Copyright (c) 2008 by Tiago Salem Herrmann <tiagosh@gmail.com>
5 Kopete (c) 2002-2005 by the Kopete developers <kopete-devel@kde.org>
7 *************************************************************************
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
14 *************************************************************************
17 #include "wlmchatmanager.h"
21 #include <QImageReader>
26 #include <QDomDocument>
27 #include <QTextDocument>
31 #include <kinputdialog.h>
33 #include <kmessagebox.h>
35 #include <kmainwindow.h>
38 #include <kstandarddirs.h>
39 #include <ktemporaryfile.h>
41 #include "kopetecontactaction.h"
42 #include "kopetemetacontact.h"
43 #include "kopetecontactlist.h"
44 #include "kopetechatsessionmanager.h"
45 #include "kopeteuiglobal.h"
46 #include "kopeteglobal.h"
47 #include "kopeteview.h"
49 #include "wlmcontact.h"
50 #include "wlmprotocol.h"
51 #include "wlmaccount.h"
54 WlmChatManager::WlmChatManager (WlmAccount
* account1
):
57 QObject::connect (&account ()->server ()->cb
,
58 SIGNAL (messageReceived
59 (MSN::SwitchboardServerConnection
*,
60 const QString
&, const Kopete::Message
&)),
63 (MSN::SwitchboardServerConnection
*,
64 const QString
&, const Kopete::Message
&)));
66 QObject::connect (&account ()->server ()->cb
,
67 SIGNAL (joinedConversation
68 (MSN::SwitchboardServerConnection
*,
69 const QString
&, const QString
&)), this,
70 SLOT (joinedConversation
71 (MSN::SwitchboardServerConnection
*,
72 const QString
&, const QString
&)));
74 QObject::connect (&account ()->server ()->cb
,
75 SIGNAL (leftConversation
76 (MSN::SwitchboardServerConnection
*,
77 const QString
&)), this,
78 SLOT (leftConversation
79 (MSN::SwitchboardServerConnection
*,
82 QObject::connect (&account ()->server ()->cb
,
83 SIGNAL (gotNewSwitchboard
84 (MSN::SwitchboardServerConnection
*,
86 SLOT (gotNewSwitchboard
87 (MSN::SwitchboardServerConnection
*,
90 QObject::connect (&account ()->server ()->cb
,
91 SIGNAL (SwitchboardServerConnectionTerminated
92 (MSN::SwitchboardServerConnection
*)), this,
93 SLOT (SwitchboardServerConnectionTerminated
94 (MSN::SwitchboardServerConnection
*)));
96 QObject::connect (&account ()->server ()->cb
,
97 SIGNAL (messageSentACK
98 (MSN::SwitchboardServerConnection
*,
99 const unsigned int &)), this,
101 (MSN::SwitchboardServerConnection
*,
102 const unsigned int &)));
104 QObject::connect (&account ()->server ()->cb
,
105 SIGNAL (receivedNudge
106 (MSN::SwitchboardServerConnection
*,
107 const QString
&)), this,
109 (MSN::SwitchboardServerConnection
*,
112 QObject::connect (&account ()->server ()->cb
,
113 SIGNAL (receivedTypingNotification
114 (MSN::SwitchboardServerConnection
*,
115 const QString
&)), this,
116 SLOT (receivedTypingNotification
117 (MSN::SwitchboardServerConnection
*,
120 QObject::connect (&account ()->server ()->cb
,
121 SIGNAL (slotGotEmoticonNotification (MSN::SwitchboardServerConnection
*,
122 const MSN::Passport
&, const QString
&,
123 const QString
&)), this,
124 SLOT (slotGotEmoticonNotification (MSN::SwitchboardServerConnection
*,
125 const MSN::Passport
&, const QString
&,
128 QObject::connect (&account ()->server ()->cb
,
129 SIGNAL (slotGotVoiceClipNotification (MSN::SwitchboardServerConnection
*,
130 const MSN::Passport
&,
131 const QString
&)), this,
132 SLOT(slotGotVoiceClipNotification (MSN::SwitchboardServerConnection
*,
133 const MSN::Passport
&,
136 QObject::connect (&account ()->server ()->cb
,
137 SIGNAL(slotGotWinkNotification (MSN::SwitchboardServerConnection
*,
138 const MSN::Passport
&,
139 const QString
&)), this,
140 SLOT(slotGotWinkNotification (MSN::SwitchboardServerConnection
*,
141 const MSN::Passport
&,
144 QObject::connect (&account ()->server ()->cb
,
145 SIGNAL(slotGotInk (MSN::SwitchboardServerConnection
*,
146 const MSN::Passport
&,
147 const QString
&)), this,
148 SLOT(slotGotInk (MSN::SwitchboardServerConnection
*,
149 const MSN::Passport
&,
152 QObject::connect (&account ()->server ()->cb
,
153 SIGNAL(slotGotVoiceClipFile(MSN::SwitchboardServerConnection
*,
154 const unsigned int &,
155 const QString
&)), this,
156 SLOT(slotGotVoiceClipFile(MSN::SwitchboardServerConnection
*,
157 const unsigned int &,
160 QObject::connect (&account ()->server ()->cb
,
161 SIGNAL(slotGotEmoticonFile(MSN::SwitchboardServerConnection
*,
162 const unsigned int &,
164 const QString
&)), this,
165 SLOT(slotGotEmoticonFile(MSN::SwitchboardServerConnection
*,
166 const unsigned int &,
170 QObject::connect (&account ()->server ()->cb
,
171 SIGNAL(slotGotWinkFile(MSN::SwitchboardServerConnection
*,
172 const unsigned int &,
173 const QString
&)), this,
174 SLOT(slotGotWinkFile(MSN::SwitchboardServerConnection
*,
175 const unsigned int &,
179 WlmChatManager::~WlmChatManager ()
181 QMap
< MSN::SwitchboardServerConnection
*,
182 WlmChatSession
* >::Iterator it
;
183 for (it
= chatSessions
.begin (); it
!= chatSessions
.end (); ++it
)
186 it
.value ()->setChatService (NULL
);
188 chatSessions
.clear ();
192 WlmChatManager::receivedNudge (MSN::SwitchboardServerConnection
* conn
,
193 const QString
& passport
)
198 if(chatSessions
[conn
])
199 chatSessions
[conn
]->receivedNudge (passport
);
204 WlmChatManager::leftConversation (MSN::SwitchboardServerConnection
* conn
,
205 const QString
& passport
)
207 kDebug (14210) << k_funcinfo
<< " " << conn
;
208 WlmChatSession
*chat
= chatSessions
[conn
];
212 WlmContact
* contact
= qobject_cast
<WlmContact
*>(account ()->contacts ()[passport
]);
215 chat
->removeContact (contact
);
220 WlmChatManager::removeChatSession (QObject
* obj
)
222 QMap
<MSN::SwitchboardServerConnection
*, WlmChatSession
* >::Iterator it
;
223 for (it
= chatSessions
.begin (); it
!= chatSessions
.end (); ++it
)
225 if (it
.value () == obj
)
227 it
.value ()->deleteLater();
228 chatSessions
.remove (it
.key ());
235 WlmChatManager::createChat (MSN::SwitchboardServerConnection
* conn
)
237 Kopete::ContactPtrList chatmembers
;
238 kDebug (14210) << k_funcinfo
<< " " << conn
;
240 if (chatSessions
[conn
])
243 std::list
< MSN::Passport
>::iterator users
= conn
->users
.begin ();
244 for (; users
!= conn
->users
.end (); ++users
)
246 Kopete::Contact
* contact
=
247 account ()->contacts ()[(*users
).c_str ()];
250 account ()->addContact ((*users
).c_str (), QString(), 0L,
251 Kopete::Account::Temporary
);
252 contact
= account ()->contacts ()[(*users
).c_str ()];
253 contact
->setOnlineStatus (WlmProtocol::protocol ()->wlmUnknown
);
255 chatmembers
.append (contact
);
258 Kopete::ChatSession
* _manager
=
259 Kopete::ChatSessionManager::self ()->findChatSession (account ()->myself (),
261 account ()->protocol ());
263 chatSessions
[conn
] = qobject_cast
< WlmChatSession
* >(_manager
);
265 // create a new chat window
266 chatSessions
[conn
] = new WlmChatSession (account ()->protocol (),
267 account ()->myself (), chatmembers
, conn
);
268 if(chatSessions
[conn
])
269 chatSessions
[conn
]->setChatService (conn
);
273 WlmChatManager::joinedConversation (MSN::SwitchboardServerConnection
* conn
,
274 const QString
& passport
,
275 const QString
& friendlyname
)
277 Q_UNUSED( friendlyname
);
279 Kopete::ContactPtrList chatmembers
;
280 Kopete::Contact
* contact
= account ()->contacts ()[passport
];
283 account ()->addContact (passport
, QString(), 0L,
284 Kopete::Account::Temporary
);
285 contact
= account ()->contacts ()[passport
];
286 contact
->setOnlineStatus (WlmProtocol::protocol ()->wlmUnknown
);
288 // populate chatmembers from SwitchboardServerConnection
289 std::list
< MSN::Passport
>::iterator users
= conn
->users
.begin ();
290 for (; users
!= conn
->users
.end (); ++users
)
292 Kopete::Contact
* contact
=
293 account ()->contacts ()[(*users
).c_str ()];
296 account ()->addContact ((*users
).c_str (), QString(), 0L,
297 Kopete::Account::Temporary
);
298 contact
= account ()->contacts ()[(*users
).c_str ()];
299 contact
->setOnlineStatus (WlmProtocol::protocol ()->wlmUnknown
);
301 chatmembers
.append (contact
);
304 // check if we already have a similar connection
305 WlmChatSession
*_manager
=
306 qobject_cast
<WlmChatSession
*>(Kopete::ChatSessionManager::self ()->
307 findChatSession (account ()->myself (), chatmembers
,
308 account ()->protocol ()));
312 // drop the old and replace by the new one
313 MSN::SwitchboardServerConnection
* conn_current
=
314 chatSessions
.key (_manager
);
315 if (conn_current
&& conn_current
!= conn
)
317 chatSessions
.remove (conn_current
);
318 chatSessions
[conn
] = _manager
;
319 chatSessions
[conn
]->setChatService(conn
);
326 chatSessions
[conn
]->addContact (contact
);
327 // the session is ready when there are at least 2 contacts, me and somebody
328 if (!chatSessions
[conn
]->isReady ())
329 chatSessions
[conn
]->setReady (true);
333 WlmChatManager::receivedMessage (MSN::SwitchboardServerConnection
* conn
,
334 const QString
& from
,
335 const Kopete::Message
& message
)
337 kDebug (14210) << k_funcinfo
<< " " << conn
;
341 WlmChatSession
*chat
= chatSessions
[conn
];
343 // Pass it on to the contact to process and display via a KMM
346 Kopete::Contact
* contact
= account ()->contacts ()[from
];
349 account ()->addContact (from
, QString(), 0L,
350 Kopete::Account::Temporary
);
351 contact
= account ()->contacts ()[from
];
353 Kopete::Message
* newMessage
=
354 new Kopete::Message (contact
, chat
->members ());
355 newMessage
->setPlainBody (message
.plainBody ());
356 newMessage
->setFont (message
.font ());
357 newMessage
->setForegroundColor (message
.foregroundColor ());
358 newMessage
->setDirection (Kopete::Message::Inbound
);
360 // stolen from msn plugin
361 QMap
<QString
,QString
>::ConstIterator it
= chat
->emoticonsList
.constBegin();
362 for(;it
!=chat
->emoticonsList
.constEnd(); ++it
)
364 QString es
=Qt::escape(it
.key());
365 QString message1
=newMessage
->escapedBody();
366 if(message1
.contains(es
))
371 // an emoticon is still missing, so wait for it
372 QLinkedList
<Kopete::Message
*> msgs
= pendingMessages
[conn
];
373 newMessage
->setHtmlBody(message1
);
374 msgs
.append(newMessage
);
375 pendingMessages
[conn
] = msgs
;
378 QImage iconImage
= QImageReader(it
.value()).read();
380 message1
.replace( QRegExp(QString::fromLatin1("%1(?![^><]*>)").arg(QRegExp::escape(es
))),
381 QString::fromLatin1("<img align=\"center\" width=\"") +
382 QString::number(iconImage
.width()) +
383 QString::fromLatin1("\" height=\"") +
384 QString::number(iconImage
.height()) +
385 QString::fromLatin1("\" src=\"") + it
.value() +
386 QString::fromLatin1("\" title=\"") + es
+
387 QString::fromLatin1("\" alt=\"") + es
+
388 QString::fromLatin1( "\"/>" ) );
389 newMessage
->setHtmlBody(message1
);
392 // Add it to the manager
393 chat
->appendMessage (*newMessage
);
396 // send keepalive each 50 seconds.
397 chat
->startSendKeepAlive();
401 kWarning (14210) << k_funcinfo
<<
402 "unable to look up contact for delivery";
407 WlmChatManager::SwitchboardServerConnectionTerminated (
408 MSN::SwitchboardServerConnection
* conn
)
413 WlmChatSession
*chat
= chatSessions
[conn
];
416 chat
->setChatService (NULL
);
417 chatSessions
.remove (conn
);
420 if(!chat->view()->isVisible())
430 WlmChatManager::gotNewSwitchboard (MSN::SwitchboardServerConnection
* conn
,
433 Kopete::ContactPtrList chatmembers
;
434 const std::pair
< std::string
, std::string
> *ctx
=
435 static_cast < const std::pair
< std::string
, std::string
> *>(tag
);
440 conn
->inviteUser (ctx
->first
);
442 conn
->auth
.tag
= NULL
;
443 kDebug (14210) << k_funcinfo
<< " " << conn
;
447 WlmChatManager::messageSentACK (MSN::SwitchboardServerConnection
* conn
,
448 const unsigned int &trID
)
450 WlmChatSession
*chat
= chatSessions
[conn
];
453 chat
->messageSentACK (trID
);
458 WlmChatManager::requestDisplayPicture (QString contactId
)
460 Kopete::Contact
* contact
= account ()->contacts ()[contactId
];
465 WlmChatSession
*session
=
466 qobject_cast
<WlmChatSession
*>(contact
->manager (Kopete::Contact::CanCreate
));
469 session
->requestDisplayPicture ();
474 WlmChatManager::receivedTypingNotification (MSN::SwitchboardServerConnection
*
475 conn
, const QString
& contactId
)
477 Kopete::Contact
* contact
= account ()->contacts ()[contactId
];
482 WlmChatSession
*chat
= chatSessions
[conn
];
485 chat
->receivedTypingMsg (contact
, true);
490 WlmChatManager::slotGotVoiceClipNotification (MSN::SwitchboardServerConnection
* conn
,
491 const MSN::Passport
& from
,
492 const QString
& msnobject
)
496 Q_UNUSED( msnobject
);
500 WlmChatManager::slotGotWinkNotification (MSN::SwitchboardServerConnection
* conn
,
501 const MSN::Passport
& from
,
502 const QString
& msnobject
)
506 Q_UNUSED( msnobject
);
510 WlmChatManager::slotGotInk (MSN::SwitchboardServerConnection
* conn
,
511 const MSN::Passport
& from
,
512 const QString
& image
)
515 WlmChatSession
*chat
= chatSessions
[conn
];
520 Kopete::Contact
* contact
= account ()->contacts ()[from
.c_str()];
523 account ()->addContact (from
.c_str(), QString(), 0L,
524 Kopete::Account::Temporary
);
525 contact
= account ()->contacts ()[from
.c_str()];
530 ink
= QByteArray::fromBase64(image
.toUtf8());
531 KTemporaryFile
*inkImage
= new KTemporaryFile();
532 inkImage
->setPrefix("inkformatgif-");
533 inkImage
->setSuffix(".gif");
535 inkImage
->write(ink
.data(), ink
.size());
536 QString msg
=QString ("<img src=\"%1\" />").arg ( inkImage
->fileName() );
539 Kopete::Message
kmsg( contact
, chat
->members() );
540 kmsg
.setHtmlBody( msg
);
541 kmsg
.setDirection( Kopete::Message::Inbound
);
542 chat
->appendMessage ( kmsg
);
549 WlmChatManager::slotGotVoiceClipFile(MSN::SwitchboardServerConnection
* conn
,
550 const unsigned int & sessionID
,
551 const QString
& file
)
554 Q_UNUSED( sessionID
);
558 void WlmChatManager::slotGotEmoticonNotification (MSN::SwitchboardServerConnection
* conn
,
559 const MSN::Passport
& buddy
,
560 const QString
& alias
,
561 const QString
& msnobject
)
565 WlmChatSession
*chat
= chatSessions
[conn
];
569 unsigned int sessionID
= chat
->generateSessionID();
572 xmlobj
.setContent (msnobject
);
574 // track display pictures by SHA1D field
575 QString SHA1D
= xmlobj
.documentElement ().attribute ("SHA1D");
577 if (SHA1D
.isEmpty ())
580 QString newlocation
=
581 KGlobal::dirs ()->locateLocal ("appdata",
583 QString (SHA1D
.replace ('/', '_')));
584 QFile
f(newlocation
);
585 if (f
.exists () && f
.size ())
587 chat
->emoticonsList
[alias
] = newlocation
;
592 chat
->emoticonsList
[alias
].clear();
594 conn
->requestEmoticon(sessionID
, newlocation
.toAscii().constData(),
595 msnobject
.toAscii().constData(), alias
.toAscii().constData());
599 WlmChatManager::slotGotEmoticonFile(MSN::SwitchboardServerConnection
* conn
,
600 const unsigned int & sessionID
,
601 const QString
& alias
,
602 const QString
& file
)
604 Q_UNUSED( sessionID
);
606 WlmChatSession
*chat
= chatSessions
[conn
];
610 chat
->emoticonsList
[alias
] = file
;
612 if(pendingMessages
[conn
].isEmpty())
615 // duplicate to avoid crashes when removing items in the next loop
616 QLinkedList
<Kopete::Message
*> pendingMessages1
= pendingMessages
[conn
];
618 QLinkedList
<Kopete::Message
*>::iterator it
= pendingMessages1
.begin();
619 for(;it
!=pendingMessages1
.end(); ++it
)
621 Kopete::Message
*message
= (*it
);
622 QMap
<QString
,QString
>::iterator it2
= chat
->emoticonsList
.begin();
624 // for each emoticon in our list
625 for(;it2
!=chat
->emoticonsList
.end(); ++it2
)
627 QString es
=Qt::escape(it2
.key());
628 QString message1
=message
->escapedBody();
629 if(message1
.contains(es
))
631 QFile
f(it2
.value());
634 // an emoticon is still missing, so wait for it
635 QLinkedList
<Kopete::Message
*> pmsgs
= pendingMessages
[conn
];
636 message
->setHtmlBody(message1
);
637 pmsgs
.removeOne((*it
));
639 pendingMessages
[conn
] = pmsgs
;
643 QImage iconImage
= QImageReader(it2
.value()).read();
645 message1
.replace( QRegExp(QString::fromLatin1("%1(?![^><]*>)").arg(QRegExp::escape(es
))),
646 QString::fromLatin1("<img align=\"center\" width=\"") +
647 QString::number(iconImage
.width()) +
648 QString::fromLatin1("\" height=\"") +
649 QString::number(iconImage
.height()) +
650 QString::fromLatin1("\" src=\"") + it2
.value() +
651 QString::fromLatin1("\" title=\"") + es
+
652 QString::fromLatin1("\" alt=\"") + es
+
653 QString::fromLatin1( "\"/>" ) );
654 message
->setHtmlBody(message1
);
659 chatSessions
[conn
]->appendMessage (*message
);
660 pendingMessages
[conn
].removeOne(message
);
667 WlmChatManager::slotGotWinkFile(MSN::SwitchboardServerConnection
* conn
,
668 const unsigned int & sessionID
,
669 const QString
& file
)
672 Q_UNUSED( sessionID
);
676 #include "wlmchatmanager.moc"