diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 57ed038..5388faf 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -66,7 +66,6 @@ jobs: -Do2_WITH_SMUGMUG:BOOL=ON \ -Do2_WITH_SPOTIFY:BOOL=ON \ -Do2_WITH_SURVEYMONKEY:BOOL=ON \ - -Do2_WITH_TWITTER:BOOL=ON \ -Do2_WITH_UBER:BOOL=ON \ -Do2_WITH_VIMEO:BOOL=ON \ -S . \ diff --git a/.github/workflows/clang_static_analyzer/start.sh b/.github/workflows/clang_static_analyzer/start.sh index 4bbaf59..bc53c4a 100755 --- a/.github/workflows/clang_static_analyzer/start.sh +++ b/.github/workflows/clang_static_analyzer/start.sh @@ -37,7 +37,6 @@ scan-build -o scanbuildoutput -plist -v cmake -Do2_BUILD_EXAMPLES:BOOL=ON \ -Do2_WITH_SMUGMUG:BOOL=ON \ -Do2_WITH_SPOTIFY:BOOL=ON \ -Do2_WITH_SURVEYMONKEY:BOOL=ON \ - -Do2_WITH_TWITTER:BOOL=ON \ -Do2_WITH_UBER:BOOL=ON \ -Do2_WITH_VIMEO:BOOL=ON \ .. diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 455e1e4..1242c26 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -103,7 +103,6 @@ jobs: -Do2_WITH_SMUGMUG:BOOL=ON \ -Do2_WITH_SPOTIFY:BOOL=ON \ -Do2_WITH_SURVEYMONKEY:BOOL=ON \ - -Do2_WITH_TWITTER:BOOL=ON \ -Do2_WITH_UBER:BOOL=ON \ -Do2_WITH_VIMEO:BOOL=ON make -j$(nproc) diff --git a/.github/workflows/coverity-scan.yml b/.github/workflows/coverity-scan.yml index e2d5446..1ec35d4 100644 --- a/.github/workflows/coverity-scan.yml +++ b/.github/workflows/coverity-scan.yml @@ -41,7 +41,6 @@ jobs: -Do2_WITH_SMUGMUG:BOOL=ON \ -Do2_WITH_SPOTIFY:BOOL=ON \ -Do2_WITH_SURVEYMONKEY:BOOL=ON \ - -Do2_WITH_TWITTER:BOOL=ON \ -Do2_WITH_UBER:BOOL=ON \ -Do2_WITH_VIMEO:BOOL=ON \ - name: Download Coverity Build Tool diff --git a/.github/workflows/mac/install.sh b/.github/workflows/mac/install.sh index c630c05..5f12174 100644 --- a/.github/workflows/mac/install.sh +++ b/.github/workflows/mac/install.sh @@ -31,7 +31,6 @@ cmake -GNinja \ -Do2_WITH_SMUGMUG:BOOL=ON \ -Do2_WITH_SPOTIFY:BOOL=ON \ -Do2_WITH_SURVEYMONKEY:BOOL=ON \ - -Do2_WITH_TWITTER:BOOL=ON \ -Do2_WITH_UBER:BOOL=ON \ -Do2_WITH_VIMEO:BOOL=ON \ .. diff --git a/CMakeLists.txt b/CMakeLists.txt index 01fdd05..c88a865 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -28,7 +28,6 @@ if(NOT o2_SHOW_TRACE) endif() option(o2_WITH_TESTS "Enable tests" OFF) -option(o2_WITH_TWITTER "Authenticate with Twitter" OFF) option(o2_WITH_DROPBOX "Authenticate with Dropbox" OFF) option(o2_WITH_GOOGLE "Authenticate with Google" OFF) option(o2_WITH_VIMEO "Authenticate with Vimeo" OFF) @@ -45,9 +44,6 @@ option(o2_WITH_KEYCHAIN "keychain store" ON) option(o2_WITH_OAUTH1 "Include OAuth1 authentication" OFF) -if (o2_WITH_TWITTER) - set(HAVE_TWITTER_SUPPORT 1) -endif() if (o2_WITH_DROPBOX) set(HAVE_DROPBOX_SUPPORT 1) endif() @@ -96,7 +92,7 @@ if(o2_WITH_KEYCHAIN) endif() endif(o2_WITH_KEYCHAIN) -if(o2_WITH_TWITTER OR o2_WITH_DROPBOX OR o2_WITH_FLICKR OR o2_WITH_SMUGMUG) +if(o2_WITH_DROPBOX OR o2_WITH_FLICKR OR o2_WITH_SMUGMUG) set(o2_WITH_OAUTH1 ON) endif() diff --git a/README.md b/README.md index 15fec3a..86b08a1 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,6 @@ O1Flickr | o1flickr.h | Flickr OAuth specialization O1Freshbooks | o1freshbooks.h | Freshbooks OAuth specialization O1Requestor | o1requestor.h | Makes authenticated OAuth 1.0 requests: GET, POST or PUT, handles timeouts O1RequestParameter | o1.h | An extra request parameter participating in request signing -O1Twitter | o1twitter.h | Twitter OAuth specialization O1SmugMug | o1smugmug.h | SmugMug OAuth specialization O2 | o2.h | Generic OAuth 2.0 authenticator O2Facebook | o2facebook.h | Facebook OAuth specialization @@ -43,7 +42,6 @@ O2ReplyServer | o2replyserver.h | HTTP server to process authentication response O2Requestor | o2requestor.h | Makes authenticated OAuth 2.0 requests (GET, POST or PUT), handles timeouts and token expiry O2Skydrive | o2skydrive.h | OneDrive OAuth specialization O2SurveyMonkey | o2surveymonkey.h | SurveyMonkey OAuth specialization -OXTwitter | oxtwitter.h | Twitter XAuth specialization O2Uber | o2uber.h | Uber OAuth specialization ## Installation @@ -256,8 +254,6 @@ The *examples* folder contains complete example applications: Name | Description :-- | :-- facebookdemo | Command line application authenticating with Facebook -sialis | QT Quick Twitter client using OAuth 1 -twitterdemo | Command line client for authenticating with Twitter and posting status updates. Uses OAuth 1 or Twitter XAuth ## Change Log diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 6a33548..62bd686 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -8,10 +8,6 @@ if(o2_WITH_GOOGLE) add_subdirectory(youtubedemo) endif(o2_WITH_GOOGLE) -if(o2_WITH_TWITTER) - add_subdirectory(twitterdemo) -endif(o2_WITH_TWITTER) - #if(o2_WITH_SPOTIFY) # add_subdirectory(spotifydemo) #endif(o2_WITH_SPOTIFY) diff --git a/examples/sialis/.gitignore b/examples/sialis/.gitignore deleted file mode 100644 index fab7372..0000000 --- a/examples/sialis/.gitignore +++ /dev/null @@ -1,73 +0,0 @@ -# This file is used to ignore files which are generated -# ---------------------------------------------------------------------------- - -*~ -*.autosave -*.a -*.core -*.moc -*.o -*.obj -*.orig -*.rej -*.so -*.so.* -*_pch.h.cpp -*_resource.rc -*.qm -.#* -*.*# -core -!core/ -tags -.DS_Store -.directory -*.debug -Makefile* -*.prl -*.app -moc_*.cpp -ui_*.h -qrc_*.cpp -Thumbs.db -*.res -*.rc -/.qmake.cache -/.qmake.stash - -# qtcreator generated files -*.pro.user* - -# xemacs temporary files -*.flc - -# Vim temporary files -.*.swp - -# Visual Studio generated files -*.ib_pdb_index -*.idb -*.ilk -*.pdb -*.sln -*.suo -*.vcproj -*vcproj.*.*.user -*.ncb -*.sdf -*.opensdf -*.vcxproj -*vcxproj.* - -# MinGW generated files -*.Debug -*.Release - -# Python byte code -*.pyc - -# Binaries -# -------- -*.dll -*.exe - diff --git a/examples/sialis/README.md b/examples/sialis/README.md deleted file mode 100644 index cb8dad3..0000000 --- a/examples/sialis/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Sialis - -GUI demo for O2, demonstrating using O2 from QML, authenticating with Twitter and sending signed requests in order to show some tweets. - -To try out Sialis: - -1. Login to developer.twitter.com with your Twitter credentials -1. Create a new application "Sialis", record its API Key and API Secret - * Enable OAuth 1.0a authentication - * Set the callback URI to _http://127.0.0.1:8888/_ -1. In _main.qml_, change the O1Twitter object's _clientId_ property to the application's API Key -1. Change the _clientSecret_ property to the application's API secret -1. Build and run, press the _Login_ button to log in to Twitter and show the latest tweets diff --git a/examples/sialis/deployment.pri b/examples/sialis/deployment.pri deleted file mode 100644 index 265ce71..0000000 --- a/examples/sialis/deployment.pri +++ /dev/null @@ -1,13 +0,0 @@ -unix:!android { - isEmpty(target.path) { - qnx { - target.path = /tmp/$${TARGET}/bin - } else { - target.path = /opt/$${TARGET}/bin - } - export(target.path) - } - INSTALLS += target -} - -export(INSTALLS) diff --git a/examples/sialis/main.cpp b/examples/sialis/main.cpp deleted file mode 100644 index a9e1e98..0000000 --- a/examples/sialis/main.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -#include - -#include "o1.h" -#include "o1twitter.h" -#include "o1requestor.h" -#include "twitterapi.h" - -int main(int argc, char *argv[]) { - QGuiApplication app(argc, argv); - QCoreApplication::setOrganizationName("MySoft"); - QCoreApplication::setOrganizationDomain("mysoft.com"); - QCoreApplication::setApplicationName("sialis"); - QtWebView::initialize(); - qmlRegisterType("com.pipacs.o2", 1, 0, "O1Twitter"); - qmlRegisterType("com.pipacs.o2", 1, 0, "TwitterApi"); - QQmlApplicationEngine engine; - engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); - return app.exec(); -} diff --git a/examples/sialis/main.qml b/examples/sialis/main.qml deleted file mode 100644 index 972ff4b..0000000 --- a/examples/sialis/main.qml +++ /dev/null @@ -1,129 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtWebView -import com.pipacs.o2 - -ApplicationWindow { - id: app - visible: true - title: "Sialis" - minimumWidth: 300 - minimumHeight: 200 - height: 700 - - O1Twitter { - id: o1Twitter - clientId: "The app's API Key from developer.twitter.com" - clientSecret: "The app's API Secret from developer.twitter.com " - localPort: 8888 - - onOpenBrowser: { - browser.url = url - browser.visible = true - } - - onCloseBrowser: { - browser.visible = false - } - - onLinkedChanged: { - loginButton.enabled = true - twitterApi.requestTweets() - } - } - - TwitterApi { - id: twitterApi - authenticator: o1Twitter - } - - footer: ToolBar { - Label { - anchors.left: parent.left - anchors.verticalCenter: parent.verticalCenter - text: o1Twitter.linked? ("Logged in as " + o1Twitter.extraTokens["screen_name"]): "Not logged in" - } - - Button { - id: loginButton - anchors.right: parent.right - anchors.verticalCenter: parent.verticalCenter - text: o1Twitter.linked? "Logout": "Login" - onClicked: { - enabled = false - if (o1Twitter.linked) { - o1Twitter.unlink() - } else { - o1Twitter.link() - } - } - } - - height: loginButton.height + 5 - } - - ListView { - id: listView - anchors.fill: parent - model: twitterApi.tweetModel - delegate: listDelegate - highlight: Rectangle {color: "#10000000"} - focus: true - - Component { - id: listDelegate - Item { - width: parent.width - height: label.contentHeight + 10 - Row { - anchors.fill: parent - Label { - id: label - anchors.centerIn: parent - width: parent.width - text: rawText - wrapMode: Text.Wrap - } - Rectangle { - width: parent.width - height: 1 - color: "#10000000" - border.color: "transparent" - } - } - MouseArea { - anchors.fill: parent - onClicked: listView.currentIndex = index - } - } - } - } - - ApplicationWindow { - id: browser - visible: false - minimumHeight: 800 - minimumWidth: 500 - title: "Login" - - property url url: "" - - WebView { - anchors.fill: parent - url: browser.url - } - - onClosing: { - close.accepted = true - loginButton.enabled = true - } - } - - Timer { - interval: 30000 - repeat: true - running: true - triggeredOnStart: true - onTriggered: twitterApi.requestTweets() - } -} diff --git a/examples/sialis/qml.qrc b/examples/sialis/qml.qrc deleted file mode 100644 index 5f6483a..0000000 --- a/examples/sialis/qml.qrc +++ /dev/null @@ -1,5 +0,0 @@ - - - main.qml - - diff --git a/examples/sialis/sialis.icns b/examples/sialis/sialis.icns deleted file mode 100644 index 907e93f..0000000 Binary files a/examples/sialis/sialis.icns and /dev/null differ diff --git a/examples/sialis/sialis.pro b/examples/sialis/sialis.pro deleted file mode 100644 index a06ba88..0000000 --- a/examples/sialis/sialis.pro +++ /dev/null @@ -1,25 +0,0 @@ -TARGET = Sialis -TEMPLATE = app -QT += qml quick webview -CONFIG += c++11 -SOURCES += main.cpp \ - twitterapi.cpp \ - tweetmodel.cpp -RESOURCES += qml.qrc - -# "Bird" icon by snap2objects: http://www.snap2objects.com -ICON = sialis.icns - -# Additional import path used to resolve QML modules in Qt Creator's code model -QML_IMPORT_PATH = - -# Default rules for deployment. -include(deployment.pri) - -# Core O2 -DEFINES += O0_EXPORT= -include(../../src/src.pri) - -HEADERS += \ - twitterapi.h \ - tweetmodel.h diff --git a/examples/sialis/tweetmodel.cpp b/examples/sialis/tweetmodel.cpp deleted file mode 100644 index cfd577e..0000000 --- a/examples/sialis/tweetmodel.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include - -#include "tweetmodel.h" - -TweetModel::TweetModel(QObject *parent): QAbstractListModel(parent) { -} - -QHash TweetModel::roleNames() const { - QHash roles; - roles[RoleText] = "rawText"; - return roles; -} - -void TweetModel::addTweet(QVariantMap tweet) { - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - tweets.append(tweet); - endInsertRows(); -} - -void TweetModel::clearTweets() { - beginRemoveRows(QModelIndex(), 0, rowCount() - 1); - tweets.clear(); - endRemoveRows(); -} - -int TweetModel::rowCount(const QModelIndex &) const { - return tweets.count(); -} - -QVariant TweetModel::data(const QModelIndex &index, int role) const { - QVariant result; - QVariantMap tweet = tweets[index.row()]; - switch (role) { - case TweetModel::RoleText: - result = tweet["text"]; - default: - result = tweet["text"]; - } - return result; -} diff --git a/examples/sialis/tweetmodel.h b/examples/sialis/tweetmodel.h deleted file mode 100644 index 441bac7..0000000 --- a/examples/sialis/tweetmodel.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef TWEETMODEL_H -#define TWEETMODEL_H - -#include -#include -#include - -/// List of tweets, suitable as a ListView model -class TweetModel : public QAbstractListModel { - Q_OBJECT - -public: - enum Roles { - RoleText = Qt::UserRole + 1, - }; - - TweetModel(QObject *parent = 0); - - /// Clear all tweets - void clearTweets(); - - /// Add a tweet - void addTweet(QVariantMap tweet); - - /// Get number of tweets - int rowCount(const QModelIndex &parent = QModelIndex()) const; - - /// Access a tweet - QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; - - /// Get role names - QHashroleNames() const; - -protected: - QList tweets; -}; - -#endif // TWEETMODEL_H diff --git a/examples/sialis/twitterapi.cpp b/examples/sialis/twitterapi.cpp deleted file mode 100644 index 864b49f..0000000 --- a/examples/sialis/twitterapi.cpp +++ /dev/null @@ -1,58 +0,0 @@ -#include -#include -#include - -#include "o1requestor.h" - -#include "twitterapi.h" - -TwitterApi::TwitterApi(QObject *parent): QObject(parent), authenticator_(0) { - manager_ = new QNetworkAccessManager(this); - tweetModel_ = new TweetModel(this); -} - -TwitterApi::~TwitterApi() { -} - -TweetModel *TwitterApi::tweetModel() { - return tweetModel_; -} - -O1Twitter *TwitterApi::authenticator() const { - return authenticator_; -} -void TwitterApi::setAuthenticator(O1Twitter *v) { - authenticator_ = v; - Q_EMIT authenticatorChanged(); -} - -void TwitterApi::requestTweets() { - if (!authenticator_ || !authenticator_->linked()) { - tweetModel_->clearTweets(); - emit tweetModelChanged(); - return; - } - O1Requestor *requestor = new O1Requestor(manager_, authenticator_, this); - QUrl url = QUrl("https://api.twitter.com/1.1/statuses/home_timeline.json"); - QNetworkRequest request(url); - QNetworkReply *reply = requestor->get(request, QList()); - connect(reply, &QNetworkReply::finished, this, &TwitterApi::tweetsReceived); - connect(reply, &QNetworkReply::errorOccurred, this, &TwitterApi::requestFailed); -} - -void TwitterApi::tweetsReceived() { - QNetworkReply *reply = qobject_cast(sender()); - QJsonDocument jsonResponse = QJsonDocument::fromJson(reply->readAll()); - tweetModel_->clearTweets(); - QJsonArray jsonArray = jsonResponse.array(); - foreach (const QJsonValue &v, jsonArray) { - QVariantMap item = v.toObject().toVariantMap(); - tweetModel_->addTweet(item); - } - emit tweetModelChanged(); -} - -void TwitterApi::requestFailed(QNetworkReply::NetworkError error) { - QNetworkReply *reply = qobject_cast(sender()); - qWarning() << "TwitterApi::requestFailed:" << (int)error << reply->errorString() << reply->readAll(); -} diff --git a/examples/sialis/twitterapi.h b/examples/sialis/twitterapi.h deleted file mode 100644 index 95e39c7..0000000 --- a/examples/sialis/twitterapi.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef TWITTERAPI_H -#define TWITTERAPI_H - -#include -#include -#include - -#include "o1twitter.h" - -#include "tweetmodel.h" - -/// Mini Twitter API -class TwitterApi: public QObject { - Q_OBJECT - -public: - /// List of tweets - Q_PROPERTY(TweetModel *tweetModel READ tweetModel NOTIFY tweetModelChanged) - TweetModel *tweetModel() ; - - /// OAuth authenticator - Q_PROPERTY(O1Twitter *authenticator READ authenticator WRITE setAuthenticator NOTIFY authenticatorChanged) - O1Twitter *authenticator() const; - void setAuthenticator(O1Twitter *v) ; - - explicit TwitterApi(QObject *parent = 0); - virtual ~TwitterApi(); - -public slots: - Q_INVOKABLE virtual void requestTweets(); - -signals: - void tweetModelChanged(); - void authenticatorChanged(); - -protected: - O1Twitter *authenticator_; - TweetModel *tweetModel_; - QNetworkAccessManager *manager_; - -protected slots: - void tweetsReceived(); - void requestFailed(QNetworkReply::NetworkError error); -}; - -#endif // TWITTERAPI_H diff --git a/examples/twitterdemo/CMakeLists.txt b/examples/twitterdemo/CMakeLists.txt deleted file mode 100644 index 7eb2d95..0000000 --- a/examples/twitterdemo/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0) - -project( twitterexample ) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_INCLUDE_CURRENT_DIR ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") - -if(o2_WITH_QT6) - find_package(Qt6 COMPONENTS Core Widgets Network REQUIRED) -else() - find_package(Qt5 COMPONENTS Core Widgets Script Network REQUIRED) -endif() - -include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} "../../src" ) - -set(fb_SRCS - main.cpp - tweeter.cpp -) - -add_executable( twitterexample ${fb_SRCS} ) - -target_link_libraries( twitterexample Qt::Core Qt::Widgets Qt::Network ) -target_link_libraries( twitterexample o2 ) diff --git a/examples/twitterdemo/main.cpp b/examples/twitterdemo/main.cpp deleted file mode 100644 index fbd1b2b..0000000 --- a/examples/twitterdemo/main.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include -#include -#include - -#include "tweeter.h" - -const char OPT_OAUTH[] = "-o"; -const char OPT_XAUTH[] = "-x"; -const char OPT_USERNAME[] = "-u"; -const char OPT_PASSWORD[] = "-p"; -const char OPT_STATUS[] = "-m"; - -const char USAGE[] = "\n" - "Usage: tweetdemo [OPTION]...\n" - "Get OAuth access tokens from Twitter's OAuth service and " - "(optionally) post a status update on a user's timeline\n" - "\nOptions:\n" - " %1\t\tLink with Twitter OAuth service, i.e get access tokens\n" - " %2\t\tLink with Twitter XAuth service, i.e get access tokens using the XAuth protocol\n" - " %3 \tTwitter username to be used while using XAuth (-x option)\n" - " %4 \tTwitter password to be used while using XAuth (-x option)\n" - " %5\t\tStatus update message, enclosed in double quotes\n"; - - -class Helper : public QObject { - Q_OBJECT - -public: - Helper() : QObject(), tweeter_(this) {} - -public slots: - void processArgs() { - QStringList argList = qApp->arguments(); - QByteArray help = QString(USAGE).arg(OPT_OAUTH, - OPT_XAUTH, - OPT_USERNAME, - OPT_PASSWORD, - OPT_STATUS).toLatin1(); - const char *helpText = help.constData(); - connect(&tweeter_, &Tweeter::linkingFailed, this, &Helper::onLinkingFailed); - connect(&tweeter_, &Tweeter::linkingSucceeded, this, &Helper::onLinkingSucceeded); - - if (argList.contains(OPT_OAUTH)) { - if (argList.contains(OPT_STATUS)) { - waitForMsg_ = true; - msg_ = argList.at(argList.indexOf(OPT_STATUS) + 1); - } - // Start OAuth - tweeter_.doOAuth(); - } else if (argList.contains(OPT_XAUTH)) { - if (!(argList.contains(OPT_USERNAME) && argList.contains(OPT_PASSWORD))) { - qDebug() << "\nError: Username or Password missing!"; - qDebug() << helpText; - qApp->exit(1); - } - - QString username = argList.at(argList.indexOf(OPT_USERNAME) + 1); - QString password = argList.at(argList.indexOf(OPT_PASSWORD) + 1); - - if (argList.contains(OPT_STATUS)) { - waitForMsg_ = true; - msg_ = argList.at(argList.indexOf(OPT_STATUS) + 1); - } - // Start XAuth - tweeter_.doXAuth(username, password); - } else if (argList.contains(OPT_STATUS)) { - QString statusMessage = argList.at(argList.indexOf(OPT_STATUS) + 1); - postStatusUpdate(statusMessage); - } else { - qDebug() << helpText; - qApp->exit(1); - } - } - - void onLinkingFailed() { - qDebug() << "Linking failed!"; - qApp->exit(1); - } - - void onLinkingSucceeded() { - qDebug() << "Linking succeeded!"; - if (waitForMsg_) { - postStatusUpdate(msg_); - } else { - qApp->quit(); - } - } - -private slots: - void postStatusUpdate(const QString& msg) { - connect(&tweeter_, &Tweeter::statusPosted, qApp, &QApplication::quit); - tweeter_.postStatusUpdate(msg); - } - -private: - Tweeter tweeter_; - bool waitForMsg_{false}; - QString msg_; -}; - -int main(int argc, char *argv[]) { - QApplication a(argc, argv); - QCoreApplication::setOrganizationName("MySoft"); - QCoreApplication::setOrganizationDomain("mysoft.com"); - QCoreApplication::setApplicationName("tweeter"); - Helper helper; -// Suppress warning: Potential leak of memory in qtimer.h [clang-analyzer-cplusplus.NewDeleteLeaks] -#ifndef __clang_analyzer__ - QTimer::singleShot(0, &helper, &Helper::processArgs); -#endif - return a.exec(); -} - -#include "main.moc" diff --git a/examples/twitterdemo/tweeter.cpp b/examples/twitterdemo/tweeter.cpp deleted file mode 100644 index ed2d338..0000000 --- a/examples/twitterdemo/tweeter.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include -#include -#include -#include - -#include "tweeter.h" -#include "o0globals.h" -#include "o1requestor.h" -#include "o0settingsstore.h" - -const char O2_CONSUMER_KEY[] = "2vHeyIxjywIadjEhvbDpg"; -const char O2_CONSUMER_SECRET[] = "Xfwe195Kp3ZpcCKgkYs7RKfugTm8EfpLkQvsKfX2vvs"; - -const int localPort = 8888; - -Tweeter::Tweeter(QObject *parent) : - QObject(parent) { -} - -void Tweeter::doOAuth() { - o1Twitter_ = new O1Twitter(this); - o1Twitter_->setClientId(O2_CONSUMER_KEY); - o1Twitter_->setClientSecret(O2_CONSUMER_SECRET); - o1Twitter_->setLocalPort(localPort); - - // Create a store object for writing the received tokens - O0SettingsStore *store = new O0SettingsStore(O2_ENCRYPTION_KEY); - store->setGroupKey("twitter"); - o1Twitter_->setStore(store); - - // Connect signals - connect(o1Twitter_, &O0BaseAuth::linkedChanged, this, &Tweeter::onLinkedChanged); - connect(o1Twitter_, &O0BaseAuth::linkingFailed, this, &Tweeter::linkingFailed); - connect(o1Twitter_, &O0BaseAuth::linkingSucceeded, this, &Tweeter::onLinkingSucceeded); - connect(o1Twitter_, &O0BaseAuth::openBrowser, this, &Tweeter::onOpenBrowser); - connect(o1Twitter_, &O0BaseAuth::closeBrowser, this, &Tweeter::onCloseBrowser); - - qDebug() << "Starting OAuth..."; - o1Twitter_->unlink(); // For the sake of this demo - o1Twitter_->link(); -} - -void Tweeter::doXAuth(const QString &username, const QString &password) { - oxTwitter_ = new OXTwitter(this); - oxTwitter_->setClientId(O2_CONSUMER_KEY); - oxTwitter_->setClientSecret(O2_CONSUMER_SECRET); - oxTwitter_->setLocalPort(localPort); - - oxTwitter_->setUsername(username); - oxTwitter_->setPassword(password); - - // Create a store object for writing the received tokens - O0SettingsStore *store = new O0SettingsStore(O2_ENCRYPTION_KEY); - store->setGroupKey("twitter"); - oxTwitter_->setStore(store); - - connect(oxTwitter_, &O0BaseAuth::linkedChanged, this, &Tweeter::onLinkedChanged); - connect(oxTwitter_, &O0BaseAuth::linkingFailed, this, &Tweeter::linkingFailed); - connect(oxTwitter_, &O0BaseAuth::linkingSucceeded, this, &Tweeter::onLinkingSucceeded); - connect(oxTwitter_, &O0BaseAuth::openBrowser, this, &Tweeter::onOpenBrowser); - connect(oxTwitter_, &O0BaseAuth::closeBrowser, this, &Tweeter::onCloseBrowser); - - qDebug() << "Starting XAuth..."; - qDebug() << "Username:" << username << "Password:" << password; - oxTwitter_->unlink(); // For the sake of this demo - oxTwitter_->link(); -} - -void Tweeter::postStatusUpdate(const QString &message) { - if (!o1Twitter_->linked()) { - qWarning() << "Application is not linked to Twitter!"; - emit statusPosted(); - return; - } - - qDebug() << "Status update message:" << message.toLatin1().constData(); - - QNetworkAccessManager* manager = new QNetworkAccessManager(this); - O1Twitter* o1 = o1Twitter_; - O1Requestor* requestor = new O1Requestor(manager, o1, this); - - QByteArray paramName("status"); - - QList reqParams = QList(); - reqParams << O0RequestParameter(paramName, message.toLatin1()); - - QByteArray postData = O1::createQueryParameters(reqParams); - - QUrl url = QUrl("https://api.twitter.com/1.1/statuses/update.json"); - - QNetworkRequest request(url); - request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM); - - QNetworkReply *reply = requestor->post(request, reqParams, postData); - connect(reply, &QNetworkReply::finished, this, &Tweeter::tweetReplyDone); -} - -void Tweeter::onOpenBrowser(const QUrl &url) { - qDebug() << "Opening browser with URL" << url.toString(); - QDesktopServices::openUrl(url); -} - -void Tweeter::onCloseBrowser() { -} - -void Tweeter::onLinkedChanged() { - qDebug() << "Linked changed!"; -} - -void Tweeter::onLinkingSucceeded() { - O1Twitter *o1t = qobject_cast(sender()); - if (!o1t->linked()) { - return; - } - QVariantMap extraTokens = o1t->extraTokens(); - if (!extraTokens.isEmpty()) { - emit extraTokensReady(extraTokens); - qDebug() << "Extra tokens in response:"; - for (auto it = extraTokens.constBegin(); it != extraTokens.constEnd(); ++it) { - qDebug() << "\t" << it.key() << ":" << (it.value().toString().left(3) + "..."); - } - } - emit linkingSucceeded(); -} - -void Tweeter::tweetReplyDone() { - QNetworkReply *reply = qobject_cast(sender()); - if (reply->error() != QNetworkReply::NoError) { - qDebug() << "ERROR:" << reply->errorString(); - qDebug() << "Content:" << reply->readAll(); - } else { - qDebug() << "Tweet posted sucessfully!"; - } - emit statusPosted(); -} diff --git a/examples/twitterdemo/tweeter.h b/examples/twitterdemo/tweeter.h deleted file mode 100644 index a867eda..0000000 --- a/examples/twitterdemo/tweeter.h +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef TWEETER_H -#define TWEETER_H - -#include -#include -#include -#include - -#include "o1twitter.h" -#include "oxtwitter.h" - -class Tweeter : public QObject -{ - Q_OBJECT -public: - explicit Tweeter(QObject *parent = nullptr); - -signals: - void extraTokensReady(const QVariantMap &extraTokens); - void linkingFailed(); - void linkingSucceeded(); - void statusPosted(); - -public slots: - void doOAuth(); - void doXAuth(const QString &username, const QString &password); - void postStatusUpdate(const QString &message); - -private slots: - void onLinkedChanged(); - void onLinkingSucceeded(); - void onOpenBrowser(const QUrl &url); - void onCloseBrowser(); - void tweetReplyDone(); - -private: - O1Twitter* o1Twitter_{nullptr}; - OXTwitter* oxTwitter_{nullptr}; -}; - -#endif // TWEETER_H diff --git a/examples/twitterdemo/twitterdemo.pro b/examples/twitterdemo/twitterdemo.pro deleted file mode 100644 index b1bf512..0000000 --- a/examples/twitterdemo/twitterdemo.pro +++ /dev/null @@ -1,15 +0,0 @@ -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets - -DEFINES += O0_EXPORT= -include(../../src/src.pri) - -TARGET = twitterdemo -TEMPLATE = app - -SOURCES += main.cpp \ - tweeter.cpp - -HEADERS += \ - tweeter.h diff --git a/o2-config.h.cmake b/o2-config.h.cmake index d073348..c1d10a3 100644 --- a/o2-config.h.cmake +++ b/o2-config.h.cmake @@ -2,7 +2,6 @@ #define O2_CONFIG_SUPPORT_FEATURE_H -#cmakedefine01 HAVE_TWITTER_SUPPORT #cmakedefine01 HAVE_DROPBOX_SUPPORT #cmakedefine01 HAVE_GOOGLE_SUPPORT #cmakedefine01 HAVE_UBER_SUPPORT diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7f144bc..44e9aa8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -54,18 +54,6 @@ if(o2_WITH_OAUTH1) ) endif(o2_WITH_OAUTH1) -if(o2_WITH_TWITTER) - set( o2_SRCS - ${o2_SRCS} - oxtwitter.cpp - ) - set( o2_HDRS - ${o2_HDRS} - o1twitter.h - oxtwitter.h - ) -endif(o2_WITH_TWITTER) - if(o2_WITH_DROPBOX) set( o2_HDRS ${o2_HDRS} diff --git a/src/o1twitter.h b/src/o1twitter.h deleted file mode 100644 index c229ac7..0000000 --- a/src/o1twitter.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef O1TWITTER_H -#define O1TWITTER_H - -#include "o0export.h" -#include "o1.h" - -/// Twitter OAuth 1.0 client -class O0_EXPORT O1Twitter: public O1 { - Q_OBJECT - -public: - explicit O1Twitter(QObject *parent = nullptr): O1(parent) { - setRequestTokenUrl(QUrl("https://api.twitter.com/oauth/request_token")); - setAuthorizeUrl(QUrl("https://api.twitter.com/oauth/authenticate")); - setAccessTokenUrl(QUrl("https://api.twitter.com/oauth/access_token")); - } -}; - -#endif // O1TWITTER_H diff --git a/src/oxtwitter.cpp b/src/oxtwitter.cpp deleted file mode 100644 index f67533b..0000000 --- a/src/oxtwitter.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include - -#include "oxtwitter.h" -#include "o0globals.h" - -const char XAUTH_USERNAME[] = "x_auth_username"; -const char XAUTH_PASSWORD[] = "x_auth_password"; -const char XAUTH_MODE[] = "x_auth_mode"; -const char XAUTH_MODE_VALUE[] = "client_auth"; - -OXTwitter::OXTwitter(QObject *parent): O1Twitter(parent) { -} - -QString OXTwitter::username() { - return username_; -} - -void OXTwitter::setUsername(const QString &username) { - username_ = username; - Q_EMIT usernameChanged(); -} - -QString OXTwitter::password() { - return password_; -} - -void OXTwitter::setPassword(const QString &password) { - password_ = password; - Q_EMIT passwordChanged(); -} - -void OXTwitter::link() { - qDebug() << "OXTwitter::link"; - if (linked()) { - qDebug() << "Linked already"; - return; - } - - if (username_.isEmpty() || password_.isEmpty()) { - qWarning() << "Error: XAuth parameters not set. Aborting!"; - return; - } - - // prepare XAuth parameters - xAuthParams_.append(O0RequestParameter(QByteArray(XAUTH_USERNAME), username_.toLatin1())); - xAuthParams_.append(O0RequestParameter(QByteArray(XAUTH_PASSWORD), password_.toLatin1())); - xAuthParams_.append(O0RequestParameter(QByteArray(XAUTH_MODE), QByteArray(XAUTH_MODE_VALUE))); - - QList oauthParams; - oauthParams.append(O0RequestParameter(O2_OAUTH_SIGNATURE_METHOD, O2_SIGNATURE_TYPE_HMAC_SHA1)); - oauthParams.append(O0RequestParameter(O2_OAUTH_CONSUMER_KEY, clientId().toLatin1())); - oauthParams.append(O0RequestParameter(O2_OAUTH_VERSION, "1.0")); -#if QT_VERSION >= QT_VERSION_CHECK(5,8,0) - oauthParams.append(O0RequestParameter(O2_OAUTH_TIMESTAMP, QString::number(QDateTime::currentSecsSinceEpoch()).toLatin1())); -#else - oauthParams.append(O0RequestParameter(O2_OAUTH_TIMESTAMP, QString::number(QDateTime::currentDateTimeUtc().toTime_t()).toLatin1())); -#endif - oauthParams.append(O0RequestParameter(O2_OAUTH_NONCE, nonce())); - oauthParams.append(O0RequestParameter(O2_OAUTH_TOKEN, QByteArray(""))); - oauthParams.append(O0RequestParameter(O2_OAUTH_VERFIER, QByteArray(""))); - - QByteArray signature = sign(oauthParams, xAuthParams_, accessTokenUrl(), QNetworkAccessManager::PostOperation, clientSecret(), ""); - oauthParams.append(O0RequestParameter(O2_OAUTH_SIGNATURE, signature)); - - // Post request - QNetworkRequest request(accessTokenUrl()); - decorateRequest(request, oauthParams); - request.setHeader(QNetworkRequest::ContentTypeHeader, O2_MIME_TYPE_XFORM); - QNetworkReply *reply = manager_->post(request, createQueryParameters(xAuthParams_)); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) - connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onTokenExchangeError(QNetworkReply::NetworkError))); -#else - connect(reply, &QNetworkReply::errorOccurred, this, &OXTwitter::onTokenExchangeError); -#endif - connect(reply, &QNetworkReply::finished, this, &OXTwitter::onTokenExchangeFinished); -} diff --git a/src/oxtwitter.h b/src/oxtwitter.h deleted file mode 100644 index a1353af..0000000 --- a/src/oxtwitter.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef OXTWITTER_H -#define OXTWITTER_H - -#include "o0export.h" -#include "o1twitter.h" - -/// Twitter authenticator using Twitter XAuth -class O0_EXPORT OXTwitter: public O1Twitter { - Q_OBJECT - -public: - explicit OXTwitter(QObject *parent = nullptr); - - /// XAuth Username - Q_PROPERTY(QString username READ username WRITE setUsername NOTIFY usernameChanged) - QString username(); - void setUsername(const QString &username); - - /// XAuth Password - Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged) - QString password(); - void setPassword(const QString &password); - -public Q_SLOTS: - /// Authenticate. - Q_INVOKABLE void link() override; - -Q_SIGNALS: - void usernameChanged(); - void passwordChanged(); - -private: - QList xAuthParams_; - QString username_; - QString password_; -}; - -#endif // OXTWITTER_H diff --git a/src/src.pri b/src/src.pri index 10be410..a4507af 100644 --- a/src/src.pri +++ b/src/src.pri @@ -18,7 +18,6 @@ SOURCES += \ $$PWD/o2replyserver.cpp \ $$PWD/o2requestor.cpp \ $$PWD/o2skydrive.cpp \ - $$PWD/oxtwitter.cpp \ $$PWD/o2simplecrypt.cpp \ $$PWD/o0baseauth.cpp \ $$PWD/o0settingsstore.cpp \ @@ -36,7 +35,6 @@ HEADERS += \ $$PWD/o1flickr.h \ $$PWD/o1requestor.h \ $$PWD/o1smugmug.h \ - $$PWD/o1twitter.h \ $$PWD/o1timedreply.h \ $$PWD/o1upwork.h \ $$PWD/o2.h \ @@ -48,7 +46,6 @@ HEADERS += \ $$PWD/o2replyserver.h \ $$PWD/o2requestor.h \ $$PWD/o2skydrive.h \ - $$PWD/oxtwitter.h \ $$PWD/o1freshbooks.h \ $$PWD/o0baseauth.h \ $$PWD/o0globals.h \ @@ -69,7 +66,6 @@ headers.files += \ $$PWD/o1flickr.h \ $$PWD/o1requestor.h \ $$PWD/o1smugmug.h \ - $$PWD/o1twitter.h \ $$PWD/o1timedreply.h \ $$PWD/o1upwork.h \ $$PWD/o2.h \ @@ -80,7 +76,6 @@ headers.files += \ $$PWD/o2replyserver.h \ $$PWD/o2requestor.h \ $$PWD/o2skydrive.h \ - $$PWD/oxtwitter.h \ $$PWD/o1freshbooks.h \ $$PWD/o0baseauth.h \ $$PWD/o0globals.h \