diff --git a/src/immichclient.cpp b/src/immichclient.cpp index c2fac3f..6974c1d 100644 --- a/src/immichclient.cpp +++ b/src/immichclient.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -17,6 +19,20 @@ namespace { const int kMetadataTimeoutMs = 15000; const int kAssetTimeoutMs = 30000; +QString DetectImageExtension(const QByteArray &data) +{ + QBuffer buffer; + buffer.setData(data); + if (!buffer.open(QIODevice::ReadOnly)) + return ""; + QImageReader reader(&buffer); + if (!reader.canRead()) + return ""; + QByteArray fmt = reader.format().toLower(); + if (fmt == "jpeg") + fmt = "jpg"; + return QString::fromUtf8(fmt); +} } ImmichClient::ImmichClient(const ImmichConfig &configIn) @@ -356,6 +372,11 @@ QString ImmichAssetCache::findExisting(const QString &assetId) const QStringList matches = dir.entryList(QStringList() << (assetId + "_*"), QDir::Files, QDir::Time); if (matches.isEmpty()) return ""; + for (const auto &match : matches) + { + if (match.endsWith(".skip")) + return dir.filePath(match); + } return dir.filePath(matches.first()); } @@ -418,8 +439,35 @@ QString ImmichAssetCache::getCachedPath(const QString &assetId, const QString &a QString existing = findExisting(assetId); if (!existing.isEmpty()) { - Log("Immich cache hit: ", assetId.toStdString()); - return existing; + if (existing.endsWith(".skip")) + { + Log("Immich skip marker: ", assetId.toStdString()); + return ""; + } + QFileInfo info(existing); + if (info.size() <= 0) + { + QFile::remove(existing); + } + else if (existing.endsWith(".img")) + { + QImageReader reader(existing); + if (!reader.canRead()) + { + Log("Immich cache invalid: ", existing.toStdString()); + QFile::remove(existing); + } + else + { + Log("Immich cache hit: ", assetId.toStdString()); + return existing; + } + } + else + { + Log("Immich cache hit: ", assetId.toStdString()); + return existing; + } } QByteArray data; @@ -427,8 +475,31 @@ QString ImmichAssetCache::getCachedPath(const QString &assetId, const QString &a if (!client.downloadAsset(assetId, data, contentType)) return ""; + QString detectedExt = DetectImageExtension(data); + if (detectedExt.isEmpty()) + { + Log("Immich download not an image for asset: ", assetId.toStdString()); + QString skipName = assetId + "_unsupported.skip"; + QDir dir(cacheDirPath); + QFile skipFile(dir.filePath(skipName)); + if (skipFile.open(QIODevice::WriteOnly)) + { + skipFile.write("unsupported"); + skipFile.close(); + } + return ""; + } + QString safeName = sanitizeFileName(assetName); - QString extension = extensionForContentType(contentType); + QString extension = detectedExt; + if (extension.isEmpty()) + extension = extensionForContentType(contentType); + if (extension == "img") + { + QString suffix = QFileInfo(assetName).suffix().toLower(); + if (!suffix.isEmpty()) + extension = suffix; + } QString filename = assetId + "_" + safeName + "." + extension; QDir dir(cacheDirPath);