diff --git a/CMakeLists.txt b/CMakeLists.txt index 6227335..37378e8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -103,10 +103,6 @@ endif() target_include_directories(miraya PRIVATE ${FORMS_DIR} ${SOURCE_DIR} - ${SOURCE_TWITCH_DIR} - ${SOURCE_OSU_DIR} - ${SOURCE_UTILS_DIR} - ${SOURCE_SETUPWIZARD_DIR} ) # =========================== linking libraries =========================== target_link_libraries(miraya PRIVATE Qt6::Core Qt6::Widgets Qt6::WebSockets Qt6::Network) diff --git a/forms/preferences.ui b/forms/preferences.ui index c48027f..f595082 100644 --- a/forms/preferences.ui +++ b/forms/preferences.ui @@ -50,6 +50,15 @@ :/resources/images/logo_gosumemory.ico:/resources/images/logo_gosumemory.ico + + + osu! API + + + + :/resources/images/logo_osu.png:/resources/images/logo_osu.png + + Twitch @@ -61,7 +70,7 @@ - Osu! IRC + osu! IRC @@ -161,6 +170,64 @@ + + + + + + QLineEdit::Password + + + + + + + Qt::ImhDigitsOnly + + + + + + + Client ID + + + + + + + Client Secret + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -325,7 +392,7 @@ - + diff --git a/forms/setupwizard.ui b/forms/setupwizard.ui index 03ce812..da2c40b 100644 --- a/forms/setupwizard.ui +++ b/forms/setupwizard.ui @@ -98,6 +98,64 @@ + + + osu! API + + + This will help miraya to grab data from beatmaps when they are requested. + + + + + + + + osu! Client ID + + + + + + + Qt::ImhDigitsOnly + + + 6 + + + + + + + osu! Client Secret + + + + + + + Qt::ImhHiddenText|Qt::ImhNoAutoUppercase|Qt::ImhNoPredictiveText|Qt::ImhSensitiveData + + + QLineEdit::Password + + + + + + + + + <html><head/><body><p>Go to your <a href="https://osu.ppy.sh/home/account/edit"><span style=" text-decoration: underline; color:#4285f4;">osu! account settings</span></a> and create a new OAuth application (at the bottom of the page). </p><p>You can chose whatever name you want, and there is no need to put any application callback URL.</p></body></html> + + + true + + + + + Twitch Setup diff --git a/src/backup/backup.h b/src/backup/backup.h index abd08eb..84f3e50 100644 --- a/src/backup/backup.h +++ b/src/backup/backup.h @@ -10,12 +10,11 @@ #include #include -class Backup : public QObject +class Backup { - Q_OBJECT -public: - static void backup(QString filePath, bool includeSensitiveInfo); - static void restore(QString filePath); + public: + static void backup(QString filePath, bool includeSensitiveInfo); + static void restore(QString filePath); }; #endif // BACKUP_H diff --git a/src/main.cpp b/src/main.cpp index cf32d49..48cac49 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,7 +8,7 @@ int main(int argc, char **argv) { app.setOrganizationName("miraya"); app.setOrganizationDomain("github.com/MirayaProject"); app.setApplicationName("bot"); - app.setApplicationVersion("1.2.0"); + app.setApplicationVersion("1.3.0-alpha.1"); #ifdef Q_OS_LINUX app.setWindowIcon(QIcon(":/resources/logo/logo.png")); #endif diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e639ac0..4677e5e 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -18,6 +18,8 @@ MainWindow::MainWindow(QWidget *parent) : updater = new Updater(this); updater->checkVersion(); + osuApi = new OsuApi(); + setupSignals(); if(!settings.value("setup/completed").toBool()){ on_actionStart_Setup_triggered(); @@ -143,9 +145,18 @@ void MainWindow::onGosumemoryClientMessageReceived(GosuMemoryDataWrapper message void MainWindow::onTwitchClientMessageReceived(TwitchDataWrapper message) { // TODO: this should not be here - for (auto val : Utils().getOsuBeatmapUrls(message.getMessage())) { - qDebug() << "[MainWindow] Osu beatmap url: " << val; - osuIrcClient->sendMap(QUrl(val), message); + for (QString url : Utils::getOsuBeatmapUrls(message.getMessage())) { + qDebug() << "[MainWindow] Osu beatmap url: " << url; + + int beatmapId = Utils::getBeatmapIdFromOsuBeatmapLink(url); + if (beatmapId > 0 && osuApi->isValid()) { + // TODO: also this should not be here + QJsonObject mapData = osuApi->getBeatmapInfo(beatmapId); + osuIrcClient->sendMap(mapData, message); + } + else { + osuIrcClient->sendMap(QUrl(url), message); + } } QLabel* label = getTwitchChatMessage(message.getUsername(), message.getMessage()); diff --git a/src/mainwindow.h b/src/mainwindow.h index 20f6282..e958042 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -27,6 +27,7 @@ #include "twitchdatawrapper.h" #include "updater.h" #include "utils.h" +#include "osu/api/osuapi.h" namespace Ui { @@ -41,7 +42,6 @@ class MainWindow : public QMainWindow explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); - private slots: void on_btnStart_clicked(); void on_actionStart_Setup_triggered(); @@ -78,6 +78,7 @@ class MainWindow : public QMainWindow GosumemoryClient *gosumemoryClient; OsuIrcClient *osuIrcClient; Updater *updater; + OsuApi *osuApi; QLabel *ircConnectionLabel; QLabel *twitchConnectionLabel; diff --git a/src/osu/api/auth/clientCredentialsFlow.cpp b/src/osu/api/auth/clientCredentialsFlow.cpp new file mode 100644 index 0000000..1edcaa1 --- /dev/null +++ b/src/osu/api/auth/clientCredentialsFlow.cpp @@ -0,0 +1,42 @@ +#include "clientCredentialsFlow.h" + +QJsonObject ClientCredentialsFlow::getToken(QString clientId, QString clientSecret, QString oAuthUrl) +{ + qDebug() << "[ClientCredentialsFlow] getToken"; + QNetworkAccessManager manager; + QNetworkRequest request((QUrl(oAuthUrl))); + + request.setHeader( + QNetworkRequest::ContentTypeHeader, + "application/x-www-form-urlencoded" + ); + request.setHeader( + QNetworkRequest::UserAgentHeader, + "Miraya" + ); + + QUrlQuery params; + params.addQueryItem("client_id", clientId); + params.addQueryItem("client_secret", clientSecret); + params.addQueryItem("grant_type", "client_credentials"); + params.addQueryItem("scope", "public"); + + QNetworkReply *reply = manager.post(request, params.toString(QUrl::FullyEncoded).toUtf8()); + + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + + int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + + qDebug() << "[ClientCredentialsFlow] HTTP Status code: " << httpStatusCode; + if (httpStatusCode == 200) { + QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); + QJsonObject obj = doc.object(); + return obj; + } + qDebug() << "[ClientCredentialsFlow] Failed to get token"; + QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); + qDebug() << QString(doc.toJson(QJsonDocument::Compact)); + return doc.object(); +} diff --git a/src/osu/api/auth/clientCredentialsFlow.h b/src/osu/api/auth/clientCredentialsFlow.h new file mode 100644 index 0000000..ecbe07f --- /dev/null +++ b/src/osu/api/auth/clientCredentialsFlow.h @@ -0,0 +1,24 @@ +#ifndef CLIENTCREDENTIALSFLOW_H +#define CLIENTCREDENTIALSFLOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class ClientCredentialsFlow +{ + public: + static QJsonObject getToken( + QString clientId, + QString clientSecret, + QString oAuthUrl = QString("https://osu.ppy.sh/oauth/token") + ); +}; + +#endif // CLIENTCREDENTIALSFLOW_H diff --git a/src/osu/api/osuapi.cpp b/src/osu/api/osuapi.cpp new file mode 100644 index 0000000..7df38e5 --- /dev/null +++ b/src/osu/api/osuapi.cpp @@ -0,0 +1,58 @@ +#include "osuapi.h" + +OsuApi::OsuApi() +{ + qDebug() << "[OsuApi] Init"; + QSettings settings; + clientId = settings.value("osuapi/clientId").toString(); + clientSecret = settings.value("osuapi/clientSecret").toString(); + oAuthUrl = "https://osu.ppy.sh/oauth/token"; + + if (!(clientId.isEmpty() || clientSecret.isEmpty())) { + token = ClientCredentialsFlow::getToken(clientId, clientSecret, oAuthUrl); + } + else { + qDebug() << "[OsuApi] Client ID or Client Secret are empty"; + } +} + +QJsonObject OsuApi::getBeatmapInfo(int beatmapId) +{ + // TODO: A lot can be split into smaller functions + // TODO: also, the QEventLoop is making everything synchronous, which is suboptimal to say the least. + qDebug() << "[OsuApi] getBeatmapInfo"; + QNetworkAccessManager manager; + QUrl url(QString("https://osu.ppy.sh/api/v2/beatmaps/%1").arg(beatmapId)); + + QNetworkRequest request(url); + + QString accessToken = token["access_token"].toString(); + + request.setRawHeader( + QByteArray("Authorization"), + (QString("Bearer %1").arg(accessToken)).toUtf8() + ); + + QNetworkReply *reply = manager.get(request); + + QEventLoop loop; + QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + loop.exec(); + + qDebug() << "[OsuApi] get request done"; + int httpStatusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + qDebug() << "[OsuApi] HTTP Status code: " << httpStatusCode; + if (httpStatusCode == 200) { + QJsonDocument doc = QJsonDocument::fromJson(reply->readAll()); + QJsonObject obj = doc.object(); + qDebug() << "[OsuApi] Beatmap info: " << obj; + return obj; + } + qDebug() << "[OsuApi] Error: " << reply->errorString(); + return QJsonObject(); +} + +bool OsuApi::isValid() +{ + return !(clientId.isEmpty() || clientSecret.isEmpty()); +} diff --git a/src/osu/api/osuapi.h b/src/osu/api/osuapi.h new file mode 100644 index 0000000..a37578d --- /dev/null +++ b/src/osu/api/osuapi.h @@ -0,0 +1,31 @@ +#ifndef OSUAPI_H +#define OSUAPI_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "api/auth/clientCredentialsFlow.h" + +class OsuApi : public QObject +{ + public: + OsuApi(); + QJsonObject getBeatmapInfo(int beatmapId); + bool isValid(); + + private: + QString clientId; + QString clientSecret; + QString oAuthUrl; + QJsonObject token; +}; + +#endif // OSUAPI_H diff --git a/src/osu/irc/osuircclient.cpp b/src/osu/irc/osuircclient.cpp index e6a2680..5bb0550 100644 --- a/src/osu/irc/osuircclient.cpp +++ b/src/osu/irc/osuircclient.cpp @@ -105,12 +105,30 @@ void OsuIrcClient::sendPrivmsg(QString message) void OsuIrcClient::sendMap(QUrl url, TwitchDataWrapper message) { - // TODO: the map embed should have the map name. - // Scraping is needed. - qDebug() << "[osu!IRC] Sending map-request: " << url.toString() << " by " << message.getUsername(); - QString msg = " [" + url.toString() + " Map request] " + "sent by " + message.getUsername() + "\r\n"; + QString msg = QString("[%1 Map request] sent by %2").arg(url.toString()).arg(message.getUsername()); + sendPrivmsg(msg); +} + +void OsuIrcClient::sendMap(QJsonObject map, TwitchDataWrapper message) +{ + QString requestor = message.getUsername(); + QString artist = map["beatmapset"].toObject()["artist"].toString(); + QString title = map["beatmapset"].toObject()["title"].toString(); + QString status = map["beatmapset"].toObject()["status"].toString(); + int mapId = map["id"].toInt(); + QString url = QString("https://osu.ppy.sh/b/%1").arg(mapId); + + qDebug() << "[osu!IRC] Sending map-request: " << url << " by " << requestor << " (" << artist << " - " << title << " - " << status << ")"; + + QString msg = QString("(%1) [%2 %3 - %4] sent by %5") + .arg(status) + .arg(url) + .arg(artist) + .arg(title) + .arg(message.getUsername()); + sendPrivmsg(msg); } @@ -128,4 +146,4 @@ void OsuIrcClient::onReadyRead() handlePing(data.split(" ").last().toLocal8Bit()); } emit readyRead(); -} \ No newline at end of file +} diff --git a/src/osu/irc/osuircclient.h b/src/osu/irc/osuircclient.h index c233c86..d20aaa6 100644 --- a/src/osu/irc/osuircclient.h +++ b/src/osu/irc/osuircclient.h @@ -2,6 +2,7 @@ #define OSUIRCCLIENT_H #include +#include #include #include #include @@ -29,6 +30,7 @@ class OsuIrcClient : public QObject { void setPort(const int &port); void sendPrivmsg(QString message); void sendMap(QUrl url, TwitchDataWrapper message); + void sendMap(QJsonObject map, TwitchDataWrapper message); private: void handlePing(QString response); diff --git a/src/preferences/preferences.cpp b/src/preferences/preferences.cpp index 80da039..b77f656 100644 --- a/src/preferences/preferences.cpp +++ b/src/preferences/preferences.cpp @@ -2,23 +2,23 @@ #include "ui_preferences.h" Preferences::Preferences(QWidget *parent) : - QDialog(parent), - ui(new Ui::Preferences) + QDialog(parent), + ui(new Ui::Preferences) { - ui->setupUi(this); - connect(ui->listWidget, &QListWidget::currentItemChanged, this, &Preferences::on_listWidget_currentItemChanged); - connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &Preferences::on_saveBtnClicked); - connect(ui->backupBtn, &QPushButton::clicked, this, &Preferences::on_backupBtn_clicked); - connect(ui->restoreBtn, &QPushButton::clicked, this, &Preferences::on_restoreBtn_clicked); - ui->listWidget->setCurrentRow(0); - loadSettings(); - setupUi(); + ui->setupUi(this); + connect(ui->listWidget, &QListWidget::currentItemChanged, this, &Preferences::on_listWidget_currentItemChanged); + connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &Preferences::on_saveBtnClicked); + connect(ui->backupBtn, &QPushButton::clicked, this, &Preferences::on_backupBtn_clicked); + connect(ui->restoreBtn, &QPushButton::clicked, this, &Preferences::on_restoreBtn_clicked); + ui->listWidget->setCurrentRow(0); + loadSettings(); + setupUi(); } Preferences::~Preferences() { - delete ui; + delete ui; } @@ -45,121 +45,130 @@ void Preferences::setupUi() void Preferences::loadSettings() { - loadGosuMemorySettings(); - loadTwitchSettings(); - loadOsuIrcSettings(); - loadThemeSettings(); + loadGosuMemorySettings(); + loadTwitchSettings(); + loadOsuIrcSettings(); + loadThemeSettings(); + loadOsuApiSettings(); } void Preferences::loadTwitchSettings() { - ui->twitchBotNickLineEdit->setText(settings.value("twitch/botNick").toString()); - ui->twitchBotOAuthLineEdit->setText(settings.value("twitch/oauth").toString()); - ui->twitchChannelLineEdit->setText(settings.value("twitch/channel").toString()); + ui->twitchBotNickLineEdit->setText(settings.value("twitch/botNick").toString()); + ui->twitchBotOAuthLineEdit->setText(settings.value("twitch/oauth").toString()); + ui->twitchChannelLineEdit->setText(settings.value("twitch/channel").toString()); } +void Preferences::loadOsuApiSettings() +{ + ui->osuapiClientIdLineEdit->setText(settings.value("osuapi/clientId").toString()); + ui->osuapiClientSecretLineEdit->setText(settings.value("osuapi/clientSecret").toString()); +} void Preferences::loadGosuMemorySettings() { - ui->gosumemoryIpLineEdit->setText(settings.value("gosumemory/ip").toString()); - ui->gosumemoryPortLineEdit->setText(settings.value("gosumemory/port").toString()); + ui->gosumemoryIpLineEdit->setText(settings.value("gosumemory/ip").toString()); + ui->gosumemoryPortLineEdit->setText(settings.value("gosumemory/port").toString()); } void Preferences::loadOsuIrcSettings() { - ui->osuIrcNicknameLineEdit->setText(settings.value("osuirc/nick").toString()); - ui->osuIrcPasswordLineEdit->setText(settings.value("osuirc/password").toString()); - ui->osuIrcServerLineEdit->setText(settings.value("osuirc/server").toString()); - ui->osuIrcPortLineEdit->setText(settings.value("osuirc/port").toString()); + ui->osuIrcNicknameLineEdit->setText(settings.value("osuirc/nick").toString()); + ui->osuIrcPasswordLineEdit->setText(settings.value("osuirc/password").toString()); + ui->osuIrcServerLineEdit->setText(settings.value("osuirc/server").toString()); + ui->osuIrcPortLineEdit->setText(settings.value("osuirc/port").toString()); } void Preferences::loadThemeSettings() { - auto darkModeSetting = settings.value("theme/darkMode"); - - if(darkModeSetting.isNull()){ - ui->themesDefaultRadio->setChecked(true); - } - else { - bool isDarkMode = darkModeSetting.toBool(); - ui->themesLightRadio->setChecked(!isDarkMode); - ui->themesDarkRadio->setChecked(isDarkMode); - } + auto darkModeSetting = settings.value("theme/darkMode"); + + if(darkModeSetting.isNull()){ + ui->themesDefaultRadio->setChecked(true); + } + else { + bool isDarkMode = darkModeSetting.toBool(); + ui->themesLightRadio->setChecked(!isDarkMode); + ui->themesDarkRadio->setChecked(isDarkMode); + } } void Preferences::on_saveBtnClicked() { - saveSettings(); - QMessageBox().information(this, "Saved", "Settings saved"); - emit themeChanged(); - accept(); + saveSettings(); + QMessageBox().information(this, "Saved", "Settings saved"); + emit themeChanged(); + accept(); } void Preferences::saveSettings() { - settings.setValue("twitch/botNick", ui->twitchBotNickLineEdit->text().toLower()); - settings.setValue("twitch/oauth", ui->twitchBotOAuthLineEdit->text()); - settings.setValue("twitch/channel", ui->twitchChannelLineEdit->text().toLower()); + settings.setValue("twitch/botNick", ui->twitchBotNickLineEdit->text().toLower()); + settings.setValue("twitch/oauth", ui->twitchBotOAuthLineEdit->text()); + settings.setValue("twitch/channel", ui->twitchChannelLineEdit->text().toLower()); + + settings.setValue("gosumemory/ip", ui->gosumemoryIpLineEdit->text()); + settings.setValue("gosumemory/port", ui->gosumemoryPortLineEdit->text()); - settings.setValue("gosumemory/ip", ui->gosumemoryIpLineEdit->text()); - settings.setValue("gosumemory/port", ui->gosumemoryPortLineEdit->text()); + settings.setValue("osuapi/clientId", ui->osuapiClientIdLineEdit->text()); + settings.setValue("osuapi/clientSecret", ui->osuapiClientSecretLineEdit->text()); // Spaces need to be replaced by underscores. // https://osu.ppy.sh/wiki/en/Community/Internet_Relay_Chat#connection - settings.setValue("osuirc/nick", ui->osuIrcNicknameLineEdit->text().replace(' ', '_')); - settings.setValue("osuirc/password", ui->osuIrcPasswordLineEdit->text()); - settings.setValue("osuirc/server", ui->osuIrcServerLineEdit->text()); - settings.setValue("osuirc/port", ui->osuIrcPortLineEdit->text()); - - if (ui->themesDefaultRadio->isChecked() && settings.contains("theme/darkMode")) { - settings.remove("theme/darkMode"); - } - else { - settings.setValue("theme/darkMode", ui->themesDarkRadio->isChecked()); - } + settings.setValue("osuirc/nick", ui->osuIrcNicknameLineEdit->text().replace(' ', '_')); + settings.setValue("osuirc/password", ui->osuIrcPasswordLineEdit->text()); + settings.setValue("osuirc/server", ui->osuIrcServerLineEdit->text()); + settings.setValue("osuirc/port", ui->osuIrcPortLineEdit->text()); + + if (ui->themesDefaultRadio->isChecked() && settings.contains("theme/darkMode")) { + settings.remove("theme/darkMode"); + } + else { + settings.setValue("theme/darkMode", ui->themesDarkRadio->isChecked()); + } } void Preferences::on_backupBtn_clicked() { - QString message = QString("%1
%2").arg( - "Would you like to include sensitive informations in your backup file?", - "Anyone that has this information will be able to access your accounts!" - ); - - auto buttonAnswer = QMessageBox().question( - this, - "Sensitive information", - message, - QMessageBox::No | QMessageBox::Yes, - QMessageBox::No - ); - bool includeSensitiveInfo = buttonAnswer == QMessageBox::Yes; - - QString filePath = QFileDialog::getSaveFileName(nullptr, "Export Settings", QString(), "JSON Files (*.json)"); - Backup::backup(filePath, includeSensitiveInfo); + QString message = QString("%1
%2").arg( + "Would you like to include sensitive informations in your backup file?", + "Anyone that has this information will be able to access your accounts!" + ); + + auto buttonAnswer = QMessageBox().question( + this, + "Sensitive information", + message, + QMessageBox::No | QMessageBox::Yes, + QMessageBox::No + ); + bool includeSensitiveInfo = buttonAnswer == QMessageBox::Yes; + + QString filePath = QFileDialog::getSaveFileName(nullptr, "Export Settings", QString(), "JSON Files (*.json)"); + Backup::backup(filePath, includeSensitiveInfo); } void Preferences::on_restoreBtn_clicked() { - QString filePath = QFileDialog::getOpenFileName(nullptr, "Import Settings", QString(), "JSON Files (*.json)"); - Backup::restore(filePath); - // reloading - loadSettings(); - QMessageBox().information(this, "Backup Restored", "Backup restored successfully"); + QString filePath = QFileDialog::getOpenFileName(nullptr, "Import Settings", QString(), "JSON Files (*.json)"); + Backup::restore(filePath); + // reloading + loadSettings(); + QMessageBox().information(this, "Backup Restored", "Backup restored successfully"); } void Preferences::on_listWidget_currentItemChanged(QListWidgetItem *current, QListWidgetItem *previous) { - if (current == nullptr) - return; - auto index = ui->listWidget->currentRow(); - ui->stackedWidget->setCurrentIndex(index); + if (current == nullptr) + return; + auto index = ui->listWidget->currentRow(); + ui->stackedWidget->setCurrentIndex(index); } diff --git a/src/preferences/preferences.h b/src/preferences/preferences.h index 4a76de6..0868591 100644 --- a/src/preferences/preferences.h +++ b/src/preferences/preferences.h @@ -32,6 +32,7 @@ class Preferences : public QDialog void loadSettings(); void loadTwitchSettings(); void loadGosuMemorySettings(); + void loadOsuApiSettings(); void loadOsuIrcSettings(); void loadThemeSettings(); void setupUi(); diff --git a/src/setupwizard/setupwizard.cpp b/src/setupwizard/setupwizard.cpp index 0f1de0d..0b3adf7 100644 --- a/src/setupwizard/setupwizard.cpp +++ b/src/setupwizard/setupwizard.cpp @@ -53,8 +53,8 @@ void SetupWizard::on_SetupWizard_finished(int result) QJsonObject SetupWizard::gatherData() { QJsonObject data; - data["gosumemory"] = getGosumemoryData(); + data["osuapi"] = getOsuApiData(); data["twitch"] = getTwitchData(); data["osuirc"] = getOsuircData(); @@ -75,6 +75,18 @@ QJsonObject SetupWizard::getGosumemoryData() return gosumemoryData; } +QJsonObject SetupWizard::getOsuApiData() +{ + int osuapiClientId = ui->osuapiClientIdLineEdit->text().toInt(); + QString osuapiClientSecret = ui->osuapiClientSecretLineEdit->text(); + + QJsonObject osuapiClientData = QJsonObject{ + {"clientId", osuapiClientId}, + {"clientSecret", osuapiClientSecret} + }; + + return osuapiClientData; +} QJsonObject SetupWizard::getTwitchData() { @@ -117,6 +129,7 @@ QJsonObject SetupWizard::getOsuircData() void SetupWizard::saveData(QJsonObject data) { QSettings settings; + QJsonObject osuapiData = data["osuapi"].toObject(); QJsonObject gosumemoryData = data["gosumemory"].toObject(); QJsonObject twitchData = data["twitch"].toObject(); QJsonObject osuircData = data["osuirc"].toObject(); @@ -124,6 +137,9 @@ void SetupWizard::saveData(QJsonObject data) settings.setValue("gosumemory/ip", gosumemoryData["ip"].toString()); settings.setValue("gosumemory/port", gosumemoryData["port"].toInt()); + settings.setValue("osuapi/clientId", osuapiData["clientId"].toInt()); + settings.setValue("osuapi/clientSecret", osuapiData["clientSecret"].toString()); + settings.setValue("twitch/botNick", twitchData["botNick"].toString()); settings.setValue("twitch/oauth", twitchData["oauth"].toString()); settings.setValue("twitch/channel", twitchData["channel"].toString()); diff --git a/src/setupwizard/setupwizard.h b/src/setupwizard/setupwizard.h index 2ec9bfc..ac6016e 100644 --- a/src/setupwizard/setupwizard.h +++ b/src/setupwizard/setupwizard.h @@ -29,6 +29,7 @@ private slots: QJsonObject gatherData(); QJsonObject getGosumemoryData(); + QJsonObject getOsuApiData(); QJsonObject getTwitchData(); QJsonObject getOsuircData(); void saveData(QJsonObject data); diff --git a/src/utils/utils.cpp b/src/utils/utils.cpp index 815c7bb..16656e7 100644 --- a/src/utils/utils.cpp +++ b/src/utils/utils.cpp @@ -29,3 +29,18 @@ QStringList Utils::getUrls(QString message) } return list; } + +int Utils::getBeatmapIdFromOsuBeatmapLink(QString link) +{ + qDebug() << "getBeatmapIdFromOsuBeatmapLink: " << link; + + // https://osu.ppy.sh/beatmapsets/2055856#taiko/4295990 + QRegularExpression rx("(b=|b/|beatmapsets/\\d+#osu/|beatmapsets/\\d+#taiko/|beatmapsets/\\d+#fruits/|beatmapsets/\\d+#mania/)(\\d+)"); + QRegularExpressionMatch match = rx.match(link); + if (match.hasMatch()) { + int id = match.captured(2).toInt(); + qDebug() << "found beatmap id: " << id; + return id; + } + return -1; +} diff --git a/src/utils/utils.h b/src/utils/utils.h index d660bb2..2feab9f 100644 --- a/src/utils/utils.h +++ b/src/utils/utils.h @@ -10,6 +10,7 @@ class Utils public: static QStringList getOsuBeatmapUrls(QString message); static QStringList getUrls(QString message); + static int getBeatmapIdFromOsuBeatmapLink(QString link); }; #endif // UTILS_H