fix: image uploader setting import (#6387)
Co-authored-by: Rasmus Karlsson <rasmus.karlsson@pajlada.com>
This commit is contained in:
+1
-1
@@ -20,7 +20,7 @@
|
||||
- Minor: Made commands searchable using the Settings dialog search bar. (#5891)
|
||||
- Minor: Added hotkey Action for opening account selector. (#6192)
|
||||
- Minor: Add a setting to change the emote and badge thumbnail size. (#6126)
|
||||
- Minor: Add an import and export button to image uploader settings. (#6284, #6394)
|
||||
- Minor: Add an import and export button to image uploader settings. (#6284, #6394, #6387)
|
||||
- Minor: Message character length label is now monospaced. (#6366)
|
||||
- Minor: Add a setting under Moderation -> Logs to customize the timestamp used for chat logs. (#6338)
|
||||
- Minor: Add a setting under Moderation -> Logs to use server timestamp from the message instead of the local clock time for logging. (#6346)
|
||||
|
||||
@@ -4,11 +4,68 @@
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QRegularExpression>
|
||||
|
||||
namespace chatterino::imageuploader::detail {
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* @brief Converts ShareX-style tokens throughout the URL to the expected format.
|
||||
*
|
||||
* Examples:
|
||||
* - https://example.com/{json:foo.bar[1]}/{json:foo.bar[2]}
|
||||
* -> https://example.com/{foo.bar.1}/{foo.bar.2}
|
||||
* - {json:{response}|foo.bar[1]}
|
||||
* -> {foo.bar.1}
|
||||
*
|
||||
* @see https://github.com/ShareX/ShareX/blob/8c0fac3bdf6c6ecb9756584096332175f290072c/ShareX.UploadersLib/CustomUploader/ShareXSyntaxParser.cs
|
||||
* @see https://github.com/ShareX/ShareX/blob/8c0fac3bdf6c6ecb9756584096332175f290072c/ShareX.UploadersLib/CustomUploader/Functions/CustomUploaderFunctionJson.cs
|
||||
*/
|
||||
QString parseUrl(const QString &url)
|
||||
{
|
||||
if (url.isEmpty() || url.compare("{response}", Qt::CaseInsensitive) == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
static const QRegularExpression tokenRegex(
|
||||
R"(\{json:([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}*)",
|
||||
QRegularExpression::CaseInsensitiveOption);
|
||||
static const QRegularExpression arrayRegex(R"(\[(\d+)\])");
|
||||
|
||||
QString out;
|
||||
qsizetype last = 0;
|
||||
bool changed = false;
|
||||
|
||||
auto it = tokenRegex.globalMatch(url);
|
||||
while (it.hasNext())
|
||||
{
|
||||
auto match = it.next();
|
||||
|
||||
out += url.mid(last, match.capturedStart() - last);
|
||||
|
||||
QString inner = match.captured(1).trimmed();
|
||||
|
||||
// Split by last '|' to support {json:input|jsonPath}
|
||||
// We assume that the preceding parameter was `{response}` as other ShareX functions are not supported
|
||||
qsizetype pipeIndex = inner.lastIndexOf('|');
|
||||
if (pipeIndex != -1)
|
||||
{
|
||||
inner = inner.mid(pipeIndex + 1).trimmed();
|
||||
}
|
||||
|
||||
inner.replace(arrayRegex, R"(.\1)");
|
||||
|
||||
out += '{' + inner + '}';
|
||||
last = match.capturedEnd();
|
||||
changed = true;
|
||||
}
|
||||
|
||||
out += url.mid(last);
|
||||
return changed ? out : QString(url);
|
||||
}
|
||||
|
||||
QStringList parseHeaders(const QJsonObject &headersObj)
|
||||
{
|
||||
QStringList headerLines;
|
||||
@@ -41,7 +98,7 @@ QJsonObject exportSettings(const Settings &s)
|
||||
if (!headers.isEmpty())
|
||||
{
|
||||
QJsonObject headersObj;
|
||||
QStringList headerLines = headers.split('\n', Qt::SkipEmptyParts);
|
||||
QStringList headerLines = headers.split(';', Qt::SkipEmptyParts);
|
||||
for (const QString &line : headerLines)
|
||||
{
|
||||
QStringList parts = line.split(':', Qt::SkipEmptyParts);
|
||||
@@ -74,12 +131,13 @@ bool importSettings(const QJsonObject &settingsObj, Settings &s)
|
||||
|
||||
s.imageUploaderUrl = settingsObj["RequestURL"].toString();
|
||||
s.imageUploaderFormField = settingsObj["FileFormName"].toString();
|
||||
s.imageUploaderLink = settingsObj["URL"].toString();
|
||||
s.imageUploaderLink = parseUrl(settingsObj["URL"].toString());
|
||||
|
||||
if (settingsObj.contains("DeletionURL") &&
|
||||
settingsObj["DeletionURL"].isString())
|
||||
{
|
||||
s.imageUploaderDeletionLink = settingsObj["DeletionURL"].toString();
|
||||
s.imageUploaderDeletionLink =
|
||||
parseUrl(settingsObj["DeletionURL"].toString());
|
||||
}
|
||||
|
||||
if (settingsObj.contains("Headers") && settingsObj["Headers"].isObject())
|
||||
@@ -87,7 +145,7 @@ bool importSettings(const QJsonObject &settingsObj, Settings &s)
|
||||
QStringList headers = parseHeaders(settingsObj["Headers"].toObject());
|
||||
if (!headers.isEmpty())
|
||||
{
|
||||
s.imageUploaderHeaders = headers.join('\n');
|
||||
s.imageUploaderHeaders = headers.join(';');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,9 +182,10 @@ ExpectedStr<QJsonObject> validateImportJson(const QString &clipboardText)
|
||||
return nonstd::make_unexpected("JSON must contain the 'Version' key");
|
||||
}
|
||||
|
||||
if (!settingsObj.contains("Name"))
|
||||
if (!settingsObj.contains("RequestURL"))
|
||||
{
|
||||
return nonstd::make_unexpected("JSON must contain the 'Name' key");
|
||||
return nonstd::make_unexpected(
|
||||
"JSON must contain the 'RequestURL' key");
|
||||
}
|
||||
|
||||
return settingsObj;
|
||||
|
||||
@@ -11,8 +11,9 @@
|
||||
"DeletionURL": "{more}",
|
||||
"FileFormName": "file",
|
||||
"Headers": {
|
||||
"My-Header": "Foo ; Bar : Baz ; KeyOnly",
|
||||
"X-My-Header": "1"
|
||||
"Bar": "Baz",
|
||||
"KeyOnly\nX-My-Header": "1",
|
||||
"My-Header": "Foo"
|
||||
},
|
||||
"Name": "Chatterino Image Uploader Settings",
|
||||
"RequestMethod": "POST",
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"input": {
|
||||
"Body": "MultipartFormData",
|
||||
"DeletionURL": "{json:delete}",
|
||||
"DestinationType": "ImageUploader, FileUploader",
|
||||
"ErrorMessage": "{json:message}",
|
||||
"FileFormName": "file",
|
||||
"Headers": {
|
||||
"X-bing": "bong",
|
||||
"X-foo": "bar"
|
||||
},
|
||||
"Parameters": {
|
||||
"urlfoo": "urlbar"
|
||||
},
|
||||
"RequestMethod": "POST",
|
||||
"RequestURL": "https://kappa.lol/api/upload",
|
||||
"URL": "{json:link}",
|
||||
"Version": "14.0.1"
|
||||
},
|
||||
"output": {
|
||||
"deletionLink": "{delete}",
|
||||
"formField": "file",
|
||||
"headers": "X-bing: bong;X-foo: bar",
|
||||
"link": "{link}",
|
||||
"url": "https://kappa.lol/api/upload"
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@
|
||||
"output": {
|
||||
"deletionLink": "{more}",
|
||||
"formField": "file",
|
||||
"headers": "Another: header\nMy-Header: Foo ; Bar : Baz ; KeyOnly\nX-My-Header: 1",
|
||||
"headers": "Another: header;My-Header: Foo ; Bar : Baz ; KeyOnly;X-My-Header: 1",
|
||||
"link": "foo{bar}baz",
|
||||
"url": "https://example.com"
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"input": {
|
||||
"Body": "MultipartFormData",
|
||||
"DeletionURL": "{json:delete}",
|
||||
"DestinationType": "ImageUploader, FileUploader",
|
||||
"ErrorMessage": "{json:message}",
|
||||
"FileFormName": "file",
|
||||
"Headers": {
|
||||
"X-bing": "bong",
|
||||
"X-foo": "bar"
|
||||
},
|
||||
"Parameters": {
|
||||
"urlfoo": "urlbar"
|
||||
},
|
||||
"RequestMethod": "POST",
|
||||
"RequestURL": "https://kappa.lol/api/upload",
|
||||
"URL": "{json:files[0].url}",
|
||||
"Version": "14.0.1"
|
||||
},
|
||||
"output": {
|
||||
"deletionLink": "{delete}",
|
||||
"formField": "file",
|
||||
"headers": "X-bing: bong;X-foo: bar",
|
||||
"link": "{files.0.url}",
|
||||
"url": "https://kappa.lol/api/upload"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"input": {
|
||||
"Body": "MultipartFormData",
|
||||
"DeletionURL": "{json:delete}",
|
||||
"DestinationType": "ImageUploader, FileUploader",
|
||||
"ErrorMessage": "{json:message}",
|
||||
"FileFormName": "file",
|
||||
"Headers": {
|
||||
"X-bing": "bong",
|
||||
"X-foo": "bar"
|
||||
},
|
||||
"Parameters": {
|
||||
"urlfoo": "urlbar"
|
||||
},
|
||||
"RequestMethod": "POST",
|
||||
"RequestURL": "https://kappa.lol/api/upload",
|
||||
"URL": "{json:response|}",
|
||||
"Version": "14.0.1"
|
||||
},
|
||||
"output": {
|
||||
"deletionLink": "{delete}",
|
||||
"formField": "file",
|
||||
"headers": "X-bing: bong;X-foo: bar",
|
||||
"link": "{}",
|
||||
"url": "https://kappa.lol/api/upload"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"input": {
|
||||
"Body": "MultipartFormData",
|
||||
"DeletionURL": "{json:delete}",
|
||||
"DestinationType": "ImageUploader, FileUploader",
|
||||
"ErrorMessage": "{json:message}",
|
||||
"FileFormName": "file",
|
||||
"Headers": {
|
||||
"X-bing": "bong",
|
||||
"X-foo": "bar"
|
||||
},
|
||||
"Parameters": {
|
||||
"urlfoo": "urlbar"
|
||||
},
|
||||
"RequestMethod": "POST",
|
||||
"RequestURL": "https://kappa.lol/api/upload",
|
||||
"URL": "{json:response|files[0].url}",
|
||||
"Version": "14.0.1"
|
||||
},
|
||||
"output": {
|
||||
"deletionLink": "{delete}",
|
||||
"formField": "file",
|
||||
"headers": "X-bing: bong;X-foo: bar",
|
||||
"link": "{files.0.url}",
|
||||
"url": "https://kappa.lol/api/upload"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user