api_media.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /*
  2. This file is part of Telegram Desktop,
  3. the official desktop application for the Telegram messaging service.
  4. For license and copyright information please follow this link:
  5. https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
  6. */
  7. #include "api/api_media.h"
  8. #include "api/api_common.h"
  9. #include "data/data_document.h"
  10. #include "data/stickers/data_stickers_set.h"
  11. #include "history/history_item.h"
  12. namespace Api {
  13. namespace {
  14. MTPVector<MTPDocumentAttribute> ComposeSendingDocumentAttributes(
  15. not_null<DocumentData*> document) {
  16. const auto filenameAttribute = MTP_documentAttributeFilename(
  17. MTP_string(document->filename()));
  18. const auto dimensions = document->dimensions;
  19. auto attributes = QVector<MTPDocumentAttribute>(1, filenameAttribute);
  20. if (dimensions.width() > 0 && dimensions.height() > 0) {
  21. if (document->hasDuration() && !document->hasMimeType(u"image/gif"_q)) {
  22. auto flags = MTPDdocumentAttributeVideo::Flags(0);
  23. using VideoFlag = MTPDdocumentAttributeVideo::Flag;
  24. if (document->isVideoMessage()) {
  25. flags |= VideoFlag::f_round_message;
  26. }
  27. if (document->supportsStreaming()) {
  28. flags |= VideoFlag::f_supports_streaming;
  29. }
  30. attributes.push_back(MTP_documentAttributeVideo(
  31. MTP_flags(flags),
  32. MTP_double(document->duration() / 1000.),
  33. MTP_int(dimensions.width()),
  34. MTP_int(dimensions.height()),
  35. MTPint(), // preload_prefix_size
  36. MTPdouble(), // video_start_ts
  37. MTPstring())); // video_codec
  38. } else {
  39. attributes.push_back(MTP_documentAttributeImageSize(
  40. MTP_int(dimensions.width()),
  41. MTP_int(dimensions.height())));
  42. }
  43. }
  44. if (document->type == AnimatedDocument) {
  45. attributes.push_back(MTP_documentAttributeAnimated());
  46. } else if (document->type == StickerDocument && document->sticker()) {
  47. attributes.push_back(MTP_documentAttributeSticker(
  48. MTP_flags(0),
  49. MTP_string(document->sticker()->alt),
  50. Data::InputStickerSet(document->sticker()->set),
  51. MTPMaskCoords()));
  52. } else if (const auto song = document->song()) {
  53. const auto flags = MTPDdocumentAttributeAudio::Flag::f_title
  54. | MTPDdocumentAttributeAudio::Flag::f_performer;
  55. attributes.push_back(MTP_documentAttributeAudio(
  56. MTP_flags(flags),
  57. MTP_int(document->duration() / 1000),
  58. MTP_string(song->title),
  59. MTP_string(song->performer),
  60. MTPstring()));
  61. } else if (const auto voice = document->voice()) {
  62. const auto flags = MTPDdocumentAttributeAudio::Flag::f_voice
  63. | MTPDdocumentAttributeAudio::Flag::f_waveform;
  64. attributes.push_back(MTP_documentAttributeAudio(
  65. MTP_flags(flags),
  66. MTP_int(document->duration() / 1000),
  67. MTPstring(),
  68. MTPstring(),
  69. MTP_bytes(documentWaveformEncode5bit(voice->waveform))));
  70. }
  71. return MTP_vector<MTPDocumentAttribute>(attributes);
  72. }
  73. } // namespace
  74. MTPInputMedia PrepareUploadedPhoto(
  75. not_null<HistoryItem*> item,
  76. RemoteFileInfo info) {
  77. using Flag = MTPDinputMediaUploadedPhoto::Flag;
  78. const auto spoiler = item->media() && item->media()->hasSpoiler();
  79. const auto ttlSeconds = item->media()
  80. ? item->media()->ttlSeconds()
  81. : 0;
  82. const auto flags = (spoiler ? Flag::f_spoiler : Flag())
  83. | (info.attachedStickers.empty() ? Flag() : Flag::f_stickers)
  84. | (ttlSeconds ? Flag::f_ttl_seconds : Flag());
  85. return MTP_inputMediaUploadedPhoto(
  86. MTP_flags(flags),
  87. info.file,
  88. MTP_vector<MTPInputDocument>(
  89. ranges::to<QVector<MTPInputDocument>>(info.attachedStickers)),
  90. MTP_int(ttlSeconds));
  91. }
  92. MTPInputMedia PrepareUploadedDocument(
  93. not_null<HistoryItem*> item,
  94. RemoteFileInfo info) {
  95. if (!item || !item->media() || !item->media()->document()) {
  96. return MTP_inputMediaEmpty();
  97. }
  98. using Flag = MTPDinputMediaUploadedDocument::Flag;
  99. const auto spoiler = item->media() && item->media()->hasSpoiler();
  100. const auto ttlSeconds = item->media()
  101. ? item->media()->ttlSeconds()
  102. : 0;
  103. const auto flags = (spoiler ? Flag::f_spoiler : Flag())
  104. | (info.thumb ? Flag::f_thumb : Flag())
  105. | (item->groupId() ? Flag::f_nosound_video : Flag())
  106. | (info.attachedStickers.empty() ? Flag::f_stickers : Flag())
  107. | (ttlSeconds ? Flag::f_ttl_seconds : Flag())
  108. | (info.videoCover ? Flag::f_video_cover : Flag());
  109. const auto document = item->media()->document();
  110. return MTP_inputMediaUploadedDocument(
  111. MTP_flags(flags),
  112. info.file,
  113. info.thumb.value_or(MTPInputFile()),
  114. MTP_string(document->mimeString()),
  115. ComposeSendingDocumentAttributes(document),
  116. MTP_vector<MTPInputDocument>(
  117. ranges::to<QVector<MTPInputDocument>>(info.attachedStickers)),
  118. info.videoCover.value_or(MTPInputPhoto()),
  119. MTP_int(0), // video_timestamp
  120. MTP_int(ttlSeconds));
  121. }
  122. bool HasAttachedStickers(MTPInputMedia media) {
  123. return media.match([&](const MTPDinputMediaUploadedPhoto &photo) -> bool {
  124. return (photo.vflags().v
  125. & MTPDinputMediaUploadedPhoto::Flag::f_stickers);
  126. }, [&](const MTPDinputMediaUploadedDocument &document) -> bool {
  127. return (document.vflags().v
  128. & MTPDinputMediaUploadedDocument::Flag::f_stickers);
  129. }, [](const auto &d) {
  130. return false;
  131. });
  132. }
  133. } // namespace Api