Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Please tell me how to use Mastodon streaming api with qt

Please tell me how to use Mastodon streaming api with qt

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 4 Posters 1.7k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    wabisuke2718
    wrote on last edited by wabisuke2718
    #1

    Please tell me how to use Mastodon streaming api with qt.
    I wrote this code but doesn't work and is likely to be wrong.
    Please please tell me

    WebSocket.cpp

    #include "WebSocket.h"
    #include <QDebug>
    #include <QAbstractSocket>
    
    
    WebSocket::WebSocket(const QUrl &url, QString accessToken, bool debug, QObject *parent) :
        QObject(parent),
        m_url(url),
        mAccessToken(accessToken),
        m_debug(debug)
    {
        if (m_debug) {
            qDebug() << "WebSocket server:" << url;
        }
    
        connect(&m_webSocket, &QWebSocket::connected, this, &WebSocket::onConnected);
        connect(&m_webSocket, &QWebSocket::disconnected, this, &WebSocket::closed);
    
        connect(&m_webSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(onWebSocketError(QAbstractSocket::SocketError)));
    
        //m_webSocket.open(QUrl(url));
    
        //QNetworkRequest req(url);
        QString header_text = "Bearer " + mAccessToken;
        //req.setRawHeader("Authorization", header_text.toUtf8());
    
        QString urlStr = url.toString() + "?access_token=" + header_text + "&stream=public";
        QNetworkRequest req(urlStr);
    
        m_webSocket.open(req);
    }
    
    void WebSocket::onWebSocketError(QAbstractSocket::SocketError error)
    {
        qDebug() << error;
    }
    
    void WebSocket::onConnected()
    {
        if (m_debug) {
            qDebug() << "WebSocket connected";
        }
        connect(&m_webSocket, &QWebSocket::textMessageReceived, this, &WebSocket::onTextMessageReceived);
        //m_webSocket.sendTextMessage(QStringLiteral("Hello, world!"));
    }
    
    void WebSocket::onTextMessageReceived(QString message)
    {
        if (m_debug) {
            qDebug() << "Message received:" << message;
        }
        m_webSocket.close();
    }
    
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    
    #include <QLabel>
    #include <QFrame>
    
    #include <QNetworkAccessManager>
    #include <QNetworkReply>
    
    #include <QJsonObject>
    #include <QJsonDocument>
    #include <QJsonParseError>
    #include <QJsonArray>
    
    #include <vector>
    
    #include "IconWidget.h"
    #include <QHBoxLayout>
    
    #include "defineconstants.h"
    
    #include <QUrlQuery>
    #include <QSystemTrayIcon>
    
    #include <QTextCodec>
    
    #include "WebSocket.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
    
        manager = new QNetworkAccessManager(this);
        connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
    
        ui->menuStartLocalTimeline->setEnabled(false);
        ui->menuStopLocalTimeline->setEnabled(true);
        //★一時的に無効化
        //mLocalTimelineTimer = startTimer(LOCAL_TIMELINE_UPDATE_INTERVAL);
    
        connect(ui->menuStartLocalTimeline, SIGNAL(triggered(bool)), this, SLOT(startLocalTimelineTimer()));
        connect(ui->menuStopLocalTimeline, SIGNAL(triggered(bool)), this, SLOT(stopLocalTimelineTimer()));
    
        //★一時的に無効化
        //manager->get(QNetworkRequest(QUrl("https://mstdn.jp/api/v1/timelines/public?local=\"true\"")));
    
        trayIcon = new QSystemTrayIcon(this);
    
        QFile file("your_usercred.txt");
        if (!file.open(QIODevice::ReadOnly)) {
            if (DEBUG_MODE) {
                qDebug() << "file could not open.";
            }
        }
        QTextStream in(&file);
        mAccessToken = in.readLine();
    
        //★ストリーミングAPIテスト
        /*
        //QEventLoop eventLoop;
        connect(manager, SIGNAL(finished(QNetworkReply*)), &eventLoop, SLOT(quit()));
        QNetworkRequest req(QUrl("https://streaming.mstdn.jp/api/v1/streaming/public"));
        QString header_text = "Bearer " + mAccessToken;
        req.setRawHeader("Authorization", header_text.toUtf8());
        req.setRawHeader("Connection", "Keep-Alive");
        manager->get(req);
        //eventLoop.exec();
        */
    
        //mWebSocketForTimeline = new WebSocket(QUrl(QStringLiteral("ws://streaming.mstdn.jp/api/v1/streaming/public")), mAccessToken, true);
        mWebSocketForTimeline = new WebSocket(QUrl(QStringLiteral("ws://streaming.mstdn.jp/api/v1/streaming")), mAccessToken, true);
    }
    
    void MainWindow::timerEvent(QTimerEvent *e)
    {
        if (e->timerId() == mLocalTimelineTimer) {
            manager->get(QNetworkRequest(QUrl("https://mstdn.jp/api/v1/timelines/public?local=\"true\"")));
        }
    }
    
    void MainWindow::startLocalTimelineTimer()
    {
        mLocalTimelineTimer = startTimer(LOCAL_TIMELINE_UPDATE_INTERVAL);
        ui->menuStartLocalTimeline->setEnabled(false);
        ui->menuStopLocalTimeline->setEnabled(true);
    }
    
    void MainWindow::stopLocalTimelineTimer()
    {
        killTimer(mLocalTimelineTimer);
        ui->menuStartLocalTimeline->setEnabled(true);
        ui->menuStopLocalTimeline->setEnabled(false);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    
    void MainWindow::on_pushButton_2_clicked()
    {
        manager->get(QNetworkRequest(QUrl("https://mstdn.jp/api/v1/timelines/public?local=\"true\"")));
    }
    
    void MainWindow::replyFinished(QNetworkReply *reply)
    {
        if (DEBUG_MODE) {
            qDebug() << "MainWindow::replyFinished() called.";
            qDebug() << "url" << reply->url();
            qDebug() << reply->errorString();
        }
    
        if (reply->url().toString() == "https://mstdn.jp/api/v1/statuses") {
            return;
        }
    
        if (reply->error() == QNetworkReply::NoError) {
            QByteArray byteArray = reply->readAll();
            //ui->textEdit->setPlainText(byteArray);
    
            QJsonParseError error;
            QJsonDocument jsonDocument = QJsonDocument::fromJson(byteArray, &error);
            qDebug() << error.errorString();
    
            /*
            qDebug() << "Is Object? " << jsonDocument.isObject();
            qDebug() << "Is Array? " << jsonDocument.isArray();
            */
    
            QJsonArray jsonArray = jsonDocument.array();
            //qDebug() << jsonArray.size();
            QStringList keys = jsonArray[0].toObject().keys();
            qDebug() << keys;
            foreach (QString key, keys) {
                qDebug() << "key =" << key;
                QString value = jsonArray[0].toObject().value(key).toString();
                qDebug() << "value =" << value;
            }
    
            //std::vector<QHBoxLayout*> tootLayouts;
            static QVBoxLayout *timelineLayout = new QVBoxLayout();
            //for (int i=0; i<jsonArray.size(); i++) {
            for (int i=jsonArray.size()-1; i>=0; i--) {
                if (i == 0) {
                    QString *title = new QString("タイトルは長いんだよー");
                    trayIcon->show();
                    trayIcon->showMessage(*title, jsonArray[i].toObject().value("content").toString());
                }
    
                QFrame *tootFrame = new QFrame();
                tootFrame->setObjectName("tootFrame");
                tootFrame->setStyleSheet("#tootFrame { border: 1px solid; background-color: white; }");
                //tootFrame->maximumWidth = ui->scrollAreaWidgetContents->width();
                //tootFrame->setMaximumWidth(ui->scrollAreaWidgetContents->width());
                QHBoxLayout *tootLayout = new QHBoxLayout();
    
                QVBoxLayout *tootContentsLayout = new QVBoxLayout();
                QLabel *name = new QLabel(jsonArray[i].toObject().value("account").toObject().value("display_name").toString(), this);
    
                QString tootHtml = jsonArray[i].toObject().value("content").toString();
                QRegExp br("<br />");
                tootHtml.replace(br, "\n");
                //QRegExp tag("<[^>]*>");
                //tootHtml.remove(tag);
                QLabel *toot = new QLabel(tootHtml);
                toot->setWordWrap(true);
                toot->setTextFormat(Qt::PlainText);
    
                QUrl *iconUrl = new QUrl(jsonArray[i].toObject().value("account").toObject().value("avatar").toString());
                //QUrl *iconUrl = new QUrl("https://media.mstdn.jp/images/accounts/avatars/000/006/953/original/b0a6986188b3fdf7.png");
                IconWidget *iconWidget = new IconWidget(iconUrl, nullptr);
                tootLayout->addWidget(iconWidget);
    
                tootContentsLayout->addWidget(name);
                tootContentsLayout->addWidget(toot);
                tootLayout->addLayout(tootContentsLayout);
                tootFrame->setLayout(tootLayout);
    
                //timelineLayout->addLayout(tootLayout);
                //timelineLayout->addWidget(tootFrame);
                timelineLayout->insertWidget(0, tootFrame);
            }
            //ui->tootList->setLayout(timelineLayout);
            //ui->scrollAreaWidgetContents->setLayout(timelineLayout);
            ui->localTimelineContents->setLayout(timelineLayout);
        }
    }
    
    void MainWindow::on_tootButton_clicked()
    {
        QUrlQuery params;
        QNetworkRequest req(QUrl("https://mstdn.jp/api/v1/statuses"));
    
        QString header_text = "Bearer " + mAccessToken;
        qDebug() << "AAA" << header_text;
        req.setRawHeader("Authorization", header_text.toUtf8());
        params.addQueryItem("visibility", "");
        params.addQueryItem("status", ui->tootText->toPlainText());
    
        manager->post(req, params.toString(QUrl::FullyEncoded).toUtf8());
    }
    
    
    1 Reply Last reply
    0
    • dheerendraD Offline
      dheerendraD Offline
      dheerendra
      Qt Champions 2022
      wrote on last edited by
      #2

      From code it looks alright. There are three slots u have written. Can u tell me which slot is getting executed ?

      Dheerendra
      @Community Service
      Certified Qt Specialist
      http://www.pthinks.com

      1 Reply Last reply
      0
      • W Offline
        W Offline
        wabisuke2718
        wrote on last edited by
        #3

        I added mainwindow.cpp source code to first comment.
        And when I execute the program, the following error occurs.
        So onWebSocketError slot is executed.
        And onConnected slot is not executed.

        qt.network.ssl: QSslSocket: cannot resolve TLSv1_1_client_method
        qt.network.ssl: QSslSocket: cannot resolve TLSv1_2_client_method
        qt.network.ssl: QSslSocket: cannot resolve TLSv1_1_server_method
        qt.network.ssl: QSslSocket: cannot resolve TLSv1_2_server_method
        qt.network.ssl: QSslSocket: cannot resolve SSL_select_next_proto
        qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
        qt.network.ssl: QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
        qt.network.ssl: QSslSocket: cannot resolve SSL_set_alpn_protos
        qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_alpn_select_cb
        qt.network.ssl: QSslSocket: cannot resolve SSL_get0_alpn_selected
        WebSocket server: QUrl("ws://streaming.mstdn.jp/api/v1/streaming")
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError
        QAbstractSocket::ConnectionRefusedError

        1 Reply Last reply
        0
        • dheerendraD Offline
          dheerendraD Offline
          dheerendra
          Qt Champions 2022
          wrote on last edited by
          #4

          Is it windows box ? Looks ssl libraries are not found in path. Can u check it ?

          Dheerendra
          @Community Service
          Certified Qt Specialist
          http://www.pthinks.com

          1 Reply Last reply
          1
          • W Offline
            W Offline
            wabisuke2718
            wrote on last edited by wabisuke2718
            #5

            I tried QSslSocket::supportsSsl() and result was true.
            (windows)

            jsulmJ 1 Reply Last reply
            0
            • W wabisuke2718

              I tried QSslSocket::supportsSsl() and result was true.
              (windows)

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @wabisuke2718 These error messages say that you SSL functions cannot be resolved. That means: either there is no openSSL library or the version of that library does not provide these functions.

              qt.network.ssl: QSslSocket: cannot resolve TLSv1_1_client_method
              qt.network.ssl: QSslSocket: cannot resolve TLSv1_2_client_method
              qt.network.ssl: QSslSocket: cannot resolve TLSv1_1_server_method
              qt.network.ssl: QSslSocket: cannot resolve TLSv1_2_server_method
              qt.network.ssl: QSslSocket: cannot resolve SSL_select_next_proto
              qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
              qt.network.ssl: QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
              qt.network.ssl: QSslSocket: cannot resolve SSL_set_alpn_protos
              qt.network.ssl: QSslSocket: cannot resolve SSL_CTX_set_alpn_select_cb
              qt.network.ssl: QSslSocket: cannot resolve SSL_get0_alpn_selected
              

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • W Offline
                W Offline
                wabisuke2718
                wrote on last edited by wabisuke2718
                #7

                How can I tell if there is no openSSL library or not providing a function?
                I added "qDebug() << QSslSocket::sslLibraryBuildVersionString();" to my source code.
                And result is "OpenSSL 1.0.2h 3 May 2016".

                Would you please let me know if there are documents on procedures to make the appropriate version of openSSL available with Qt?

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  Hi,

                  This information tells you which version of OpenSSL was used to build the backend. Qt doesn't distribute OpenSSL because there are several countries that have restrictions regarding application using encryption.

                  What OS are you running your application on ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved