File indexing completed on 2024-04-28 04:55:44
0001 /* 0002 This file is part of Choqok, the KDE micro-blogging client 0003 0004 SPDX-FileCopyrightText: 2017 Andrea Scarpino <scarpino@kde.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0007 */ 0008 0009 #include "mastodoneditaccountwidget.h" 0010 0011 #include <QCoreApplication> 0012 #include <QCheckBox> 0013 #include <QInputDialog> 0014 #include <QJsonDocument> 0015 #include <QEventLoop> 0016 #include <QPushButton> 0017 #include <QUrl> 0018 0019 #include <KIO/AccessManager> 0020 #include <KIO/StoredTransferJob> 0021 #include <KMessageBox> 0022 0023 #include "choqoktools.h" 0024 #include "accountmanager.h" 0025 0026 #include "mastodonaccount.h" 0027 #include "mastodondebug.h" 0028 #include "mastodonmicroblog.h" 0029 #include "mastodonoauth.h" 0030 0031 MastodonEditAccountWidget::MastodonEditAccountWidget(MastodonMicroBlog *microblog, 0032 MastodonAccount *account, 0033 QWidget *parent): 0034 ChoqokEditAccountWidget(account, parent) 0035 , m_account(account) 0036 { 0037 setupUi(this); 0038 0039 connect(kcfg_authorize, &QPushButton::clicked, this, &MastodonEditAccountWidget::authorizeUser); 0040 0041 if (m_account) { 0042 kcfg_alias->setText(m_account->alias()); 0043 kcfg_acct->setText(m_account->username()); 0044 setAuthenticated(!m_account->tokenSecret().isEmpty()); 0045 } else { 0046 setAuthenticated(false); 0047 QString newAccountAlias = microblog->serviceName(); 0048 const QString servName = newAccountAlias; 0049 int counter = 1; 0050 while (Choqok::AccountManager::self()->findAccount(newAccountAlias)) { 0051 newAccountAlias = QStringLiteral("%1%2").arg(servName).arg(counter); 0052 counter++; 0053 } 0054 m_account = new MastodonAccount(microblog, newAccountAlias); 0055 setAccount(m_account); 0056 kcfg_alias->setText(newAccountAlias); 0057 } 0058 0059 loadTimelinesTable(); 0060 } 0061 0062 MastodonEditAccountWidget::~MastodonEditAccountWidget() 0063 { 0064 } 0065 0066 Choqok::Account *MastodonEditAccountWidget::apply() 0067 { 0068 m_account->setAlias(kcfg_alias->text()); 0069 m_account->setUsername(MastodonMicroBlog::userNameFromAcct(kcfg_acct->text())); 0070 m_account->setTokenSecret(m_account->oAuth()->token()); 0071 m_account->writeConfig(); 0072 saveTimelinesTable(); 0073 return m_account; 0074 } 0075 0076 void MastodonEditAccountWidget::authorizeUser() 0077 { 0078 qCDebug(CHOQOK); 0079 if (kcfg_acct->text().isEmpty() || !kcfg_acct->text().contains(QLatin1Char('@'))) { 0080 return; 0081 } 0082 if (m_account->consumerKey().isEmpty() || m_account->consumerSecret().isEmpty()) { 0083 registerClient(); 0084 } 0085 0086 connect(m_account->oAuth(), &QAbstractOAuth::authorizeWithBrowser, &Choqok::openUrl); 0087 connect(m_account->oAuth(), &QAbstractOAuth::statusChanged, this, &MastodonEditAccountWidget::gotToken); 0088 0089 m_account->oAuth()->grant(); 0090 0091 QString verifier = QInputDialog::getText(this, i18n("Code"), 0092 i18n("Enter the code received from %1", m_account->host())); 0093 if (verifier.isEmpty()) { 0094 return; 0095 } 0096 0097 m_account->oAuth()->getToken(verifier); 0098 } 0099 0100 void MastodonEditAccountWidget::gotToken() 0101 { 0102 isAuthenticated = false; 0103 if (m_account->oAuth()->status() == QAbstractOAuth::Status::Granted) { 0104 setAuthenticated(true); 0105 KMessageBox::information(this, i18n("Choqok is authorized successfully."), i18n("Authorized")); 0106 } else { 0107 KMessageBox::detailedError(this, i18n("Authorization Error"), i18n("OAuth authorization error")); 0108 } 0109 } 0110 0111 bool MastodonEditAccountWidget::validateData() 0112 { 0113 if (kcfg_alias->text().isEmpty() || kcfg_acct->text().isEmpty() || 0114 !kcfg_acct->text().contains(QLatin1Char('@')) || 0115 !isAuthenticated) { 0116 return false; 0117 } else { 0118 return true; 0119 } 0120 } 0121 0122 void MastodonEditAccountWidget::setAuthenticated(bool authenticated) 0123 { 0124 isAuthenticated = authenticated; 0125 if (authenticated) { 0126 kcfg_authorize->setIcon(QIcon::fromTheme(QLatin1String("object-unlocked"))); 0127 kcfg_authenticateLed->on(); 0128 kcfg_authenticateStatus->setText(i18n("Authenticated")); 0129 } else { 0130 kcfg_authorize->setIcon(QIcon::fromTheme(QLatin1String("object-locked"))); 0131 kcfg_authenticateLed->off(); 0132 kcfg_authenticateStatus->setText(i18n("Not Authenticated")); 0133 } 0134 } 0135 0136 void MastodonEditAccountWidget::loadTimelinesTable() 0137 { 0138 for (const QString &timeline: m_account->microblog()->timelineNames()) { 0139 int newRow = timelinesTable->rowCount(); 0140 timelinesTable->insertRow(newRow); 0141 timelinesTable->setItem(newRow, 0, new QTableWidgetItem(timeline)); 0142 0143 QCheckBox *enable = new QCheckBox(timelinesTable); 0144 enable->setChecked(m_account->timelineNames().contains(timeline)); 0145 timelinesTable->setCellWidget(newRow, 1, enable); 0146 } 0147 } 0148 0149 void MastodonEditAccountWidget::registerClient() 0150 { 0151 if (kcfg_acct->text().contains(QLatin1Char('@'))) { 0152 m_account->setUsername(MastodonMicroBlog::userNameFromAcct(kcfg_acct->text())); 0153 m_account->setHost(QLatin1String("https://") + MastodonMicroBlog::hostFromAcct(kcfg_acct->text())); 0154 0155 m_account->oAuth()->setAccessTokenUrl(QUrl(m_account->host() + QLatin1String("/oauth/token"))); 0156 m_account->oAuth()->setAuthorizationUrl(QUrl(m_account->host() + QLatin1String("/oauth/authorize"))); 0157 0158 QUrl url(m_account->host() + QLatin1String("/api/v1/apps")); 0159 QByteArray data; 0160 data += "client_name=" + QCoreApplication::applicationName().toLatin1(); 0161 data += "&redirect_uris=" + QUrl::toPercentEncoding(QLatin1String("urn:ietf:wg:oauth:2.0:oob")); 0162 data += "&scopes=" + QUrl::toPercentEncoding(QLatin1String("read write follow")); 0163 data += "&website=" + QUrl::toPercentEncoding(QLatin1String("https://choqok.kde.org/")); 0164 0165 KIO::StoredTransferJob *job = KIO::storedHttpPost(data, url, KIO::HideProgressInfo); 0166 if (!job) { 0167 qCDebug(CHOQOK) << "Cannot create an http POST request!"; 0168 return; 0169 } 0170 job->addMetaData(QLatin1String("content-type"), QLatin1String("Content-Type: application/x-www-form-urlencoded")); 0171 QEventLoop loop; 0172 connect(job, &KIO::StoredTransferJob::result, &loop, &QEventLoop::quit); 0173 job->start(); 0174 loop.exec(); 0175 0176 if (job->error()) { 0177 qCDebug(CHOQOK) << "An error occurred in Job"; 0178 return; 0179 } else { 0180 KIO::StoredTransferJob *stj = qobject_cast<KIO::StoredTransferJob *>(job); 0181 0182 const QJsonDocument json = QJsonDocument::fromJson(stj->data()); 0183 if (!json.isNull()) { 0184 const QVariantMap result = json.toVariant().toMap(); 0185 m_account->setConsumerKey(result[QLatin1String("client_id")].toString()); 0186 m_account->setConsumerSecret(result[QLatin1String("client_secret")].toString()); 0187 m_account->oAuth()->setClientIdentifier(m_account->consumerKey()); 0188 m_account->oAuth()->setClientIdentifierSharedKey(m_account->consumerSecret()); 0189 } else { 0190 qCDebug(CHOQOK) << "Cannot parse JSON reply"; 0191 } 0192 } 0193 } else { 0194 qCDebug(CHOQOK) << "username is not valid"; 0195 } 0196 } 0197 0198 void MastodonEditAccountWidget::saveTimelinesTable() 0199 { 0200 QStringList timelines; 0201 for (int i = 0; i < timelinesTable->rowCount(); ++i) { 0202 QCheckBox *enable = qobject_cast<QCheckBox *>(timelinesTable->cellWidget(i, 1)); 0203 if (enable && enable->isChecked()) { 0204 timelines.append(timelinesTable->item(i, 0)->text()); 0205 } 0206 } 0207 //m_account->setTimelineNames(timelines); 0208 } 0209 0210 #include "moc_mastodoneditaccountwidget.cpp"