mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-08 08:04:08 +02:00
Added ability to fetch song cover from external resource.
This commit is contained in:
parent
3fadf2ee54
commit
ad761011d6
4 changed files with 177 additions and 0 deletions
|
@ -961,6 +961,8 @@ PRIVATE
|
||||||
storage/storage_account.h
|
storage/storage_account.h
|
||||||
storage/storage_cloud_blob.cpp
|
storage/storage_cloud_blob.cpp
|
||||||
storage/storage_cloud_blob.h
|
storage/storage_cloud_blob.h
|
||||||
|
storage/storage_cloud_song_cover.cpp
|
||||||
|
storage/storage_cloud_song_cover.h
|
||||||
storage/storage_domain.cpp
|
storage/storage_domain.cpp
|
||||||
storage/storage_domain.h
|
storage/storage_domain.h
|
||||||
storage/storage_facade.cpp
|
storage/storage_facade.cpp
|
||||||
|
|
|
@ -36,6 +36,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "history/view/media/history_view_gif.h"
|
#include "history/view/media/history_view_gif.h"
|
||||||
#include "window/window_session_controller.h"
|
#include "window/window_session_controller.h"
|
||||||
#include "storage/cache/storage_cache_database.h"
|
#include "storage/cache/storage_cache_database.h"
|
||||||
|
#include "storage/storage_cloud_song_cover.h"
|
||||||
#include "boxes/confirm_box.h"
|
#include "boxes/confirm_box.h"
|
||||||
#include "ui/image/image.h"
|
#include "ui/image/image.h"
|
||||||
#include "ui/text/text_utilities.h"
|
#include "ui/text/text_utilities.h"
|
||||||
|
@ -540,6 +541,13 @@ void DocumentData::setattributes(
|
||||||
songData->duration = data.vduration().v;
|
songData->duration = data.vduration().v;
|
||||||
songData->title = qs(data.vtitle().value_or_empty());
|
songData->title = qs(data.vtitle().value_or_empty());
|
||||||
songData->performer = qs(data.vperformer().value_or_empty());
|
songData->performer = qs(data.vperformer().value_or_empty());
|
||||||
|
|
||||||
|
if (!hasThumbnail()
|
||||||
|
&& !songData->title.isEmpty()
|
||||||
|
&& !songData->performer.isEmpty()) {
|
||||||
|
|
||||||
|
Storage::CloudSongCover::LoadThumbnailFromExternal(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, [&](const MTPDdocumentAttributeFilename &data) {
|
}, [&](const MTPDdocumentAttributeFilename &data) {
|
||||||
_filename = qs(data.vfile_name());
|
_filename = qs(data.vfile_name());
|
||||||
|
|
151
Telegram/SourceFiles/storage/storage_cloud_song_cover.cpp
Normal file
151
Telegram/SourceFiles/storage/storage_cloud_song_cover.cpp
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#include "storage/storage_cloud_song_cover.h"
|
||||||
|
|
||||||
|
#include "data/data_cloud_file.h"
|
||||||
|
#include "data/data_document.h"
|
||||||
|
#include "data/data_file_origin.h"
|
||||||
|
#include "data/data_session.h"
|
||||||
|
#include "main/main_session.h"
|
||||||
|
#include "storage/file_download.h"
|
||||||
|
|
||||||
|
#include <QtCore/QJsonArray>
|
||||||
|
#include <QtCore/QJsonDocument>
|
||||||
|
#include <QtCore/QJsonObject>
|
||||||
|
#include <QtCore/QJsonValue>
|
||||||
|
|
||||||
|
namespace Storage::CloudSongCover {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
constexpr auto kMaxResponseSize = 1024 * 1024;
|
||||||
|
constexpr auto kDefaultCoverSize = 100;
|
||||||
|
|
||||||
|
struct Responce {
|
||||||
|
const QString artworkUrl;
|
||||||
|
const int size;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto Location(const QString &url) {
|
||||||
|
return DownloadLocation{ PlainUrlLocation{ url } };
|
||||||
|
}
|
||||||
|
|
||||||
|
auto JsonUrl(not_null<SongData*> song) {
|
||||||
|
return QString("https://itunes.apple.com/search?term=" \
|
||||||
|
"%1 %2&entity=song&limit=4").arg(song->performer).arg(song->title);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dummy JSON responce.
|
||||||
|
// {
|
||||||
|
// "resultCount": 2,
|
||||||
|
// "results": [
|
||||||
|
// {
|
||||||
|
// "artworkUrl100": ""
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "artworkUrl100": ""
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
|
||||||
|
std::optional<Responce> ParseResponce(const QByteArray &response) {
|
||||||
|
if (response.size() >= kMaxResponseSize) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
|
||||||
|
const auto document = QJsonDocument::fromJson(response, &error);
|
||||||
|
|
||||||
|
const auto log = [](const QString &message) {
|
||||||
|
DEBUG_LOG(("Parse Artwork JSON Error: %1.").arg(message));
|
||||||
|
};
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
log(error.errorString());
|
||||||
|
return std::nullopt;
|
||||||
|
} else if (!document.isObject()) {
|
||||||
|
log("not an object received in JSON");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto results = document.object().value("results");
|
||||||
|
if (!results.isArray()) {
|
||||||
|
log("'results' field not found");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto resultsArray = results.toArray();
|
||||||
|
if (resultsArray.empty()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
const auto artworkUrl = resultsArray.first().toObject()
|
||||||
|
.value("artworkUrl100").toString();
|
||||||
|
if (artworkUrl.isEmpty()) {
|
||||||
|
log("'artworkUrl100' field is empty");
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Responce{ artworkUrl, kDefaultCoverSize };
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadAndApplyThumbnail(
|
||||||
|
not_null<DocumentData*> document,
|
||||||
|
const Responce &responce) {
|
||||||
|
const auto size = responce.size;
|
||||||
|
const auto imageWithLocation = ImageWithLocation{
|
||||||
|
.location = ImageLocation(Location(responce.artworkUrl), size, size)
|
||||||
|
};
|
||||||
|
|
||||||
|
document->updateThumbnails(
|
||||||
|
QByteArray(),
|
||||||
|
imageWithLocation,
|
||||||
|
ImageWithLocation{ .location = ImageLocation() });
|
||||||
|
|
||||||
|
document->loadThumbnail(Data::FileOrigin());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadThumbnailFromExternal(not_null<DocumentData*> document) {
|
||||||
|
const auto songData = document->song();
|
||||||
|
if (!songData
|
||||||
|
|| songData->performer.isEmpty()
|
||||||
|
|| songData->title.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &size = kDefaultCoverSize;
|
||||||
|
const auto jsonLocation = ImageWithLocation{
|
||||||
|
.location = ImageLocation(Location(JsonUrl(songData)), size, size)
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto jsonCloudFile = std::make_shared<Data::CloudFile>();
|
||||||
|
Data::UpdateCloudFile(
|
||||||
|
*jsonCloudFile,
|
||||||
|
jsonLocation,
|
||||||
|
document->owner().cache(),
|
||||||
|
0, // Cache tag.
|
||||||
|
nullptr,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
auto done = [=](const QByteArray &result) {
|
||||||
|
if (!jsonCloudFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (const auto responce = ParseResponce(result)) {
|
||||||
|
LoadAndApplyThumbnail(document, *responce);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Data::LoadCloudFile(
|
||||||
|
&document->session(),
|
||||||
|
*jsonCloudFile,
|
||||||
|
Data::FileOrigin(),
|
||||||
|
LoadFromCloudOrLocal,
|
||||||
|
true,
|
||||||
|
0,
|
||||||
|
[] { return true; },
|
||||||
|
std::move(done));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Storage::CloudSongCover
|
16
Telegram/SourceFiles/storage/storage_cloud_song_cover.h
Normal file
16
Telegram/SourceFiles/storage/storage_cloud_song_cover.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/*
|
||||||
|
This file is part of Telegram Desktop,
|
||||||
|
the official desktop application for the Telegram messaging service.
|
||||||
|
|
||||||
|
For license and copyright information please follow this link:
|
||||||
|
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
class DocumentData;
|
||||||
|
|
||||||
|
namespace Storage::CloudSongCover {
|
||||||
|
|
||||||
|
void LoadThumbnailFromExternal(not_null<DocumentData*> document);
|
||||||
|
|
||||||
|
} // namespace Storage::CloudSongCover
|
Loading…
Add table
Reference in a new issue