1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-11 16:44:05 +02:00

Sync with upstream qtweetlib

This commit is contained in:
Jeff Mitchell
2011-03-22 10:12:46 -04:00
parent 2ffe51163c
commit c15c99cfa9
5 changed files with 123 additions and 80 deletions

View File

@@ -61,6 +61,7 @@ QTweetStatus QTweetConvert::variantMapToStatus(const QVariantMap &var)
status.setId(var["id"].toLongLong());
status.setInReplyToUserId(var["in_reply_to_user_id"].toLongLong());
status.setInReplyToScreenName(var["in_reply_to_screen_name"].toString());
status.setFavorited(var["favorited"].toBool());
QVariantMap userMap = var["user"].toMap();
QTweetUser user = variantMapToUserInfo(userMap);

View File

@@ -64,7 +64,7 @@ void QTweetFriendshipDestroy::unfollow(qint64 userid, bool includeEntities)
QNetworkRequest req(url);
QByteArray oauthHeader = oauthTwitter()->generateAuthorizationHeader(url, OAuth::GET);
QByteArray oauthHeader = oauthTwitter()->generateAuthorizationHeader(url, OAuth::DELETE);
req.setRawHeader(AUTH_HEADER, oauthHeader);
QNetworkReply *reply = oauthTwitter()->networkAccessManager()->deleteResource(req);
@@ -92,7 +92,7 @@ void QTweetFriendshipDestroy::unfollow(const QString &screenName, bool includeEn
QNetworkRequest req(url);
QByteArray oauthHeader = oauthTwitter()->generateAuthorizationHeader(url, OAuth::GET);
QByteArray oauthHeader = oauthTwitter()->generateAuthorizationHeader(url, OAuth::DELETE);
req.setRawHeader(AUTH_HEADER, oauthHeader);
QNetworkReply *reply = oauthTwitter()->networkAccessManager()->deleteResource(req);

View File

@@ -69,7 +69,7 @@ void QTweetSearchResult::setCreatedAt(const QDateTime &dateTime)
void QTweetSearchResult::setCreatedAt(const QString &twitterDate)
{
QString dateString = twitterDate.left(3) + ' ' + twitterDate.mid(8, 3) + ' ' +
twitterDate.mid(5, 2) + ' ' + twitterDate.mid(13, 4);
twitterDate.mid(5, 2) + ' ' + twitterDate.mid(12, 4);
QString timeString = twitterDate.mid(17, 8);
QDate date = QDate::fromString(dateString);

View File

@@ -33,14 +33,28 @@
#define TWITTER_USERSTREAM_URL "https://userstream.twitter.com/2/user.json"
// ### TODO User Agent or X-User-Agent
/**
* Constructor
*/
QTweetUserStream::QTweetUserStream(QObject *parent) :
QObject(parent), m_oauthTwitter(0), m_reply(0), m_backofftimer(new QTimer(this))
QObject(parent), m_oauthTwitter(0), m_reply(0),
m_backofftimer(new QTimer(this)),
m_timeoutTimer(new QTimer(this)),
m_streamTryingReconnect(false)
{
m_backofftimer->setInterval(20000);
m_backofftimer->setSingleShot(true);
connect(m_backofftimer, SIGNAL(timeout()), this, SLOT(startFetching()));
m_timeoutTimer->setInterval(90000);
connect(m_timeoutTimer, SIGNAL(timeout()), this, SLOT(replyTimeout()));
#ifdef STREAM_LOGGER
m_streamLog.setFileName("streamlog.txt");
m_streamLog.open(QIODevice::WriteOnly | QIODevice::Text);
#endif
}
/**
@@ -59,49 +73,6 @@ OAuthTwitter* QTweetUserStream::oauthTwitter() const
return m_oauthTwitter;
}
/**
* Called when there is network error
*/
void QTweetUserStream::replyError(QNetworkReply::NetworkError code)
{
qDebug() << "Reply error: " << code;
// ### TODO: determine network error codes, assumptions here
if (code < 200) {
//linear backoff
if (m_backofftimer->interval() < 250) {
m_backofftimer->setInterval(250);
} else {
int nextLinInterval = m_backofftimer->interval() + 250;
if (nextLinInterval > 16000) //cap
nextLinInterval = 16000;
m_backofftimer->setInterval(nextLinInterval);
}
m_backofftimer->start();
return;
}
if (code > 200) {
//exp. backoff
if (m_backofftimer->interval() < 10000) {
m_backofftimer->setInterval(10000);
} else {
int nextExpInterval = 2 * m_backofftimer->interval();
if (nextExpInterval > 240000)
nextExpInterval = 240000;
m_backofftimer->setInterval(240000);
}
m_backofftimer->start();
}
}
/**
* Starts fetching user stream
*/
@@ -122,7 +93,9 @@ void QTweetUserStream::startFetching()
m_reply = m_oauthTwitter->networkAccessManager()->get(req);
connect(m_reply, SIGNAL(finished()), this, SLOT(replyFinished()));
connect(m_reply, SIGNAL(readyRead()), this, SLOT(replyReadyRead()));
connect(m_reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError)));
connect(m_reply, SIGNAL(readyRead()), m_timeoutTimer, SLOT(start()));
connect(m_reply, SIGNAL(finished()), m_timeoutTimer, SLOT(stop()));
}
/**
@@ -130,16 +103,40 @@ void QTweetUserStream::startFetching()
*/
void QTweetUserStream::replyFinished()
{
if (!m_reply->error()) { //no error, reconnect
qDebug() << "User stream closed ";
//sligh delay for reconnect
m_backofftimer->setInterval(250);
m_streamTryingReconnect = true;
if (!m_reply->error()) { //no error, reconnect
qDebug() << "No error, reconnect";
m_reply->deleteLater();
m_reply = 0;
startFetching();
} else { //error
qDebug() << "Error: " << m_reply->error() << ", " << m_reply->errorString();
m_reply->deleteLater();
m_reply = 0;
//if (m_backofftimer->interval() < 20001) {
// m_backofftimer->start();
// return;
//}
//increase back off interval
int nextInterval = 2 * m_backofftimer->interval();
if (nextInterval > 300000) {
m_backofftimer->setInterval(300000);
emit failureConnect();
}
m_backofftimer->setInterval(nextInterval);
m_backofftimer->start();
m_reply->deleteLater();
m_reply = 0;
} else { //error, delete QNetworkReply
m_reply->deleteLater();
m_reply = 0;
qDebug() << "Exp backoff interval: " << nextInterval;
}
}
@@ -147,30 +144,53 @@ void QTweetUserStream::replyReadyRead()
{
QByteArray response = m_reply->readAll();
//reset timer
m_backofftimer->setInterval(0);
#ifdef STREAM_LOGGER
m_streamLog.write(response);
m_streamLog.write("\n");
#endif
//split to response to delimited and not delimited part
int lastCarrReturn = response.lastIndexOf('\r');
QByteArray rightNotDelimitedPart = response.mid(lastCarrReturn + 1);
QByteArray leftDelimitedPart = response.left(lastCarrReturn);
if (m_streamTryingReconnect) {
emit reconnected();
m_streamTryingReconnect = false;
}
//prepend to left previous not delimited response
leftDelimitedPart = leftDelimitedPart.prepend(m_cashedResponse);
//set backoff timer to initial interval
m_backofftimer->setInterval(20000);
QList<QByteArray> elements = leftDelimitedPart.split('\r');
QByteArray responseWithPreviousCache = response.prepend(m_cachedResponse);
for (int i = 0; i < elements.size(); ++i) {
if (elements.at(i) != QByteArray(1, '\n')) {
emit stream(elements.at(i));
parseStream(elements.at(i));
int start = 0;
int end;
while ((end = responseWithPreviousCache.indexOf('\r', start)) != -1) {
if (start != end) {
QByteArray element = responseWithPreviousCache.mid(start, end - start);
if (!element.isEmpty()) {
emit stream(element);
parseStream(element);
}
}
if (rightNotDelimitedPart != QByteArray(1, '\n'))
m_cashedResponse = rightNotDelimitedPart;
else
m_cashedResponse.clear();
int skip = (response.at(end + 1) == QLatin1Char('\n')) ? 2 : 1;
start = end + skip;
}
//undelimited part just cache it
m_cachedResponse.clear();
if (start != responseWithPreviousCache.size()) {
QByteArray element = responseWithPreviousCache.mid(start);
if (!element.isEmpty())
m_cachedResponse = element;
}
}
void QTweetUserStream::replyTimeout()
{
qDebug() << "Timeout connection";
m_reply->abort();
}
void QTweetUserStream::parseStream(const QByteArray& data)
@@ -187,6 +207,9 @@ void QTweetUserStream::parsingFinished(const QVariant &json, bool ok, const QStr
{
if (!ok) {
qDebug() << "JSON parsing error: " << errorMsg;
#ifdef STREAM_LOGGER
m_streamLog.write("***** JSON parsing error *****\n");
#endif
return;
}

View File

@@ -25,6 +25,10 @@
#include <QNetworkReply>
#include "qtweetlib_global.h"
#ifdef STREAM_LOGGER
#include <QFile>
#endif
class QNetworkAccessManager;
class QNetworkReply;
class OAuthTwitter;
@@ -49,7 +53,6 @@ signals:
* Emits stream elements
*/
void stream(const QByteArray& );
/**
* Emits tweets (parsed) elements from stream
*/
@@ -68,14 +71,24 @@ signals:
* Emits deletion of status in the stream
*/
void deleteStatusStream(qint64 id, qint64 userid);
/**
* Emited when user stream is reconnected after failure
* Usefull when user stream connection fails to fetch missed tweets with REST API
*/
void reconnected();
/**
* Emited when user stream doesn't connect and backoff timer reaches maximum value (300 seconds)
* Usefull when users stream fails to revert to REST API
*/
void failureConnect();
public slots:
void startFetching();
private slots:
void replyError(QNetworkReply::NetworkError code);
void replyFinished();
void replyReadyRead();
void replyTimeout();
void parsingFinished(const QVariant& json, bool ok, const QString& errorMsg);
private:
@@ -84,10 +97,16 @@ private:
void parseDirectMessage(const QVariantMap& streamObject);
void parseDeleteStatus(const QVariantMap& streamObject);
QByteArray m_cachedResponse;
OAuthTwitter *m_oauthTwitter;
QNetworkReply *m_reply;
QTimer *m_backofftimer;
QByteArray m_cashedResponse;
QTimer *m_timeoutTimer;
bool m_streamTryingReconnect;
#ifdef STREAM_LOGGER
QFile m_streamLog;
#endif
};
#endif // QTWEETUSERSTREAM_H