133 lines
3.2 KiB
C++
133 lines
3.2 KiB
C++
#include "Types.h"
|
|
|
|
#include <QJsonArray>
|
|
#include <QSet>
|
|
#include <QStringList>
|
|
|
|
using namespace Qt::StringLiterals;
|
|
|
|
ShareEndpoint ShareEndpoint::fromUserInput(const QString &input, const QString &password, QString *error)
|
|
{
|
|
ShareEndpoint result;
|
|
const QUrl url = QUrl::fromUserInput(input.trimmed());
|
|
if (!url.isValid() || (url.scheme() != u"http" && url.scheme() != u"https") || url.host().isEmpty())
|
|
{
|
|
if (error)
|
|
{
|
|
*error = u"Enter a valid HTTP or HTTPS Immich share URL."_s;
|
|
}
|
|
return result;
|
|
}
|
|
if (!url.userInfo().isEmpty())
|
|
{
|
|
if (error)
|
|
{
|
|
*error = u"Credentials in the URL are not supported."_s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const QString path = url.path();
|
|
const qsizetype marker = path.lastIndexOf(u"/share/"_s);
|
|
if (marker < 0)
|
|
{
|
|
if (error)
|
|
{
|
|
*error = u"The URL must contain /share/<key-or-slug>."_s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QString credential = path.sliced(marker + 7);
|
|
while (credential.endsWith(u'/'))
|
|
{
|
|
credential.chop(1);
|
|
}
|
|
if (credential.isEmpty() || credential.contains(u'/'))
|
|
{
|
|
if (error)
|
|
{
|
|
*error = u"The share key or slug is missing or malformed."_s;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QUrl cleanUrl = url;
|
|
cleanUrl.setQuery({});
|
|
cleanUrl.setFragment({});
|
|
|
|
QUrl root = cleanUrl;
|
|
root.setPath(path.first(marker) + u"/api"_s);
|
|
|
|
result.publicUrl = cleanUrl;
|
|
result.apiRoot = root;
|
|
result.credential = credential;
|
|
result.password = password;
|
|
if (error)
|
|
{
|
|
error->clear();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QString ShareEndpoint::origin() const
|
|
{
|
|
QString value = publicUrl.scheme() + u"://"_s + publicUrl.host();
|
|
if (publicUrl.port() > 0)
|
|
{
|
|
value += u":"_s + QString::number(publicUrl.port());
|
|
}
|
|
return value;
|
|
}
|
|
|
|
SyncPlan buildSyncPlan(const ShareInfo &left, const ShareInfo &right)
|
|
{
|
|
QSet<QString> leftChecksums;
|
|
QSet<QString> rightChecksums;
|
|
for (const auto &asset : left.assets)
|
|
{
|
|
if (!asset.checksum.isEmpty())
|
|
{
|
|
leftChecksums.insert(asset.checksum);
|
|
}
|
|
}
|
|
for (const auto &asset : right.assets)
|
|
{
|
|
if (!asset.checksum.isEmpty())
|
|
{
|
|
rightChecksums.insert(asset.checksum);
|
|
}
|
|
}
|
|
|
|
SyncPlan plan;
|
|
for (const auto &asset : left.assets)
|
|
{
|
|
if (!asset.checksum.isEmpty() && !rightChecksums.contains(asset.checksum))
|
|
{
|
|
plan.leftToRight.append(asset);
|
|
}
|
|
}
|
|
for (const auto &asset : right.assets)
|
|
{
|
|
if (!asset.checksum.isEmpty() && !leftChecksums.contains(asset.checksum))
|
|
{
|
|
plan.rightToLeft.append(asset);
|
|
}
|
|
}
|
|
return plan;
|
|
}
|
|
|
|
QJsonObject shareInfoJson(const ShareEndpoint &endpoint, const ShareInfo &info)
|
|
{
|
|
return {
|
|
{u"origin"_s, endpoint.origin()},
|
|
{u"name"_s, info.name},
|
|
{u"description"_s, info.description},
|
|
{u"type"_s, info.type},
|
|
{u"allowDownload"_s, info.allowDownload},
|
|
{u"allowUpload"_s, info.allowUpload},
|
|
{u"passwordProtected"_s, info.passwordProtected},
|
|
{u"assetCount"_s, static_cast<qint64>(info.assets.size())},
|
|
};
|
|
}
|