-
Notifications
You must be signed in to change notification settings - Fork 165
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Download files from direct URLs via a command line parameter #1873
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made some minor comments on the review but I don't like the way this is currently done. I think downloading file should be a distinct command, like modorganizer.exe download https://xxx
. This is how nxm links should be handled (but are not for historical reasons).
src/commandline.cpp
Outdated
@@ -187,6 +187,8 @@ std::optional<int> CommandLine::process(const std::wstring& line) | |||
// not a shortcut, try a link | |||
if (isNxmLink(qs)) { | |||
m_nxmLink = qs; | |||
} else if (qs.startsWith("https://", Qt::CaseInsensitive) || qs.startsWith("http://", Qt::CaseInsensitive)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think http://
download links should be allowed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is about what user
supplies to MO2. Links posted on the internet may begin with http:
(this happens), when in fact, the link would be immediately redirected to https
. If you want user to see a warning message, manually fix the link and run again, sure, I can add that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand why you would do that but that's a very bad idea, especially knowing what's possible to do with mods. If people still post http://
links on their website, then that's the website faults, MO2 should not have to deal with that, we're in 2023.
I would simply not handle the link. Users are unlikely to run this command manually, so the warning would only be seen by the external tools that would dispatch link, in which case the check could be made there and MO2 would just have to return an error code.
@@ -440,7 +455,10 @@ bool DownloadManager::addDownload(const QStringList &URLs, QString gameName, | |||
h2Conf.setStreamReceiveWindowSize(16777215); | |||
QNetworkRequest request(preferredUrl); | |||
request.setHeader(QNetworkRequest::UserAgentHeader, m_NexusInterface->getAccessManager()->userAgent()); | |||
request.setAttribute(QNetworkRequest::CacheSaveControlAttribute, false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for these two added attributes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same reason they are used in Nexus downloads https://github.com/ModOrganizer2/modorganizer/blob/qt6/src/nexusinterface.cpp#L821 . Spent half a day pulling my hair out on this.
By default, MO2 caches repeating requests, especially with small files. When this happens, the finished()
signal is sent immediately, causing downloadFinished
to fire before downloading a single byte. Then the check for size==0 kicks in here https://github.com/ModOrganizer2/modorganizer/blob/qt6/src/downloadmanager.cpp#L2100 , and the download gets marked as failed without showing a single message, because messages don't cover this case.
These two lines disable cache for the request.
@@ -580,7 +598,10 @@ void DownloadManager::startDownload(QNetworkReply *reply, DownloadInfo *newDownl | |||
newDownload->m_State != STATE_READY && | |||
newDownload->m_State != STATE_FETCHINGMODINFO && | |||
reply->isFinished()) { | |||
downloadFinished(indexByInfo(newDownload)); | |||
int index = indexByInfo(newDownload); | |||
if (index >= 0) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The needs for this should be investigated, although probably not relevant for this PR, but maybe add a TODO comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the fix to downloadFinished
(below) is accepted, this may be redundant (I need to re-check). If it's not accepted, downloadFinished
may fire with invalid -1 value, causing the no download index
warning.
src/downloadmanager.cpp
Outdated
@@ -916,7 +937,7 @@ void DownloadManager::resumeDownloadInt(int index) | |||
|
|||
// Check for finished download; | |||
if (info->m_TotalSize <= info->m_Output.size() && info->m_Reply != nullptr | |||
&& info->m_Reply->isOpen() && info->m_Reply->isFinished() && info->m_State != STATE_ERROR) { | |||
&& info->m_Reply->isFinished() && info->m_State != STATE_ERROR) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, this is actually a leftover from investigating the cache issue, I used resumeDownloadInt
as a crutch. When MO2 is closed and file exists, resumeDownloadInt
would skip this block, because connection is not open at that point, and append the same contents to the file again, doubling its size.
Since resumeDownloadInt
is irrelevant to this PR, I have reverted this change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correction - this is unrelated to the cache issue, happens with disabled cache as well, I brought the change back.
@@ -2076,10 +2097,14 @@ void DownloadManager::nxmRequestFailed(QString gameName, int modID, int fileID, | |||
void DownloadManager::downloadFinished(int index) | |||
{ | |||
DownloadInfo *info; | |||
if (index) | |||
if (index > 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason for this change (and the one below)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
downloadFinished
is used in two ways:
- as a function, accepting an integer argument,
- as a signal callback.
Currently, downloadFinished
has a bug, when it does not run for the first download in the list (index 0), because of the logical mistake here 0==false https://github.com/ModOrganizer2/modorganizer/blob/qt6/src/downloadmanager.cpp#L2079
When it runs with downloadFinished(0), if (index)
skips execution and jumps to detecting the signal sender, which yields nothing, because it is not a signal call. As a result, the first file may never see the finishing routine, causing cascade of errors and discrepancy in interface and actual status. In case of the proposed command, this looks like a duplicating paused file, when user tries to redownload the first file.
The first idea was to add if (index >= 0)
, but then the signal callback info = findDownload(this->sender(), &index)
never fires, because during the callback index
is also 0
.
So I implemented detection of the first row as a fallback after all paths are exhausted.
I expected opposition on this fix and added the additional check in startDownload
, catching possible downloadFinished(-1) call, which is an invalid value, causing the no download index
warning. If the fix is accepted, the startDownload
change probably becomes redundant.
src/moapplication.cpp
Outdated
@@ -405,6 +405,9 @@ void MOApplication::externalMessage(const QString& message) | |||
} else if (isNxmLink(message)) { | |||
MessageDialog::showMessage(tr("Download started"), qApp->activeWindow(), false); | |||
m_core->downloadRequestedNXM(message); | |||
} else if (message.startsWith("https://", Qt::CaseInsensitive) || message.startsWith("http://", Qt::CaseInsensitive)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as above, I don't think http://
links should be accepted.
I agree with Holt, this should be behind a dedicated download command. |
I've changed the target branch to |
# Conflicts: # src/aboutdialog.cpp # src/aboutdialog.h # src/commandline.cpp # src/commandline.h # src/directoryrefresher.cpp # src/downloadmanager.cpp # src/organizercore.cpp
Adds the ability to use MO2's download manager to download files via direct URLs or temporary URLs from S3-compatible storages.
Usage:
ModOrganizer.exe "https://eddoursul.win/Cyberware%20TTW%20Patch.7z"
ModOrganizer.exe download "https://eddoursul.win/Cyberware%20TTW%20Patch.7z"