1 /*
2  * This file is part of TelepathyLoggerQt
3  *
4  * Copyright (C) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
5  *
6  * This library is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published
8  * by the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #include "tpl-tool.h"
21 #include <tools/_gen/tpl-tool.moc.hpp>
22 #include <TelepathyLoggerQt/utils.h>
23 #include <QApplication>
24 #include <TelepathyQt/Account>
25 #include <TelepathyQt/AccountSet>
26 #include <TelepathyQt/AccountManager>
27 #include <TelepathyQt/ContactManager>
28 #include <TelepathyQt/Connection>
29 #include <TelepathyQt/PendingReady>
30 #include <TelepathyLoggerQt/Entity>
31 #include <TelepathyLoggerQt/Event>
32 #include <TelepathyLoggerQt/TextEvent>
33 #include <TelepathyLoggerQt/CallEvent>
34 #include <TelepathyLoggerQt/LogManager>
35 #include <TelepathyLoggerQt/PendingDates>
36 #include <TelepathyLoggerQt/PendingEntities>
37 #include <TelepathyLoggerQt/PendingEvents>
38 #include <TelepathyLoggerQt/PendingSearch>
39 #include <TelepathyLoggerQt/Init>
40 #include <glib-object.h>
41 #include <QGst/Init>
42 #include <QDebug>
43 
44 #define TPL_TOOL_DATE_FORMAT "yyyyMMdd"
45 
TplToolApplication(int & argc,char ** argv)46 TplToolApplication::TplToolApplication(int &argc, char **argv)
47     : QCoreApplication(argc, argv)
48 {
49     qDebug();
50 
51     mAccountManager = Tp::AccountManager::create();
52     connect(mAccountManager->becomeReady(Tp::AccountManager::FeatureCore),
53             SIGNAL(finished(Tp::PendingOperation*)),
54             this,
55             SLOT(onAccountManagerReady(Tp::PendingOperation*)));
56 }
57 
accountPtr(const QString & id)58 Tp::AccountPtr TplToolApplication::accountPtr(const QString &id)
59 {
60     qDebug();
61 
62     mAccountPtr = Tpl::Utils::instance()->accountPtr(id);
63     if (!mAccountPtr->isValid()) {
64         return mAccountPtr;
65     }
66 
67     connect(mAccountPtr->becomeReady(Tp::Features() << Tp::Account::FeatureCore << Tp::Account::FeatureAvatar),
68             SIGNAL(finished(Tp::PendingOperation*)),
69             this,
70             SLOT(onAccountReady(Tp::PendingOperation*)));
71 
72     return mAccountPtr;
73 }
74 
entityPtr(const QString & id)75 Tpl::EntityPtr TplToolApplication::entityPtr(const QString &id)
76 {
77     qDebug();
78 
79     return Tpl::Entity::create(id.toUtf8(), Tpl::EntityTypeContact, NULL, NULL);
80 }
81 
parseArgs1()82 bool TplToolApplication::parseArgs1()
83 {
84     qDebug();
85 
86     QStringList args = arguments();
87 
88     Tpl::LogManagerPtr logManager = Tpl::LogManager::instance();
89     if (logManager.isNull()) {
90         qWarning() << "LogManager not found";
91         return false;
92     }
93 
94     if (args.size() == 2 && args.at(1) == "accounts") {
95         Tp::AccountSetPtr accountSet = Tpl::Utils::instance()->accountManagerPtr()->validAccounts();
96         QList<Tp::AccountPtr> accounts = accountSet->accounts();
97         Tp::AccountPtr account;
98         int i = 0;
99         Q_FOREACH(account, accounts) {
100             qDebug() << "account " << i++ << account->objectPath();
101         }
102         this->exit();
103         return true;
104     } else if ((args.size() == 3 && args.at(1) == "contacts") ||
105                (args.size() == 4 && args.at(1) == "exists") ||
106                (args.size() == 3 && args.at(1) == "entities") ||
107                (args.size() == 4 && args.at(1) == "dates") ||
108                (args.size() == 5 && args.at(1) == "events") ||
109                (args.size() == 5 && args.at(1) == "filteredEvents")) {
110         Tp::AccountPtr account = accountPtr(args.at(2));
111         if (account.isNull()) {
112             qWarning() << "Account not found " << args.at(2);
113         }
114         return true;
115     } else if (args.size() == 3 && args.at(1) == "search") {
116         Tpl::PendingSearch *ps = logManager->search(args.at(2), Tpl::EventTypeMaskAny);
117         qDebug() << "PendingSearch=" << ps;
118         if (!ps) {
119             qWarning() << "Error in search";
120             this->exit(-1);
121             return false;
122         }
123 
124         connect(ps,
125                 SIGNAL(finished(Tpl::PendingOperation*)),
126                 this,
127                 SLOT(onPendingSearch(Tpl::PendingOperation*)));
128 
129         return true;
130     }
131 
132     qDebug() << "Telepathy logger command line tool (qt4)";
133     qDebug() << "";
134     qDebug() << "General usage: tpl-tool <command> <parameters>";
135     qDebug() << "";
136     qDebug() << "tpl-tool accounts";
137     qDebug() << "tpl-tool contacts <account>";
138     qDebug() << "tpl-tool exists <account> <entity>";
139     qDebug() << "tpl-tool entities <account>";
140     qDebug() << "tpl-tool dates <account> <entity>";
141     qDebug() << "tpl-tool events <account> <entity> <date>";
142     qDebug() << "tpl-tool filteredEvents <account> <entity> <numEvents>";
143     qDebug() << "tpl-tool search <text>";
144     this->exit(-1);
145 
146     return false;
147 }
148 
parseArgs2()149 bool TplToolApplication::parseArgs2()
150 {
151     qDebug();
152 
153     QStringList args = arguments();
154 
155     Tpl::LogManagerPtr logManager = Tpl::LogManager::instance();
156     if (logManager.isNull()) {
157         qWarning() << "LogManager not found";
158         return false;
159     }
160 
161     if (args.size() == 3 && args.at(1) == "contacts") {
162         Tp::Contacts contacts = mAccountPtr->connection()->contactManager()->allKnownContacts();
163         qDebug() << "number of contacts = " << contacts.size();
164 
165         Tp::ContactPtr contact;
166         int i = 0;
167         Q_FOREACH(contact, contacts) {
168             qDebug() << "contact " << i++ << contact->id();
169         }
170         this->exit();
171         return true;
172     } else if (args.size() == 4 && args.at(1) == "exists") {
173         Tpl::EntityPtr entity = entityPtr(args.at(3));
174         if (entity.isNull()) {
175             qWarning() << "Entity not found " << args.at(3);
176         }
177 
178         bool ret = logManager->exists(mAccountPtr, entity, Tpl::EventTypeMaskAny);
179         qDebug() << "tpl-tool exists " << args.at(2) << args.at(3) << " -> " << ret;
180         this->exit();
181         return true;
182     } else if (args.at(1) == "entities") {
183         Tpl::PendingEntities *pe = logManager->queryEntities(mAccountPtr);
184         qDebug() << "PendingEntities=" << pe;
185         if (!pe) {
186             qWarning() << "Error in PendingEntities";
187             this->exit(-1);
188             return false;
189         }
190 
191         connect(pe,
192                 SIGNAL(finished(Tpl::PendingOperation*)),
193                 this,
194                 SLOT(onPendingEntities(Tpl::PendingOperation*)));
195 
196         return true;
197     } else if (args.at(1) == "dates") {
198         Tpl::EntityPtr entity = entityPtr(args.at(3));
199         if (entity.isNull()) {
200             qWarning() << "Entity not found " << args.at(3);
201         }
202 
203         Tpl::PendingDates *pd = logManager->queryDates(mAccountPtr, entity, Tpl::EventTypeMaskAny);
204         qDebug() << "PendingDates=" << pd;
205         if (!pd) {
206             qWarning() << "Error in PendingDates";
207             this->exit(-1);
208             return false;
209         }
210 
211         connect(pd,
212                 SIGNAL(finished(Tpl::PendingOperation*)),
213                 this,
214                 SLOT(onPendingDates(Tpl::PendingOperation*)));
215 
216         return true;
217     } else if (args.at(1) == "events") {
218         Tpl::EntityPtr entity = entityPtr(args.at(3));
219         if (entity.isNull()) {
220             qWarning() << "Entity not found " << args.at(3);
221         }
222 
223         QDate date = QDate::fromString(args.at(4), TPL_TOOL_DATE_FORMAT);
224 
225         Tpl::PendingEvents *pe = logManager->queryEvents(mAccountPtr, entity, Tpl::EventTypeMaskAny, date);
226         qDebug() << "PendingEvents=" << pe << "date=" << date;
227         if (!pe) {
228             qWarning() << "Error in PendingDates";
229             this->exit(-1);
230             return false;
231         }
232 
233         connect(pe,
234                 SIGNAL(finished(Tpl::PendingOperation*)),
235                 this,
236                 SLOT(onPendingEvents(Tpl::PendingOperation*)));
237 
238         return true;
239     } else if (args.at(1) == "filteredEvents") {
240         Tpl::EntityPtr entity = entityPtr(args.at(3));
241         if (entity.isNull()) {
242             qWarning() << "Entity not found " << args.at(3);
243         }
244 
245         Tpl::PendingEvents *pe = logManager->queryFilteredEvents(mAccountPtr, entity, Tpl::EventTypeMaskAny, args.at(4).toInt(), &TplToolApplication::eventFilterMethod, this);
246         qDebug() << "PendingEvents (filtered) =" << pe << "numEvents=" << args.at(4);
247         if (!pe) {
248             qWarning() << "Error in PendingDates";
249             this->exit(-1);
250             return false;
251         }
252 
253         connect(pe,
254                 SIGNAL(finished(Tpl::PendingOperation*)),
255                 this,
256                 SLOT(onPendingEvents(Tpl::PendingOperation*)));
257 
258         return true;
259     }
260 
261     this->exit(-1);
262     return false;
263 }
264 
onAccountManagerReady(Tp::PendingOperation * po)265 void TplToolApplication::onAccountManagerReady(Tp::PendingOperation *po)
266 {
267     qDebug() << "po=" << po << "isError=" << po->isError();
268 
269     if (po->isError()) {
270         qWarning() << "error getting account mananger ready";
271         exit(-1);
272         return;
273     }
274 
275     Tpl::LogManagerPtr logManager = Tpl::LogManager::instance();
276     if (logManager.isNull()) {
277         qWarning() << "LogManager not found";
278         exit(-1);
279         return;
280     }
281 
282     logManager->setAccountManagerPtr(mAccountManager);
283 
284     parseArgs1();
285 }
286 
onAccountReady(Tp::PendingOperation * po)287 void TplToolApplication::onAccountReady(Tp::PendingOperation *po)
288 {
289     qDebug() << "po=" << po << "isError=" << po->isError();
290 
291     if (po->isError()) {
292         qWarning() << "error getting account ready";
293         exit(-1);
294         return;
295     }
296 
297     Tp::ConnectionPtr connection = mAccountPtr->connection();
298     if (connection.isNull()) {
299         qWarning() << "error null connection";
300         exit(-1);
301         return;
302     }
303 
304     connect(mAccountPtr->connection()->becomeReady(Tp::Features() << Tp::Connection::FeatureCore << Tp::Connection::FeatureSelfContact << Tp::Connection::FeatureRoster),
305         SIGNAL(finished(Tp::PendingOperation*)),
306         this,
307         SLOT(onConnectionReady(Tp::PendingOperation*)));
308 }
309 
onConnectionReady(Tp::PendingOperation * po)310 void TplToolApplication::onConnectionReady(Tp::PendingOperation *po)
311 {
312     qDebug() << "po=" << po << "isError=" << po->isError();
313 
314     if (po->isError()) {
315         qWarning() << "error getting connection ready";
316         exit(-1);
317         return;
318     }
319 
320     parseArgs2();
321 }
322 
onPendingSearch(Tpl::PendingOperation * po)323 void TplToolApplication::onPendingSearch(Tpl::PendingOperation *po)
324 {
325     Tpl::PendingSearch *ps = (Tpl::PendingSearch*) po;
326 
327     if (ps->isError()) {
328         qWarning() << "error in search";
329         exit(-1);
330         return;
331     }
332 
333     Tpl::SearchHitList hits = ps->hits();
334     qDebug() << " search hits " << hits.size();
335 
336     int count = 0;
337 
338     Q_FOREACH(const Tpl::SearchHit &hit, hits) {
339         qDebug() << count++ << "account=" << hit.account.data() << (hit.account.isNull() ? "null" : hit.account->objectPath())
340                  << "date=" << hit.date.toString(TPL_TOOL_DATE_FORMAT)
341                  << "target=" << (hit.target ? hit.target->identifier() + '/' + hit.target->alias() + '/' + QString::number(hit.target->entityType()) + '/' + hit.target->avatarToken() : "null");
342     }
343 
344     this->exit();
345 }
346 
onPendingEntities(Tpl::PendingOperation * po)347 void TplToolApplication::onPendingEntities(Tpl::PendingOperation *po)
348 {
349     Tpl::PendingEntities *pe = (Tpl::PendingEntities*) po;
350 
351     if (pe->isError()) {
352         qWarning() << "error in search";
353         exit(-1);
354         return;
355     }
356 
357     Tpl::EntityPtrList entities= pe->entities();
358     qDebug() << " Pending entities " << entities.size();
359 
360     int count = 0;
361     Tpl::EntityPtr entity;
362     Q_FOREACH(entity, entities) {
363         qDebug() << count++ << "entity id=" << entity->identifier() << "alias=" << entity->alias() << "type=" << entity->entityType() << "avatarToken=" << entity->avatarToken();
364     }
365 
366     this->exit();
367 }
368 
onPendingDates(Tpl::PendingOperation * po)369 void TplToolApplication::onPendingDates(Tpl::PendingOperation *po)
370 {
371     Tpl::PendingDates *pd = (Tpl::PendingDates*) po;
372 
373     if (pd->isError()) {
374         qWarning() << "error in search";
375         exit(-1);
376         return;
377     }
378 
379     Tpl::QDateList dates = pd->dates();
380     qDebug() << " Pending dates " << dates.size();
381 
382     int count = 0;
383     QDate date;
384     Q_FOREACH(date, dates) {
385         qDebug() << count++ << "date " << date.toString(TPL_TOOL_DATE_FORMAT);
386     }
387 
388     this->exit();
389 }
390 
onPendingEvents(Tpl::PendingOperation * po)391 void TplToolApplication::onPendingEvents(Tpl::PendingOperation *po)
392 {
393     Tpl::PendingEvents *pe = (Tpl::PendingEvents*) po;
394 
395     if (pe->isError()) {
396         qWarning() << "error in PendingEvents";
397         exit(-1);
398         return;
399     }
400 
401     Tpl::EventPtrList events = pe->events();
402     qDebug() << " Pending events " << events.size();
403 
404     int count = 0;
405     QObject a;
406     Tpl::EventPtr event;
407     Q_FOREACH(event, events) {
408         Tpl::TextEventPtr textEvent = event.dynamicCast<Tpl::TextEvent>();
409         Tpl::CallEventPtr callEvent = event.dynamicCast<Tpl::CallEvent>();
410         if (!textEvent.isNull()) {
411             qDebug() << count++ << "textEvent"
412                       << "timestamp=" << textEvent->timestamp().toString()
413                       << "sender=" << textEvent->sender()->identifier()
414                       << "receiver=" << textEvent->receiver()->identifier()
415                       << "message=" << textEvent->message()
416                       << "messageType=" << textEvent->messageType()
417                       << "account=" << (textEvent->account() ? textEvent->account()->objectPath() : "null")
418                       << "accountPath=" << textEvent->accountPath();
419         } else if (!callEvent.isNull()) {
420             qDebug() << count++ << "callEvent"
421                       << "timestamp=" << callEvent->timestamp().toString()
422                       << "sender=" << callEvent->sender()->identifier()
423                       << "receiver=" << callEvent->receiver()->identifier()
424                       << "duraton=" << callEvent->duration()
425                       << "endActor=" << callEvent->endActor()->identifier()
426                       << "endReason=" << callEvent->endReason()
427                       << "detailedEndReason=" << callEvent->detailedEndReason()
428                       << "account=" << (callEvent->account() ? callEvent->account()->objectPath() : "null")
429                       << "accountPath=" << callEvent->accountPath();
430         } else {
431             qDebug() << count++ << "event"
432                       << "timestamp=" << event->timestamp().toString()
433                       << "sender=" << event->sender()->identifier()
434                       << "receiver=" << event->receiver()->identifier()
435                       << "account=" << (event->account() ? event->account()->objectPath() : "null")
436                       << "accountPath=" << event->accountPath();
437         }
438     }
439 
440     this->exit();
441 }
442 
eventFilterMethod(const Tpl::EventPtr & event,void * user_data)443 bool TplToolApplication::eventFilterMethod(const Tpl::EventPtr &event, void *user_data)
444 {
445     return true;
446 }
447 
main(int argc,char ** argv)448 int main(int argc, char **argv)
449 {
450     g_type_init();
451     Tp::registerTypes();
452 
453     TplToolApplication app(argc, argv);
454     Tpl::init();
455 
456     return app.exec();
457 }
458