diff --git a/ext/handlers/filters/purchasedpaidmedia/purchasedpaidmedia.go b/ext/handlers/filters/purchasedpaidmedia/purchasedpaidmedia.go new file mode 100644 index 0000000..2ce9a36 --- /dev/null +++ b/ext/handlers/filters/purchasedpaidmedia/purchasedpaidmedia.go @@ -0,0 +1,24 @@ +package purchasedpaidmedia + +import ( + "strings" + + "github.com/PaulSonOfLars/gotgbot/v2" + "github.com/PaulSonOfLars/gotgbot/v2/ext/handlers/filters" +) + +func All(_ *gotgbot.PaidMediaPurchased) bool { + return true +} + +func FromUserID(id int64) filters.PurchasedPaidMedia { + return func(s *gotgbot.PaidMediaPurchased) bool { + return s.From.Id == id + } +} + +func HasPayloadPrefix(pre string) filters.PurchasedPaidMedia { + return func(s *gotgbot.PaidMediaPurchased) bool { + return strings.HasPrefix(s.PaidMediaPayload, pre) + } +} diff --git a/ext/handlers/filters/types.go b/ext/handlers/filters/types.go index 900cda6..47ae5d0 100644 --- a/ext/handlers/filters/types.go +++ b/ext/handlers/filters/types.go @@ -15,4 +15,5 @@ type ( ShippingQuery func(sq *gotgbot.ShippingQuery) bool Reaction func(mru *gotgbot.MessageReactionUpdated) bool BusinessConnection func(bc *gotgbot.BusinessConnection) bool + PurchasedPaidMedia func(pm *gotgbot.PaidMediaPurchased) bool ) diff --git a/ext/handlers/purchasedpaidmedia.go b/ext/handlers/purchasedpaidmedia.go new file mode 100644 index 0000000..bb7f21b --- /dev/null +++ b/ext/handlers/purchasedpaidmedia.go @@ -0,0 +1,36 @@ +package handlers + +import ( + "fmt" + + "github.com/PaulSonOfLars/gotgbot/v2" + "github.com/PaulSonOfLars/gotgbot/v2/ext" + "github.com/PaulSonOfLars/gotgbot/v2/ext/handlers/filters" +) + +type PurchasedPaidMedia struct { + Filter filters.PurchasedPaidMedia + Response Response +} + +func NewPurchasedPaidMedia(f filters.PurchasedPaidMedia, r Response) PurchasedPaidMedia { + return PurchasedPaidMedia{ + Filter: f, + Response: r, + } +} + +func (r PurchasedPaidMedia) CheckUpdate(b *gotgbot.Bot, ctx *ext.Context) bool { + if ctx.PreCheckoutQuery == nil { + return false + } + return r.Filter == nil || r.Filter(ctx.PurchasedPaidMedia) +} + +func (r PurchasedPaidMedia) HandleUpdate(b *gotgbot.Bot, ctx *ext.Context) error { + return r.Response(b, ctx) +} + +func (r PurchasedPaidMedia) Name() string { + return fmt.Sprintf("purchasedpaidmedia_%p", r.Response) +} diff --git a/gen_consts.go b/gen_consts.go index df523b9..9dcf0cf 100755 --- a/gen_consts.go +++ b/gen_consts.go @@ -20,6 +20,7 @@ const ( UpdateTypeCallbackQuery = "callback_query" UpdateTypeShippingQuery = "shipping_query" UpdateTypePreCheckoutQuery = "pre_checkout_query" + UpdateTypePurchasedPaidMedia = "purchased_paid_media" UpdateTypePoll = "poll" UpdateTypePollAnswer = "poll_answer" UpdateTypeMyChatMember = "my_chat_member" @@ -77,6 +78,9 @@ func (u Update) GetType() string { case u.PreCheckoutQuery != nil: return UpdateTypePreCheckoutQuery + case u.PurchasedPaidMedia != nil: + return UpdateTypePurchasedPaidMedia + case u.Poll != nil: return UpdateTypePoll diff --git a/gen_methods.go b/gen_methods.go index 7b9604f..1bcedbb 100755 --- a/gen_methods.go +++ b/gen_methods.go @@ -4415,6 +4415,8 @@ func (bot *Bot) SendMessageWithContext(ctx context.Context, chatId int64, text s type SendPaidMediaOpts struct { // Unique identifier of the business connection on behalf of which the message will be sent BusinessConnectionId string + // Bot-defined paid media payload, 0-128 bytes. This will not be displayed to the user, use it for your internal processes. + Payload string // Media caption, 0-1024 characters after entities parsing Caption string // Mode for parsing entities in the media caption. See formatting options for more details. @@ -4439,7 +4441,7 @@ type SendPaidMediaOpts struct { // // Use this method to send paid media. On success, the sent Message is returned. // - chatId (type int64): Unique identifier for the target chat. If the chat is a channel, all Telegram Star proceeds from this media will be credited to the chat's balance. Otherwise, they will be credited to the bot's balance. -// - starCount (type int64): The number of Telegram Stars that must be paid to buy access to the media +// - starCount (type int64): The number of Telegram Stars that must be paid to buy access to the media; 1-2500 // - media (type []InputPaidMedia): A JSON-serialized array describing the media to be sent; up to 10 items // - opts (type SendPaidMediaOpts): All optional parameters. func (bot *Bot) SendPaidMedia(chatId int64, starCount int64, media []InputPaidMedia, opts *SendPaidMediaOpts) (*Message, error) { @@ -4469,6 +4471,7 @@ func (bot *Bot) SendPaidMediaWithContext(ctx context.Context, chatId int64, star } if opts != nil { v["business_connection_id"] = opts.BusinessConnectionId + v["payload"] = opts.Payload v["caption"] = opts.Caption v["parse_mode"] = opts.ParseMode if opts.CaptionEntities != nil { diff --git a/gen_types.go b/gen_types.go index f249656..11b7a5a 100755 --- a/gen_types.go +++ b/gen_types.go @@ -1336,6 +1336,8 @@ type MergedChatBoostSource struct { User *User `json:"user,omitempty"` // Optional. Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet. (Only for giveaway) GiveawayMessageId int64 `json:"giveaway_message_id,omitempty"` + // Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only (Only for giveaway) + PrizeStarCount int64 `json:"prize_star_count,omitempty"` // Optional. True, if the giveaway was completed, but there was no user to win the prize (Only for giveaway) IsUnclaimed bool `json:"is_unclaimed,omitempty"` } @@ -1461,12 +1463,14 @@ func (v ChatBoostSourceGiftCode) chatBoostSource() {} // ChatBoostSourceGiveaway (https://core.telegram.org/bots/api#chatboostsourcegiveaway) // -// The boost was obtained by the creation of a Telegram Premium giveaway. This boosts the chat 4 times for the duration of the corresponding Telegram Premium subscription. +// The boost was obtained by the creation of a Telegram Premium or a Telegram Star giveaway. This boosts the chat 4 times for the duration of the corresponding Telegram Premium subscription for Telegram Premium giveaways and prize_star_count / 500 times for one year for Telegram Star giveaways. type ChatBoostSourceGiveaway struct { // Identifier of a message in the chat with the giveaway; the message could have been deleted already. May be 0 if the message isn't sent yet. GiveawayMessageId int64 `json:"giveaway_message_id"` - // Optional. User that won the prize in the giveaway if any + // Optional. User that won the prize in the giveaway if any; for Telegram Premium giveaways only User *User `json:"user,omitempty"` + // Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + PrizeStarCount int64 `json:"prize_star_count,omitempty"` // Optional. True, if the giveaway was completed, but there was no user to win the prize IsUnclaimed bool `json:"is_unclaimed,omitempty"` } @@ -1482,6 +1486,7 @@ func (v ChatBoostSourceGiveaway) MergeChatBoostSource() MergedChatBoostSource { Source: "giveaway", GiveawayMessageId: v.GiveawayMessageId, User: v.User, + PrizeStarCount: v.PrizeStarCount, IsUnclaimed: v.IsUnclaimed, } } @@ -2848,7 +2853,9 @@ type Giveaway struct { PrizeDescription string `json:"prize_description,omitempty"` // Optional. A list of two-letter ISO 3166-1 alpha-2 country codes indicating the countries from which eligible users for the giveaway must come. If empty, then all users can participate in the giveaway. Users with a phone number that was bought on Fragment can always participate in giveaways. CountryCodes []string `json:"country_codes,omitempty"` - // Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for + // Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + PrizeStarCount int64 `json:"prize_star_count,omitempty"` + // Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for; for Telegram Premium giveaways only PremiumSubscriptionMonthCount int64 `json:"premium_subscription_month_count,omitempty"` } @@ -2862,12 +2869,17 @@ type GiveawayCompleted struct { UnclaimedPrizeCount int64 `json:"unclaimed_prize_count,omitempty"` // Optional. Message with the giveaway that was completed, if it wasn't deleted GiveawayMessage *Message `json:"giveaway_message,omitempty"` + // Optional. True, if the giveaway is a Telegram Star giveaway. Otherwise, currently, the giveaway is a Telegram Premium giveaway. + IsStarGiveaway bool `json:"is_star_giveaway,omitempty"` } // GiveawayCreated (https://core.telegram.org/bots/api#giveawaycreated) // -// This object represents a service message about the creation of a scheduled giveaway. Currently holds no information. -type GiveawayCreated struct{} +// This object represents a service message about the creation of a scheduled giveaway. +type GiveawayCreated struct { + // Optional. The number of Telegram Stars to be split between giveaway winners; for Telegram Star giveaways only + PrizeStarCount int64 `json:"prize_star_count,omitempty"` +} // GiveawayWinners (https://core.telegram.org/bots/api#giveawaywinners) // @@ -2885,7 +2897,9 @@ type GiveawayWinners struct { Winners []User `json:"winners,omitempty"` // Optional. The number of other chats the user had to join in order to be eligible for the giveaway AdditionalChatCount int64 `json:"additional_chat_count,omitempty"` - // Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for + // Optional. The number of Telegram Stars that were split between giveaway winners; for Telegram Star giveaways only + PrizeStarCount int64 `json:"prize_star_count,omitempty"` + // Optional. The number of months the Telegram Premium subscription won from the giveaway will be active for; for Telegram Premium giveaways only PremiumSubscriptionMonthCount int64 `json:"premium_subscription_month_count,omitempty"` // Optional. Number of undistributed prizes UnclaimedPrizeCount int64 `json:"unclaimed_prize_count,omitempty"` @@ -6945,6 +6959,16 @@ func (v PaidMediaPreview) MarshalJSON() ([]byte, error) { // PaidMediaPreview.paidMedia is a dummy method to avoid interface implementation. func (v PaidMediaPreview) paidMedia() {} +// PaidMediaPurchased (https://core.telegram.org/bots/api#paidmediapurchased) +// +// This object contains information about a paid media purchase. +type PaidMediaPurchased struct { + // User who purchased the media + From User `json:"from"` + // Bot-specified paid media payload + PaidMediaPayload string `json:"paid_media_payload"` +} + // PaidMediaVideo (https://core.telegram.org/bots/api#paidmediavideo) // // The paid media is a video. @@ -8491,6 +8515,8 @@ type MergedTransactionPartner struct { InvoicePayload string `json:"invoice_payload,omitempty"` // Optional. Information about the paid media bought by the user (Only for user) PaidMedia []PaidMedia `json:"paid_media,omitempty"` + // Optional. Bot-specified paid media payload (Only for user) + PaidMediaPayload string `json:"paid_media_payload,omitempty"` // Optional. State of the transaction if the transaction is outgoing (Only for fragment) WithdrawalState RevenueWithdrawalState `json:"withdrawal_state,omitempty"` } @@ -8718,15 +8744,18 @@ type TransactionPartnerUser struct { InvoicePayload string `json:"invoice_payload,omitempty"` // Optional. Information about the paid media bought by the user PaidMedia []PaidMedia `json:"paid_media,omitempty"` + // Optional. Bot-specified paid media payload + PaidMediaPayload string `json:"paid_media_payload,omitempty"` } // UnmarshalJSON is a custom JSON unmarshaller to use the helpers which allow for unmarshalling structs into interfaces. func (v *TransactionPartnerUser) UnmarshalJSON(b []byte) error { // All fields in TransactionPartnerUser, with interface fields as json.RawMessage type tmp struct { - User User `json:"user"` - InvoicePayload string `json:"invoice_payload"` - PaidMedia json.RawMessage `json:"paid_media"` + User User `json:"user"` + InvoicePayload string `json:"invoice_payload"` + PaidMedia json.RawMessage `json:"paid_media"` + PaidMediaPayload string `json:"paid_media_payload"` } t := tmp{} err := json.Unmarshal(b, &t) @@ -8740,6 +8769,7 @@ func (v *TransactionPartnerUser) UnmarshalJSON(b []byte) error { if err != nil { return fmt.Errorf("failed to unmarshal custom JSON field PaidMedia: %w", err) } + v.PaidMediaPayload = t.PaidMediaPayload return nil } @@ -8752,10 +8782,11 @@ func (v TransactionPartnerUser) GetType() string { // MergeTransactionPartner returns a MergedTransactionPartner struct to simplify working with types in a non-generic world. func (v TransactionPartnerUser) MergeTransactionPartner() MergedTransactionPartner { return MergedTransactionPartner{ - Type: "user", - User: &v.User, - InvoicePayload: v.InvoicePayload, - PaidMedia: v.PaidMedia, + Type: "user", + User: &v.User, + InvoicePayload: v.InvoicePayload, + PaidMedia: v.PaidMedia, + PaidMediaPayload: v.PaidMediaPayload, } } @@ -8812,6 +8843,8 @@ type Update struct { ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"` // Optional. New incoming pre-checkout query. Contains full information about checkout PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"` + // Optional. A user purchased paid media with a non-empty payload sent by the bot in a non-channel chat + PurchasedPaidMedia *PaidMediaPurchased `json:"purchased_paid_media,omitempty"` // Optional. New poll state. Bots receive only updates about manually stopped polls and polls, which are sent by the bot Poll *Poll `json:"poll,omitempty"` // Optional. A user changed their answer in a non-anonymous poll. Bots receive new votes only in polls that were sent by the bot itself. diff --git a/spec_commit b/spec_commit index 932b851..65471f9 100644 --- a/spec_commit +++ b/spec_commit @@ -1 +1 @@ -a3636ebe8a092809f18d3da9ca023259ae3ef8d1 \ No newline at end of file +0fa498977f006abdfa57dd82bb8bc4c33933a7e7 \ No newline at end of file