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

« back to all changes in this revision

Viewing changes to choqok/twittersearch.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alessandro Ghersi, Alessandro Ghersi, Christian Mangold
  • Date: 2009-08-11 22:29:59 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090811222959-7tnr98ptcnyx3pjg
Tags: 0.6.6-0ubuntu1
[Alessandro Ghersi]
* New upstream release
  - Bump Standards-Version to 3.8.2
  - Long description formatted to fit in 80 characters

[Christian Mangold]
* Improve long description
* Update Maintainer, package is in main now
* Add a watch file

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, "tag:search.twitter.com,[0-9]+:([0-9]+)", searchUrl, parent)
 
39
{
 
40
    kDebug();
 
41
    mSearchTypes[CustomSearch].first = i18n( "Custom Search" );
 
42
    mSearchTypes[CustomSearch].second = true;
 
43
 
 
44
    mSearchTypes[ToUser].first = i18nc( "Tweets are Twitter posts",  "Tweets To This User" );
 
45
    mSearchTypes[ToUser].second = true;
 
46
 
 
47
    mSearchTypes[FromUser].first = i18nc( "Tweets are Twitter posts", "Tweets From This User" );
 
48
    mSearchTypes[FromUser].second = true;
 
49
 
 
50
    mSearchTypes[ReferenceUser].first = i18nc( "Tweets are Twitter posts", "Tweets Including This User's Name" );
 
51
    mSearchTypes[ReferenceUser].second = true;
 
52
 
 
53
    mSearchTypes[ReferenceHashtag].first = i18nc( "Tweets are Twitter posts", "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, qulonglong sinceStatusId, qulonglong count, qulonglong page )
 
63
{
 
64
    kDebug();
 
65
    QString formattedQuery;
 
66
    switch ( option ) {
 
67
        case CustomSearch:
 
68
            formattedQuery = query;
 
69
            break;
 
70
        case ToUser:
 
71
            formattedQuery = "to:" + query;
 
72
            break;
 
73
        case FromUser:
 
74
            formattedQuery = "from:" + query;
 
75
            break;
 
76
        case ReferenceUser:
 
77
            formattedQuery = '@' + query;
 
78
            break;
 
79
        case ReferenceHashtag:
 
80
            formattedQuery = "#" + query;
 
81
            break;
 
82
        default:
 
83
            formattedQuery = query;
 
84
            break;
 
85
    };
 
86
    KUrl url( "http://search.twitter.com/search.atom" );
 
87
    url.addQueryItem("q", formattedQuery);
 
88
    if( sinceStatusId )
 
89
        url.addQueryItem( "since_id", QString::number( sinceStatusId ) );
 
90
    if( count && count <= 100 )
 
91
        url.addQueryItem( "rpp", QString::number( count ) );
 
92
    url.addQueryItem( "page", QString::number( page ) );
 
93
 
 
94
    return url;
 
95
}
 
96
 
 
97
void TwitterSearch::requestSearchResults( QString query, int option, qulonglong sinceStatusId, qulonglong count, qulonglong page )
 
98
{
 
99
    kDebug();
 
100
 
 
101
    KUrl url = buildUrl( query, option, sinceStatusId, count, page );
 
102
 
 
103
    KIO::StoredTransferJob *job = KIO::storedGet( url, KIO::Reload, KIO::HideProgressInfo );
 
104
    if( !job ) {
 
105
        kDebug() << "Cannot create a http GET request!";
 
106
        emit error( i18n( "Unable to fetch search results." ) );
 
107
        return;
 
108
    }
 
109
 
 
110
    connect( job, SIGNAL( result( KJob* ) ), this, SLOT( searchResultsReturned( KJob* ) ) );
 
111
    job->start();
 
112
}
 
113
 
 
114
void TwitterSearch::searchResultsReturned( KJob* job )
 
115
{
 
116
    kDebug();
 
117
    if( job == 0 ) {
 
118
        kDebug() << "job is a null pointer";
 
119
        emit error( i18n( "Unable to fetch search results." ) );
 
120
        return;
 
121
    }
 
122
 
 
123
    if( job->error() ) {
 
124
        kError() << "Error: " << job->errorString();
 
125
        emit error( i18n( "Unable to fetch search results: %1", job->errorString() ) );
 
126
        return;
 
127
    }
 
128
    KIO::StoredTransferJob *jj = qobject_cast<KIO::StoredTransferJob *>( job );
 
129
    QList<Status>* statusList = parseAtom( jj->data() );
 
130
 
 
131
    emit searchResultsReceived( *statusList );
 
132
}
 
133
 
 
134
QList<Status>* TwitterSearch::parseAtom( const QByteArray &buffer )
 
135
{
 
136
    kDebug();
 
137
    QDomDocument document;
 
138
    QList<Status> *statusList = new QList<Status>;
 
139
    
 
140
    document.setContent( buffer );
 
141
    
 
142
    QDomElement root = document.documentElement();
 
143
    
 
144
    if ( root.tagName() != "feed" ) {
 
145
        kDebug() << "There is no feed element in Atom feed " << buffer.data();
 
146
        return statusList;
 
147
    }
 
148
    
 
149
    QDomNode node = root.firstChild();
 
150
    QString timeStr;
 
151
    while ( !node.isNull() ) {
 
152
        if ( node.toElement().tagName() != "entry" ) {
 
153
            node = node.nextSibling();
 
154
            continue;
 
155
        }
 
156
        
 
157
        QDomNode entryNode = node.firstChild();
 
158
        Status status;
 
159
        status.isDMessage = false;
 
160
        
 
161
        while ( !entryNode.isNull() ) {
 
162
            QDomElement elm = entryNode.toElement();
 
163
            if ( elm.tagName() == "id" ) {
 
164
                // Fomatting example: "tag:search.twitter.com,2005:1235016836"
 
165
                qulonglong id = 0;
 
166
                if(m_rId.exactMatch(elm.text())) {
 
167
                    id = m_rId.cap(1).toULongLong();
 
168
                }
 
169
                /*                sscanf( qPrintable( elm.text() ),
 
170
                "tag:search.twitter.com,%*d:%d", &id);*/
 
171
                status.statusId = id;
 
172
            } else if ( elm.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( elm.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 ( elm.tagName() == "title" ) {
 
182
                status.content = elm.text();
 
183
            } else if ( elm.tagName() == "twitter:source" ) {
 
184
                status.source = elm.text();
 
185
            } else if ( elm.tagName() == "link" &&
 
186
                elm.attributeNode( "rel" ).value() == "image") {
 
187
                QDomAttr imageAttr = elm.attributeNode( "href" );
 
188
            status.user.profileImageUrl = imageAttr.value();
 
189
            } else if ( elm.tagName() == "author") {
 
190
                QDomNode userNode = entryNode.firstChild();
 
191
                while ( !userNode.isNull() )
 
192
                {
 
193
                    if ( userNode.toElement().tagName() == "name" )
 
194
                    {
 
195
                        QString fullName = userNode.toElement().text();
 
196
                        int bracketPos = fullName.indexOf( " ", 0 );
 
197
                        
 
198
                        QString screenName = fullName.left( bracketPos );
 
199
                        QString name = fullName.right ( fullName.size() - bracketPos - 2 );
 
200
                        name.chop( 1 );
 
201
                        
 
202
                        status.user.name = name;
 
203
                        status.user.screenName = screenName;
 
204
                    }
 
205
                    userNode = userNode.nextSibling();
 
206
                }
 
207
            }
 
208
            entryNode = entryNode.nextSibling();
 
209
        }
 
210
        status.isFavorited = false;
 
211
        status.isTruncated = false;
 
212
        status.replyToStatusId = 0;
 
213
        statusList->insert( 0, status );
 
214
        node = node.nextSibling();
 
215
    }
 
216
    
 
217
    return statusList;
 
218
}