mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-07-22 02:12:14 -07:00
* refactored cardzone.cpp, added doc and changed if to switch case * started moving every files into different folders * remove undercase to match with other files naming convention * refactored dialog files * ran format.sh * refactored client/tabs folder * refactored client/tabs folder * refactored client/tabs folder * refactored client folder * refactored carddbparser * refactored dialogs * Create sonar-project.properties temporary file for lint * Create build.yml temporary file for lint * removed all files from root directory * removed all files from root directory * added current branch to workflow * fixed most broken import * fixed issues while renaming files * fixed oracle importer * fixed dbconverter * updated translations * made sub-folders for client * removed linter * removed linter folder * fixed oracle import * revert card_zone documentation * renamed db parser files name and deck_view imports * fixed dlg file issue * ran format file and fixed test file * fixed carddb test files * moved player folder in game * updated translations and format files * fixed peglib import * format cmake files * removing vcpkg to try to add it back later * tried fixing vcpkg file * renamed filter to filters and moved database parser to cards folder * reverted translation files * reverted oracle translated * Update cockatrice/src/dialogs/dlg_register.cpp Co-authored-by: tooomm <tooomm@users.noreply.github.com> * Update cockatrice/src/client/ui/window_main.cpp Co-authored-by: tooomm <tooomm@users.noreply.github.com> * removed empty line at file start * removed useless include from tab_supervisor.cpp * refactored cardzone.cpp, added doc and changed if to switch case * started moving every files into different folders * remove undercase to match with other files naming convention * refactored dialog files * ran format.sh * refactored client/tabs folder * refactored client folder * refactored carddbparser * refactored dialogs * removed all files from root directory * Create sonar-project.properties temporary file for lint * Create build.yml temporary file for lint * added current branch to workflow * fixed most broken import * fixed issues while renaming files * fixed oracle importer * fixed dbconverter * updated translations * made sub-folders for client * removed linter * removed linter folder * fixed oracle import * revert card_zone documentation * renamed db parser files name and deck_view imports * fixed dlg file issue * ran format file and fixed test file * fixed carddb test files * moved player folder in game * updated translations and format files * fixed peglib import * reverted translation files * format cmake files * removing vcpkg to try to add it back later * tried fixing vcpkg file * pre-updating of cockatrice changes * removed empty line at file start * reverted oracle translated * Update cockatrice/src/dialogs/dlg_register.cpp Co-authored-by: tooomm <tooomm@users.noreply.github.com> * Update cockatrice/src/client/ui/window_main.cpp Co-authored-by: tooomm <tooomm@users.noreply.github.com> * removed useless include from tab_supervisor.cpp --------- Co-authored-by: tooomm <tooomm@users.noreply.github.com>
122 lines
4.4 KiB
C++
122 lines
4.4 KiB
C++
#include "tapped_out_interface.h"
|
|
|
|
#include "decklist.h"
|
|
|
|
#include <QDesktopServices>
|
|
#include <QMessageBox>
|
|
#include <QNetworkAccessManager>
|
|
#include <QNetworkReply>
|
|
#include <QNetworkRequest>
|
|
#include <QRegularExpression>
|
|
#include <QUrlQuery>
|
|
|
|
TappedOutInterface::TappedOutInterface(CardDatabase &_cardDatabase, QObject *parent)
|
|
: QObject(parent), cardDatabase(_cardDatabase)
|
|
{
|
|
manager = new QNetworkAccessManager(this);
|
|
connect(manager, SIGNAL(finished(QNetworkReply *)), this, SLOT(queryFinished(QNetworkReply *)));
|
|
}
|
|
|
|
void TappedOutInterface::queryFinished(QNetworkReply *reply)
|
|
{
|
|
if (reply->error() != QNetworkReply::NoError) {
|
|
QMessageBox::critical(nullptr, tr("Error"), reply->errorString());
|
|
reply->deleteLater();
|
|
deleteLater();
|
|
return;
|
|
}
|
|
|
|
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
|
|
if (reply->hasRawHeader("Location")) {
|
|
/*
|
|
* If the reply contains a "Location" header, a relative URL to the deck on TappedOut
|
|
* can be extracted from the header. The http status is a 302 "redirect".
|
|
*/
|
|
QString deckUrl = reply->rawHeader("Location");
|
|
qDebug() << "Tappedout: good reply, http status" << httpStatus << "location" << deckUrl;
|
|
QDesktopServices::openUrl("https://tappedout.net" + deckUrl);
|
|
} else {
|
|
/*
|
|
* Otherwise, the deck has not been parsed correctly. Error messages can be extracted
|
|
* from the html. Css pseudo selector for errors: $("div.alert-danger > ul > li")
|
|
*/
|
|
QString data(reply->readAll());
|
|
QStringList errorMessageList = {tr("Unable to analyze the deck.")};
|
|
|
|
static const QRegularExpression rx("<div class=\"alert alert-danger.*?<ul>(.*?)</ul>");
|
|
auto match = rx.match(data);
|
|
if (match.hasMatch()) {
|
|
QString errors = match.captured(1);
|
|
static const QRegularExpression rx2("<li>(.*?)</li>");
|
|
static const QRegularExpression rxremove("<[^>]*>");
|
|
auto matchIterator = rx2.globalMatch(errors);
|
|
while (matchIterator.hasNext()) {
|
|
auto match2 = matchIterator.next();
|
|
errorMessageList.append(match2.captured(1).remove(rxremove).simplified());
|
|
}
|
|
}
|
|
|
|
QString errorMessage = errorMessageList.join("\n");
|
|
qDebug() << "Tappedout: bad reply, http status" << httpStatus << "size" << data.size() << "message"
|
|
<< errorMessage;
|
|
|
|
QMessageBox::critical(nullptr, tr("Error"), errorMessage);
|
|
}
|
|
|
|
reply->deleteLater();
|
|
deleteLater();
|
|
}
|
|
|
|
void TappedOutInterface::getAnalyzeRequestData(DeckList *deck, QByteArray *data)
|
|
{
|
|
DeckList mainboard, sideboard;
|
|
copyDeckSplitMainAndSide(*deck, mainboard, sideboard);
|
|
|
|
QUrl params;
|
|
QUrlQuery urlQuery;
|
|
urlQuery.addQueryItem("name", deck->getName());
|
|
urlQuery.addQueryItem("mainboard", mainboard.writeToString_Plain(false, true));
|
|
urlQuery.addQueryItem("sideboard", sideboard.writeToString_Plain(false, true));
|
|
params.setQuery(urlQuery);
|
|
data->append(params.query(QUrl::EncodeReserved).toUtf8());
|
|
}
|
|
|
|
void TappedOutInterface::analyzeDeck(DeckList *deck)
|
|
{
|
|
QByteArray data;
|
|
getAnalyzeRequestData(deck, &data);
|
|
|
|
QNetworkRequest request(QUrl("https://tappedout.net/mtg-decks/paste/"));
|
|
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
|
|
|
|
manager->post(request, data);
|
|
}
|
|
|
|
struct CopyMainOrSide
|
|
{
|
|
CardDatabase &cardDatabase;
|
|
DeckList &mainboard, &sideboard;
|
|
|
|
CopyMainOrSide(CardDatabase &_cardDatabase, DeckList &_mainboard, DeckList &_sideboard)
|
|
: cardDatabase(_cardDatabase), mainboard(_mainboard), sideboard(_sideboard){};
|
|
|
|
void operator()(const InnerDecklistNode *node, const DecklistCardNode *card) const
|
|
{
|
|
CardInfoPtr dbCard = cardDatabase.getCard(card->getName());
|
|
if (!dbCard || dbCard->getIsToken())
|
|
return;
|
|
|
|
DecklistCardNode *addedCard;
|
|
if (node->getName() == DECK_ZONE_SIDE)
|
|
addedCard = sideboard.addCard(card->getName(), node->getName());
|
|
else
|
|
addedCard = mainboard.addCard(card->getName(), node->getName());
|
|
addedCard->setNumber(card->getNumber());
|
|
}
|
|
};
|
|
|
|
void TappedOutInterface::copyDeckSplitMainAndSide(const DeckList &source, DeckList &mainboard, DeckList &sideboard)
|
|
{
|
|
CopyMainOrSide copyMainOrSide(cardDatabase, mainboard, sideboard);
|
|
source.forEachCard(copyMainOrSide);
|
|
}
|