diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 67ac6f187..e44fb61bd 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -135,6 +135,8 @@ PRIVATE api/api_peer_photo.h api/api_polls.cpp api/api_polls.h + api/api_ringtones.cpp + api/api_ringtones.h api/api_self_destruct.cpp api/api_self_destruct.h api/api_send_progress.cpp diff --git a/Telegram/SourceFiles/api/api_ringtones.cpp b/Telegram/SourceFiles/api/api_ringtones.cpp new file mode 100644 index 000000000..3ead9ee41 --- /dev/null +++ b/Telegram/SourceFiles/api/api_ringtones.cpp @@ -0,0 +1,119 @@ +/* +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 "api/api_ringtones.h" + +#include "apiwrap.h" +#include "base/random.h" +#include "base/unixtime.h" +#include "data/data_session.h" +#include "main/main_session.h" +#include "storage/file_upload.h" +#include "storage/localimageloader.h" + +namespace Api { +namespace { + +SendMediaReady PrepareRingtoneDocument( + MTP::DcId dcId, + const QString &filename, + const QString &filemime, + const QByteArray &content) { + auto attributes = QVector<MTPDocumentAttribute>( + 1, + MTP_documentAttributeFilename(MTP_string(filename))); + const auto id = base::RandomValue<DocumentId>(); + const auto document = MTP_document( + MTP_flags(0), + MTP_long(id), + MTP_long(0), + MTP_bytes(), + MTP_int(base::unixtime::now()), + MTP_string(filemime), + MTP_int(content.size()), + MTP_vector<MTPPhotoSize>(), + MTPVector<MTPVideoSize>(), + MTP_int(dcId), + MTP_vector<MTPDocumentAttribute>(std::move(attributes))); + + return SendMediaReady( + SendMediaType::File, + QString(), // filepath + filename, + content.size(), + content, + id, + 0, + QString(), + PeerId(), + MTP_photoEmpty(MTP_long(0)), + PreparedPhotoThumbs(), + document, + QByteArray(), + 0); +} + +} // namespace + +Ringtones::Ringtones(not_null<ApiWrap*> api) +: _session(&api->session()) +, _api(&api->instance()) { + crl::on_main(_session, [=] { + // You can't use _session->lifetime() in the constructor, + // only queued, because it is not constructed yet. + _session->uploader().documentReady( + ) | rpl::start_with_next([=](const Storage::UploadedMedia &data) { + ready(data.fullId, data.info.file); + }, _session->lifetime()); + }); +} + +void Ringtones::upload( + const QString &filename, + const QString &filemime, + const QByteArray &content) { + const auto ready = PrepareRingtoneDocument( + _api.instance().mainDcId(), + filename, + filemime, + content); + + const auto uploadedData = UploadedData{ filename, filemime }; + const auto fakeId = FullMsgId( + _session->userPeerId(), + _session->data().nextLocalMessageId()); + const auto already = ranges::find_if( + _uploads, + [&](const auto &d) { + return uploadedData.filemime == d.second.filemime + && uploadedData.filename == d.second.filename; + }); + if (already != end(_uploads)) { + _session->uploader().cancel(already->first); + _uploads.erase(already); + } + _uploads.emplace(fakeId, uploadedData); + _session->uploader().uploadMedia(fakeId, ready); +} + +void Ringtones::ready(const FullMsgId &msgId, const MTPInputFile &file) { + const auto maybeUploadedData = _uploads.take(msgId); + if (!maybeUploadedData) { + return; + } + const auto uploadedData = *maybeUploadedData; + _api.request(MTPaccount_UploadRingtone( + file, + MTP_string(uploadedData.filename), + MTP_string(uploadedData.filemime) + )).done([=](const MTPDocument &result) { + _session->data().processDocument(result); + }).fail([](const MTP::Error &error) { + }).send(); +} + +} // namespace Api diff --git a/Telegram/SourceFiles/api/api_ringtones.h b/Telegram/SourceFiles/api/api_ringtones.h new file mode 100644 index 000000000..1bf828c96 --- /dev/null +++ b/Telegram/SourceFiles/api/api_ringtones.h @@ -0,0 +1,44 @@ +/* +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 + +#include "mtproto/sender.h" + +class ApiWrap; +class PeerData; + +namespace Main { +class Session; +} // namespace Main + +namespace Api { + +class Ringtones final { +public: + explicit Ringtones(not_null<ApiWrap*> api); + + void upload( + const QString &filename, + const QString &filemime, + const QByteArray &content); + +private: + struct UploadedData { + QString filename; + QString filemime; + }; + void ready(const FullMsgId &msgId, const MTPInputFile &file); + + const not_null<Main::Session*> _session; + MTP::Sender _api; + + base::flat_map<FullMsgId, UploadedData> _uploads; + +}; + +} // namespace Api diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index 9265e809d..64f219445 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_views.h" #include "api/api_confirm_phone.h" #include "api/api_unread_things.h" +#include "api/api_ringtones.h" #include "data/notify/data_notify_settings.h" #include "data/stickers/data_stickers.h" #include "data/data_drafts.h" @@ -141,7 +142,8 @@ ApiWrap::ApiWrap(not_null<Main::Session*> session) , _peerPhoto(std::make_unique<Api::PeerPhoto>(this)) , _polls(std::make_unique<Api::Polls>(this)) , _chatParticipants(std::make_unique<Api::ChatParticipants>(this)) -, _unreadThings(std::make_unique<Api::UnreadThings>(this)) { +, _unreadThings(std::make_unique<Api::UnreadThings>(this)) +, _ringtones(std::make_unique<Api::Ringtones>(this)) { crl::on_main(session, [=] { // You can't use _session->lifetime() in the constructor, // only queued, because it is not constructed yet. @@ -4066,3 +4068,7 @@ Api::ChatParticipants &ApiWrap::chatParticipants() { Api::UnreadThings &ApiWrap::unreadThings() { return *_unreadThings; } + +Api::Ringtones &ApiWrap::ringtones() { + return *_ringtones; +} diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 93870829d..7535336ba 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -68,6 +68,7 @@ class PeerPhoto; class Polls; class ChatParticipants; class UnreadThings; +class Ringtones; namespace details { @@ -357,6 +358,7 @@ public: [[nodiscard]] Api::Polls &polls(); [[nodiscard]] Api::ChatParticipants &chatParticipants(); [[nodiscard]] Api::UnreadThings &unreadThings(); + [[nodiscard]] Api::Ringtones &ringtones(); void updatePrivacyLastSeens(); @@ -638,6 +640,7 @@ private: const std::unique_ptr<Api::Polls> _polls; const std::unique_ptr<Api::ChatParticipants> _chatParticipants; const std::unique_ptr<Api::UnreadThings> _unreadThings; + const std::unique_ptr<Api::Ringtones> _ringtones; mtpRequestId _wallPaperRequestId = 0; QString _wallPaperSlug;