~ubuntu-branches/ubuntu/karmic/choqok/karmic

« back to all changes in this revision

Viewing changes to src/twittersearch.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christian Mangold
  • Date: 2009-04-30 20:41:19 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20090430204119-v1k5uw4aejloyfo7
Tags: 0.5-0ubuntu1
* New upstream release (LP: #370009)
* Bumped Standards-Version to 3.8.1
* Switched to pkg-kde-tools

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
    This file is part of choqoK, the KDE micro-blogging client
 
3
 
 
4
    Copyright (C) 2008-2009 Mehrdad Momeny <mehrdad.momeny@gmail.com>
 
5
 
 
6
    This program is free software; you can redistribute it and/or
 
7
    modify it under the terms of the GNU General Public License as
 
8
    published by the Free Software Foundation; either version 2 of
 
9
    the License or (at your option) version 3 or any later version
 
10
    accepted by the membership of KDE e.V. (or its successor approved
 
11
    by the membership of KDE e.V.), which shall act as a proxy
 
12
    defined in Section 14 of version 3 of the license.
 
13
 
 
14
 
 
15
    This program is distributed in the hope that it will be useful,
 
16
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
18
    GNU General Public License for more details.
 
19
 
 
20
    You should have received a copy of the GNU General Public License
 
21
    along with this program; if not, see http://www.gnu.org/licenses/
 
22
 
 
23
*/
 
24
 
 
25
#include "twittersearch.h"
 
26
 
 
27
#include <KDE/KLocale>
 
28
#include <QDomDocument>
 
29
#include <kio/jobclasses.h>
 
30
#include <kio/job.h>
 
31
#include <kurl.h>
 
32
#include <kio/netaccess.h>
 
33
#include <kdebug.h>
 
34
 
 
35
#include "backend.h"
 
36
 
 
37
TwitterSearch::TwitterSearch( Account* account, const QString searchUrl, QObject *parent ) :
 
38
        Search(account, searchUrl, parent)
 
39
{
 
40
    kDebug();
 
41
    mSearchTypes[CustomSearch].first = i18n( "Custom Search" );
 
42
    mSearchTypes[CustomSearch].second = true;
 
43
 
 
44
    mSearchTypes[ToUser].first = i18n( "Tweets To This User" );
 
45
    mSearchTypes[ToUser].second = true;
 
46
 
 
47
    mSearchTypes[FromUser].first = i18n( "Tweets From This User" );
 
48
    mSearchTypes[FromUser].second = true;
 
49
 
 
50
    mSearchTypes[ReferenceUser].first = i18n( "Tweets Including This User's Name" );
 
51
    mSearchTypes[ReferenceUser].second = true;
 
52
 
 
53
    mSearchTypes[ReferenceHashtag].first = i18n( "Tweets Including This Hashtag" );
 
54
    mSearchTypes[ReferenceHashtag].second = true;
 
55
}
 
56
 
 
57
TwitterSearch::~TwitterSearch()
 
58
{
 
59
    kDebug();
 
60
}
 
61
 
 
62
KUrl TwitterSearch::buildUrl( QString query, int option, uint sinceStatusId, uint count, uint page )
 
63
{
 
64
    kDebug();
 
65
    QString baseUrl = "http://search.twitter.com/search.atom?";
 
66
    if( sinceStatusId )
 
67
        baseUrl += "since_id=" + QString::number( sinceStatusId ) + '&';
 
68
    if( count && count <= 100 )
 
69
        baseUrl += "rpp=" + QString::number( count ) + '&';
 
70
    baseUrl += "page=" + QString::number( page ) + '&';
 
71
    baseUrl += "q=";
 
72
 
 
73
    QString formattedQuery;
 
74
    switch ( option ) {
 
75
        case CustomSearch:
 
76
            formattedQuery = query;
 
77
            break;
 
78
        case ToUser:
 
79
            formattedQuery = "to:" + query;
 
80
            break;
 
81
        case FromUser:
 
82
            formattedQuery = "from:" + query;
 
83
            break;
 
84
        case ReferenceUser:
 
85
            formattedQuery = '@' + query;
 
86
            break;
 
87
        case ReferenceHashtag:
 
88
            formattedQuery = "%23" + query;
 
89
            break;
 
90
        default:
 
91
            formattedQuery = query;
 
92
            break;
 
93
    };
 
94
 
 
95
    KUrl url;
 
96
    url.setUrl( baseUrl + formattedQuery );
 
97
 
 
98
    return url;
 
99
}
 
100
 
 
101
void TwitterSearch::requestSearchResults( QString query, int option, uint sinceStatusId, uint count, uint page )
 
102
{
 
103
    kDebug();
 
104
 
 
105
    KUrl url = buildUrl( query, option, sinceStatusId, count, page );
 
106
 
 
107
    KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo );
 
108
    if( !job ) {
 
109
        kDebug() << "Cannot create a http GET request!";
 
110
        emit error( i18n( "Unable to fetch search results." ) );
 
111
        return;
 
112
    }
 
113
 
 
114
    connect( job, SIGNAL( result( KJob* ) ), this, SLOT( searchResultsReturned( KJob* ) ) );
 
115
    job->start();
 
116
}
 
