diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 01a1e7cf5..622bd3e5b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -4175,6 +4175,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_restricted_send_polls_all" = "Posting polls isn't allowed in this group."; "lng_restricted_send_public_polls" = "Sorry, public polls can't be forwarded to channels."; +"lng_restricted_send_paid_media" = "Sorry, paid media can't be sent to this channel."; "lng_restricted_send_voice_messages" = "{user} restricted sending of voice messages to them."; "lng_restricted_send_video_messages" = "{user} restricted sending of video messages to them."; diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index ea74b4d00..01ecb2b4d 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -47,6 +47,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/painter.h" #include "ui/vertical_list.h" #include "lottie/lottie_single_player.h" +#include "data/data_channel.h" #include "data/data_document.h" #include "data/data_user.h" #include "data/data_peer_values.h" // Data::AmPremiumValue. @@ -706,8 +707,11 @@ bool SendFilesBox::hasSpoilerMenu() const { bool SendFilesBox::canChangePrice() const { const auto way = _sendWay.current(); - return _captionToPeer - && _captionToPeer->isBroadcast() + const auto broadcast = _captionToPeer + ? _captionToPeer->asBroadcast() + : nullptr; + return broadcast + && broadcast->canPostPaidMedia() && _list.canChangePrice( way.groupFiles() && way.sendImagesAsPhotos(), way.sendImagesAsPhotos()); diff --git a/Telegram/SourceFiles/data/data_channel.cpp b/Telegram/SourceFiles/data/data_channel.cpp index 2ba8346d2..2f7694395 100644 --- a/Telegram/SourceFiles/data/data_channel.cpp +++ b/Telegram/SourceFiles/data/data_channel.cpp @@ -583,6 +583,10 @@ bool ChannelData::canDeleteStories() const { || (adminRights() & AdminRight::DeleteStories); } +bool ChannelData::canPostPaidMedia() const { + return canPostMessages() && (flags() & Flag::PaidMediaAllowed); +} + bool ChannelData::anyoneCanAddMembers() const { return !(defaultRestrictions() & Restriction::AddParticipants); } @@ -1084,7 +1088,8 @@ void ApplyChannelUpdate( | Flag::ParticipantsHidden | Flag::CanGetStatistics | Flag::ViewAsMessages - | Flag::CanViewRevenue; + | Flag::CanViewRevenue + | Flag::PaidMediaAllowed; channel->setFlags((channel->flags() & ~mask) | (update.is_can_set_username() ? Flag::CanSetUsername : Flag()) | (update.is_can_view_participants() @@ -1101,6 +1106,7 @@ void ApplyChannelUpdate( | (update.is_view_forum_as_messages() ? Flag::ViewAsMessages : Flag()) + | (update.is_paid_media_allowed() ? Flag::PaidMediaAllowed : Flag()) | (update.is_can_view_revenue() ? Flag::CanViewRevenue : Flag())); channel->setUserpicPhoto(update.vchat_photo()); if (const auto migratedFrom = update.vmigrated_from_chat_id()) { diff --git a/Telegram/SourceFiles/data/data_channel.h b/Telegram/SourceFiles/data/data_channel.h index 6dbe84329..d6f880bda 100644 --- a/Telegram/SourceFiles/data/data_channel.h +++ b/Telegram/SourceFiles/data/data_channel.h @@ -66,6 +66,7 @@ enum class ChannelDataFlag : uint64 { ViewAsMessages = (1ULL << 30), SimilarExpanded = (1ULL << 31), CanViewRevenue = (1ULL << 32), + PaidMediaAllowed = (1ULL << 33), }; inline constexpr bool is_flag_type(ChannelDataFlag) { return true; }; using ChannelDataFlags = base::flags; @@ -357,6 +358,7 @@ public: [[nodiscard]] bool canPostStories() const; [[nodiscard]] bool canEditStories() const; [[nodiscard]] bool canDeleteStories() const; + [[nodiscard]] bool canPostPaidMedia() const; [[nodiscard]] bool hiddenPreHistory() const; [[nodiscard]] bool canViewMembers() const; [[nodiscard]] bool canViewAdmins() const; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index 7203aceb1..d9c306013 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -2389,6 +2389,13 @@ std::optional HistoryItem::errorTextForForward( && _media->poll()->publicVotes() && peer->isBroadcast()) { return tr::lng_restricted_send_public_polls(tr::now); + } else if (_media + && _media->invoice() + && _media->invoice()->isPaidMedia + && peer->isBroadcast() + && peer->isFullLoaded() + && !peer->asBroadcast()->canPostPaidMedia()) { + return tr::lng_restricted_send_paid_media(tr::now); } else if (!Data::CanSend(to, requiredRight, false)) { return tr::lng_forward_cant(tr::now); } diff --git a/Telegram/SourceFiles/mtproto/scheme/api.tl b/Telegram/SourceFiles/mtproto/scheme/api.tl index f5e1ba2b3..91b310021 100644 --- a/Telegram/SourceFiles/mtproto/scheme/api.tl +++ b/Telegram/SourceFiles/mtproto/scheme/api.tl @@ -102,7 +102,7 @@ channel#aadfc8f flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5 channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat; chatFull#2633421b flags:# can_set_username:flags.7?true has_scheduled:flags.8?true translations_disabled:flags.19?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector available_reactions:flags.18?ChatReactions reactions_limit:flags.20?int = ChatFull; -channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull; +channelFull#bbab348d flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true flags2:# can_delete_channel:flags2.0?true antispam:flags2.1?true participants_hidden:flags2.2?true translations_disabled:flags2.3?true stories_pinned_available:flags2.5?true view_forum_as_messages:flags2.6?true restricted_sponsored:flags2.11?true can_view_revenue:flags2.12?true paid_media_allowed:flags2.14?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector default_send_as:flags.29?Peer available_reactions:flags.30?ChatReactions reactions_limit:flags2.13?int stories:flags2.4?PeerStories wallpaper:flags2.7?WallPaper boosts_applied:flags2.8?int boosts_unrestrict:flags2.9?int emojiset:flags2.10?StickerSet = ChatFull; chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant; chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant; @@ -763,7 +763,7 @@ auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeTyp auth.sentCodeTypeEmailCode#f450f59b flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true email_pattern:string length:int reset_available_period:flags.3?int reset_pending_date:flags.4?int = auth.SentCodeType; auth.sentCodeTypeSetUpEmailRequired#a5491dea flags:# apple_signin_allowed:flags.0?true google_signin_allowed:flags.1?true = auth.SentCodeType; auth.sentCodeTypeFragmentSms#d9565c39 url:string length:int = auth.SentCodeType; -auth.sentCodeTypeFirebaseSms#13c90f17 flags:# nonce:flags.0?bytes play_integrity_nonce:flags.2?bytes receipt:flags.1?string push_timeout:flags.1?int length:int = auth.SentCodeType; +auth.sentCodeTypeFirebaseSms#9fd736 flags:# nonce:flags.0?bytes play_integrity_project_id:flags.2?long play_integrity_nonce:flags.2?bytes receipt:flags.1?string push_timeout:flags.1?int length:int = auth.SentCodeType; auth.sentCodeTypeSmsWord#a416ac81 flags:# beginning:flags.0?string = auth.SentCodeType; auth.sentCodeTypeSmsPhrase#b37794af flags:# beginning:flags.0?string = auth.SentCodeType; @@ -1827,6 +1827,8 @@ payments.starsRevenueWithdrawalUrl#1dab80b7 url:string = payments.StarsRevenueWi payments.starsRevenueAdsAccountUrl#394e7f21 url:string = payments.StarsRevenueAdsAccountUrl; +inputStarsTransaction#206ae6d1 flags:# refund:flags.0?true id:string = InputStarsTransaction; + ---functions--- invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X; @@ -2375,6 +2377,7 @@ payments.refundStarsCharge#25ae8f4a user_id:InputUser charge_id:string = Updates payments.getStarsRevenueStats#d91ffad6 flags:# dark:flags.0?true peer:InputPeer = payments.StarsRevenueStats; payments.getStarsRevenueWithdrawalUrl#13bbe8b3 peer:InputPeer stars:long password:InputCheckPasswordSRP = payments.StarsRevenueWithdrawalUrl; payments.getStarsRevenueAdsAccountUrl#d1d7efc5 peer:InputPeer = payments.StarsRevenueAdsAccountUrl; +payments.getStarsTransactionsByID#27842d2e peer:InputPeer id:Vector = payments.StarsStatus; stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true emojis:flags.5?true text_color:flags.6?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector software:flags.3?string = messages.StickerSet; stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;