NOISSUE add silly twitch URL and CCIP resolving page to 'add instance'
It needs a few more steps and it will handle all kinds of twitch packs.
This commit is contained in:
parent
917f148fc4
commit
fde43c993e
@ -443,6 +443,8 @@ set(FLAME_SOURCES
|
|||||||
modplatform/flame/PackManifest.cpp
|
modplatform/flame/PackManifest.cpp
|
||||||
modplatform/flame/FileResolvingTask.h
|
modplatform/flame/FileResolvingTask.h
|
||||||
modplatform/flame/FileResolvingTask.cpp
|
modplatform/flame/FileResolvingTask.cpp
|
||||||
|
modplatform/flame/UrlResolvingTask.h
|
||||||
|
modplatform/flame/UrlResolvingTask.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_unit_test(Index
|
add_unit_test(Index
|
||||||
|
140
api/logic/modplatform/flame/UrlResolvingTask.cpp
Normal file
140
api/logic/modplatform/flame/UrlResolvingTask.cpp
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
#include "UrlResolvingTask.h"
|
||||||
|
#include <QtXml>
|
||||||
|
|
||||||
|
/*
|
||||||
|
namespace {
|
||||||
|
const char * metabase = "https://cursemeta.dries007.net";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
Flame::UrlResolvingTask::UrlResolvingTask(const QString& toProcess)
|
||||||
|
: m_url(toProcess)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flame::UrlResolvingTask::executeTask()
|
||||||
|
{
|
||||||
|
setStatus(tr("Resolving URL..."));
|
||||||
|
setProgress(0, 1);
|
||||||
|
m_dljob.reset(new NetJob("URL resolver"));
|
||||||
|
|
||||||
|
weAreDigging = false;
|
||||||
|
needle = QString();
|
||||||
|
|
||||||
|
if(m_url.startsWith("https://")) {
|
||||||
|
if(m_url.endsWith("?client=y")) {
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download?client=y
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088?client=y
|
||||||
|
m_url.chop(9);
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088
|
||||||
|
}
|
||||||
|
if(m_url.endsWith("/download")) {
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download -> need to dig inside html...
|
||||||
|
weAreDigging = true;
|
||||||
|
needle = m_url;
|
||||||
|
needle.replace("https://", "twitch://");
|
||||||
|
needle.replace("/download", "/download-client/");
|
||||||
|
m_url.append("?client=y");
|
||||||
|
} else if (m_url.contains("/download/")) {
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download/2697088
|
||||||
|
m_url.replace("/download/", "/download-client/");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(m_url.startsWith("twitch://")) {
|
||||||
|
// twitch://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
|
||||||
|
m_url.replace(0, 9, "https://");
|
||||||
|
// https://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
|
||||||
|
}
|
||||||
|
auto dl = Net::Download::makeByteArray(QUrl(m_url), &results);
|
||||||
|
m_dljob->addNetAction(dl);
|
||||||
|
connect(m_dljob.get(), &NetJob::finished, this, &Flame::UrlResolvingTask::netJobFinished);
|
||||||
|
m_dljob->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flame::UrlResolvingTask::netJobFinished()
|
||||||
|
{
|
||||||
|
if(weAreDigging) {
|
||||||
|
processHTML();
|
||||||
|
} else {
|
||||||
|
processCCIP();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flame::UrlResolvingTask::processHTML()
|
||||||
|
{
|
||||||
|
QString htmlDoc = QString::fromUtf8(results);
|
||||||
|
auto index = htmlDoc.indexOf(needle);
|
||||||
|
if(index < 0) {
|
||||||
|
emitFailed(tr("Couldn't find the needle in the haystack..."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto indexStart = index;
|
||||||
|
int indexEnd = -1;
|
||||||
|
while((index + 1) < htmlDoc.size() && htmlDoc[index] != '"') {
|
||||||
|
index ++;
|
||||||
|
if(htmlDoc[index] == '"') {
|
||||||
|
indexEnd = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(indexEnd > 0) {
|
||||||
|
QString found = htmlDoc.mid(indexStart, indexEnd - indexStart);
|
||||||
|
qDebug() << "Found needle: " << found;
|
||||||
|
// twitch://www.curseforge.com/minecraft/modpacks/ftb-sky-odyssey/download-client/2697088
|
||||||
|
m_url = found;
|
||||||
|
executeTask();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
emitFailed(tr("Couldn't find the end of the needle in the haystack..."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flame::UrlResolvingTask::processCCIP()
|
||||||
|
{
|
||||||
|
QDomDocument doc;
|
||||||
|
if (!doc.setContent(results)) {
|
||||||
|
qDebug() << results;
|
||||||
|
emitFailed(tr("Resolving failed."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto packageNode = doc.namedItem("package");
|
||||||
|
if(!packageNode.isElement()) {
|
||||||
|
emitFailed(tr("Resolving failed: missing package root element."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto projectNode = packageNode.namedItem("project");
|
||||||
|
if(!projectNode.isElement()) {
|
||||||
|
emitFailed(tr("Resolving failed: missing project element."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto attribs = projectNode.attributes();
|
||||||
|
|
||||||
|
auto projectIdNode = attribs.namedItem("id");
|
||||||
|
if(!projectIdNode.isAttr()) {
|
||||||
|
emitFailed(tr("Resolving failed: missing id attribute."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto fileIdNode = attribs.namedItem("file");
|
||||||
|
if(!fileIdNode.isAttr()) {
|
||||||
|
emitFailed(tr("Resolving failed: missing file attribute."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto projectId = projectIdNode.nodeValue();
|
||||||
|
auto fileId = fileIdNode.nodeValue();
|
||||||
|
bool success = true;
|
||||||
|
m_result.projectId = projectId.toInt(&success);
|
||||||
|
if(!success) {
|
||||||
|
emitFailed(tr("Failed to resove projectId as a number."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_result.fileId = fileId.toInt(&success);
|
||||||
|
if(!success) {
|
||||||
|
emitFailed(tr("Failed to resove fileId as a number."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qDebug() << "Resolved" << m_url << "as" << m_result.projectId << "/" << m_result.fileId;
|
||||||
|
emitSucceeded();
|
||||||
|
}
|
||||||
|
|
40
api/logic/modplatform/flame/UrlResolvingTask.h
Normal file
40
api/logic/modplatform/flame/UrlResolvingTask.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tasks/Task.h"
|
||||||
|
#include "net/NetJob.h"
|
||||||
|
#include "PackManifest.h"
|
||||||
|
|
||||||
|
#include "multimc_logic_export.h"
|
||||||
|
|
||||||
|
namespace Flame
|
||||||
|
{
|
||||||
|
class MULTIMC_LOGIC_EXPORT UrlResolvingTask : public Task
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit UrlResolvingTask(const QString &toProcess);
|
||||||
|
virtual ~UrlResolvingTask() {};
|
||||||
|
|
||||||
|
const Flame::File &getResults() const
|
||||||
|
{
|
||||||
|
return m_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void executeTask() override;
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void processCCIP();
|
||||||
|
void processHTML();
|
||||||
|
void netJobFinished();
|
||||||
|
|
||||||
|
private: /* data */
|
||||||
|
QString m_url;
|
||||||
|
QString needle;
|
||||||
|
Flame::File m_result;
|
||||||
|
QByteArray results;
|
||||||
|
NetJobPtr m_dljob;
|
||||||
|
bool weAreDigging = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -75,6 +75,11 @@ void ImportPage::updateState()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if(input.endsWith("?client=y")) {
|
||||||
|
input.chop(9);
|
||||||
|
input.append("/file");
|
||||||
|
url = QUrl::fromUserInput(input);
|
||||||
|
}
|
||||||
// hook, line and sinker.
|
// hook, line and sinker.
|
||||||
QFileInfo fi(url.fileName());
|
QFileInfo fi(url.fileName());
|
||||||
dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url));
|
dialog->setSuggestedPack(fi.completeBaseName(), new InstanceImportTask(url));
|
||||||
|
@ -8,6 +8,7 @@ TwitchPage::TwitchPage(NewInstanceDialog* dialog, QWidget *parent)
|
|||||||
: QWidget(parent), ui(new Ui::TwitchPage), dialog(dialog)
|
: QWidget(parent), ui(new Ui::TwitchPage), dialog(dialog)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
connect(ui->checkButton, &QPushButton::clicked, this, &TwitchPage::triggerCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
TwitchPage::~TwitchPage()
|
TwitchPage::~TwitchPage()
|
||||||
@ -17,10 +18,30 @@ TwitchPage::~TwitchPage()
|
|||||||
|
|
||||||
bool TwitchPage::shouldDisplay() const
|
bool TwitchPage::shouldDisplay() const
|
||||||
{
|
{
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TwitchPage::openedImpl()
|
void TwitchPage::openedImpl()
|
||||||
{
|
{
|
||||||
dialog->setSuggestedPack();
|
dialog->setSuggestedPack();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TwitchPage::triggerCheck(bool)
|
||||||
|
{
|
||||||
|
if(m_modIdResolver) {
|
||||||
|
qDebug() << "Click!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto task = new Flame::UrlResolvingTask(ui->lineEdit->text());
|
||||||
|
connect(task, &Task::finished, this, &TwitchPage::checkDone);
|
||||||
|
m_modIdResolver.reset(task);
|
||||||
|
task->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TwitchPage::checkDone()
|
||||||
|
{
|
||||||
|
auto result = m_modIdResolver->getResults();
|
||||||
|
auto formatted = QString("Project %1, File %2").arg(result.projectId).arg(result.fileId);
|
||||||
|
ui->twitchLabel->setText(formatted);
|
||||||
|
m_modIdResolver.reset();
|
||||||
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "pages/BasePage.h"
|
#include "pages/BasePage.h"
|
||||||
#include <MultiMC.h>
|
#include <MultiMC.h>
|
||||||
#include "tasks/Task.h"
|
#include "tasks/Task.h"
|
||||||
|
#include "modplatform/flame/UrlResolvingTask.h"
|
||||||
|
|
||||||
namespace Ui
|
namespace Ui
|
||||||
{
|
{
|
||||||
@ -55,7 +56,12 @@ public:
|
|||||||
|
|
||||||
void openedImpl() override;
|
void openedImpl() override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void triggerCheck(bool checked);
|
||||||
|
void checkDone();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::TwitchPage *ui = nullptr;
|
Ui::TwitchPage *ui = nullptr;
|
||||||
NewInstanceDialog* dialog = nullptr;
|
NewInstanceDialog* dialog = nullptr;
|
||||||
|
shared_qobject_ptr<Flame::UrlResolvingTask> m_modIdResolver;
|
||||||
};
|
};
|
||||||
|
@ -10,9 +10,25 @@
|
|||||||
<height>405</height>
|
<height>405</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item>
|
<item row="0" column="1">
|
||||||
<widget class="QLabel" name="label_3">
|
<widget class="QLineEdit" name="lineEdit"/>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Twitch URL:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0" colspan="3">
|
||||||
|
<widget class="QLabel" name="twitchLabel">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
<property name="font">
|
<property name="font">
|
||||||
<font>
|
<font>
|
||||||
<pointsize>40</pointsize>
|
<pointsize>40</pointsize>
|
||||||
@ -26,8 +42,19 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<widget class="QPushButton" name="checkButton">
|
||||||
|
<property name="text">
|
||||||
|
<string>Check</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>lineEdit</tabstop>
|
||||||
|
<tabstop>checkButton</tabstop>
|
||||||
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../resources/assets/assets.qrc"/>
|
<include location="../../resources/assets/assets.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
Reference in New Issue
Block a user