117
 
 
118
void TwitterSearch::searchResultsReturned( KJob* job )
 
119
{
 
120
    kDebug();
 
121
    if( job == 0 ) {
 
122
        kDebug() << "job is a null pointer";
 
123
        emit error( i18n( "Unable to fetch search results." ) );
 
124
        return;
 
125
    }
 
126
 
 
127
    if( job->error() ) {
 
128
        kError() << "Error: " << job->errorString();
 
129
        emit error( i18n( "Unable to fetch search results. Error: %1", job->errorString() ) );
 
130
        return;
 
131
    }
 
132
    KIO::StoredTransferJob *jj = qobject_cast<KIO::StoredTransferJob *>( job );
 
133
    QList<Status>* statusList = parseAtom( jj->data() );
 
134
 
 
135
    emit searchResultsReceived( *statusList );
 
136
}
 
137
 
 
138
QList<Status>* TwitterSearch::parseAtom( const QByteArray &buffer )
 
139
{
 
140
    kDebug();
 
141
    QDomDocument document;
 
142
    QList<Status> *statusList = new QList<Status>;
 
143
 
 
144
    document.setContent( buffer );
 
145
 
 
146
    QDomElement root = document.documentElement();
 
147
 
 
148
    if ( root.tagName() != "feed" ) {
 
149
        kDebug() << "There is no feed element in Atom feed " << buffer.data();
 
150
        return statusList;
 
151
    }
 
152
 
 
153
    QDomNode node = root.firstChild();
 
154
    QString timeStr;
 
155
    while ( !node.isNull() ) {
 
156
        if ( node.toElement().tagName() != "entry" ) {
 
157
            node = node.nextSibling();
 
158
            continue;
 
159
        }
 
160
 
 
161
        QDomNode entryNode = node.firstChild();
 
162
        Status status;
 
163
        status.isDMessage = false;
 
164
 
 
165
        while ( !entryNode.isNull() ) {
 
166
            if ( entryNode.toElement().tagName() == "id" ) {
 
167
                // Fomatting example: "tag:search.twitter.com,2005:1235016836"
 
168
                int id = 0;
 
169
                sscanf( qPrintable( entryNode.toElement().text() ),
 
170
                        "tag:search.twitter.com,%*d:%d", &id);
 
171
                status.statusId = id;
 
172
            } else if ( entryNode.toElement().tagName() == "published" ) {
 
173
                // Formatting example: "2009-02-21T19:42:39Z"
 
174
                // Need to extract date in similar fashion to dateFromString
 
175
                int year, month, day, hour, minute, second;
 
176
                sscanf( qPrintable( entryNode.toElement().text() ),
 
177
                        "%d-%d-%dT%d:%d:%d%*s", &year, &month, &day, &hour, &minute, &second);
 
178
                QDateTime recognized( QDate( year, month, day), QTime( hour, minute, second ) );
 
179
                recognized.setTimeSpec( Qt::UTC );
 
180
                status.creationDateTime = recognized;
 
181
            } else if ( entryNode.toElement().tagName() == "title" ) {
 
182
                status.content = entryNode.toElement().text();
 
183
            } else if ( entryNode.toElement().tagName() == "twitter:source" ) {
 
184
                status.source = entryNode.toElement().text();
 
185
            } else if ( entryNode.toElement().tagName() == "link" &&
 
186
                        entryNode.toElement().attributeNode( "rel" ).value() == "image") {
 
187
 
 
188
                QDomAttr imageAttr = entryNode.toElement().attributeNode( "href" );
 
189
                status.user.profileImageUrl = imageAttr.value();
 
190
 
 
191
            } else if ( entryNode.toElement().tagName() == "author") {
 
192
 
 
193
                QDomNode userNode = entryNode.firstChild();
 
194
                while ( !userNode.isNull() )
 
195
                {
 
196
                    if ( userNode.toElement().tagName() == "name" )
 
197
                    {
 
198
                        QString fullName = userNode.toElement().text();
 
199
                        int bracketPos = fullName.indexOf( " ", 0 );
 
200
 
 
201
                        QString screenName = fullName.left( bracketPos );
 
202
                        QString name = fullName.right ( fullName.size() - bracketPos - 2 );
 
203
                        name.chop( 1 );
 
204
 
 
205
                        status.user.name = name;
 
206
                        status.user.screenName = screenName;
 
207
                    }
 
208
                    userNode = userNode.nextSibling();
 
209
                }
 
210
 
 
211
            }
 
212
 
 
213
            entryNode = entryNode.nextSibling();
 
214
        }
 
215
        status.isFavorited = false;
 
216
        status.isTruncated = false;
 
217
        status.replyToStatusId = 0;
 
218
        statusList->insert( 0, status );
 
219
        node = node.nextSibling();
 
220
    }
 
221
 
 
222
    return statusList;
 
223
}