feat: allow opening arbitrary urls with streamlink (#7162)

Reported-by: ContinualDissapointment
Reviewed-by: pajlada <rasmus.karlsson@pajlada.com>
This commit is contained in:
Arne
2026-08-09 11:12:30 +00:00
committed by GitHub
parent 514ff0b42c
commit e64e74bcd0
7 changed files with 34 additions and 25 deletions
+3 -3
View File
@@ -340,15 +340,15 @@ QString streamlink(const CommandContext &ctx)
else
{
ctx.channel->addSystemMessage(
"/streamlink [channel]. Open specified Twitch channel in "
"streamlink. If no channel argument is specified, open the "
"/streamlink [channel/URL]. Open specified Twitch channel or "
"URL in streamlink. If no argument is specified, open the "
"current Twitch channel instead.");
return "";
}
}
stripChannelName(target);
openStreamlinkForChannel(target);
openStreamlinkForChannelOrUrl(target);
return "";
}
+1 -1
View File
@@ -80,7 +80,7 @@ void performReaction(const ToastReaction &reaction, const QString &channelName)
QDesktopServices::openUrl(QUrl(TWITCH_PLAYER_URL.arg(channelName)));
break;
case ToastReaction::OpenInStreamlink: {
openStreamlinkForChannel(channelName);
openStreamlinkForChannelOrUrl(channelName);
break;
}
case ToastReaction::OpenInCustomPlayer: {
+17 -8
View File
@@ -5,6 +5,7 @@
#include "util/StreamLink.hpp"
#include "Application.hpp"
#include "common/LinkParser.hpp"
#include "common/QLogging.hpp"
#include "common/Version.hpp"
#include "singletons/Settings.hpp"
@@ -159,12 +160,12 @@ void getStreamQualities(const QString &channelURL,
p->start();
}
void openStreamlink(const QString &channelURL, const QString &quality,
void openStreamlink(const QString &url, const QString &quality,
QStringList extraArguments)
{
auto *proc = createStreamlinkProcess();
auto arguments = proc->arguments()
<< std::move(extraArguments) << channelURL << quality;
<< std::move(extraArguments) << url << quality;
// Remove empty arguments before appending additional streamlink options
// as the options might purposely contain empty arguments
@@ -182,7 +183,7 @@ void openStreamlink(const QString &channelURL, const QString &quality,
}
}
void openStreamlinkForChannel(const QString &channel)
void openStreamlinkForChannelOrUrl(const QString &channelOrUrl)
{
static const QString INFO_TEMPLATE("Opening %1 in Streamlink ...");
@@ -197,18 +198,26 @@ void openStreamlinkForChannel(const QString &channel)
if (currentSplit != nullptr)
{
currentSplit->getChannel()->addSystemMessage(
INFO_TEMPLATE.arg(channel));
INFO_TEMPLATE.arg(channelOrUrl));
}
}
QString channelURL = "twitch.tv/" + channel;
QString url;
if (linkparser::parse(channelOrUrl).has_value())
{
url = channelOrUrl;
}
else
{
url = "twitch.tv/" + channelOrUrl;
}
auto preferredQuality = getSettings()->preferredQuality.getEnum();
if (preferredQuality == StreamLinkPreferredQuality::Choose)
{
getStreamQualities(channelURL, [=](QStringList qualityOptions) {
QualityPopup::showDialog(channelURL, qualityOptions);
getStreamQualities(url, [=](QStringList qualityOptions) {
QualityPopup::showDialog(url, qualityOptions);
});
return;
@@ -249,7 +258,7 @@ void openStreamlinkForChannel(const QString &channel)
args << "--stream-sorting-excludes" << exclude;
}
openStreamlink(channelURL, quality, args);
openStreamlink(url, quality, args);
}
} // namespace chatterino
+4 -4
View File
@@ -24,14 +24,14 @@ constexpr inline QStringView STREAMLINK_BINARY_NAME = u"streamlink.exe";
constexpr inline QStringView STREAMLINK_BINARY_NAME = u"streamlink";
#endif
// Open streamlink for given channel, quality and extra arguments
// Open streamlink for given url, quality and extra arguments
// the "Additional arguments" are fetched and added at the beginning of the
// streamlink call
void openStreamlink(const QString &channelURL, const QString &quality,
void openStreamlink(const QString &url, const QString &quality,
QStringList extraArguments = QStringList());
// Start opening streamlink for the given channel, reading settings like quality
// Start opening streamlink for the given channel or url, reading settings like quality
// from settings and opening a quality dialog if the quality is "Choose"
void openStreamlinkForChannel(const QString &channel);
void openStreamlinkForChannelOrUrl(const QString &channelOrUrl);
} // namespace chatterino
+5 -5
View File
@@ -12,14 +12,14 @@
namespace chatterino {
QualityPopup::QualityPopup(const QString &channelURL, QStringList options)
QualityPopup::QualityPopup(const QString &url, QStringList options)
: BasePopup(
{
BaseWindow::DisableLayoutSave,
BaseWindow::BoundsCheckOnShow,
},
static_cast<QWidget *>(&(getApp()->getWindows()->getMainWindow())))
, channelURL_(channelURL)
, url_(url)
{
this->ui_.selector = new QComboBox(this);
this->ui_.vbox = new QVBoxLayout(this);
@@ -39,9 +39,9 @@ QualityPopup::QualityPopup(const QString &channelURL, QStringList options)
this->setLayout(this->ui_.vbox);
}
void QualityPopup::showDialog(const QString &channelURL, QStringList options)
void QualityPopup::showDialog(const QString &url, QStringList options)
{
QualityPopup *instance = new QualityPopup(channelURL, options);
QualityPopup *instance = new QualityPopup(url, options);
instance->window()->setWindowTitle("Chatterino - select stream quality");
instance->setAttribute(Qt::WA_DeleteOnClose, true);
@@ -69,7 +69,7 @@ void QualityPopup::okButtonClicked()
{
try
{
openStreamlink(this->channelURL_, this->ui_.selector->currentText());
openStreamlink(this->url_, this->ui_.selector->currentText());
}
catch (const Exception &ex)
{
+3 -3
View File
@@ -15,8 +15,8 @@ namespace chatterino {
class QualityPopup : public BasePopup
{
public:
QualityPopup(const QString &channelURL, QStringList options);
static void showDialog(const QString &channelURL, QStringList options);
QualityPopup(const QString &url, QStringList options);
static void showDialog(const QString &url, QStringList options);
protected:
void keyPressEvent(QKeyEvent *e) override;
@@ -31,7 +31,7 @@ private:
QDialogButtonBox *buttonBox;
} ui_{};
QString channelURL_;
QString url_;
};
} // namespace chatterino
+1 -1
View File
@@ -814,7 +814,7 @@ void Split::openChannelInStreamlink(const QString channelName)
{
try
{
openStreamlinkForChannel(channelName);
openStreamlinkForChannelOrUrl(channelName);
}
catch (const Exception &ex)
{