diff --git a/bot.go b/bot.go index 39037b8d..ad22f2f3 100644 --- a/bot.go +++ b/bot.go @@ -719,6 +719,19 @@ func (bot *BotAPI) GetMyDefaultAdministratorRights(config GetMyDefaultAdministra return rights, err } +// SavePreparedInlineMessage stores a message that can be sent by a user of a Mini App. +func (bot *BotAPI) SavePreparedInlineMessage(config SavePreparedInlineMessageConfig) (PreparedInlineMessage, error) { + var message PreparedInlineMessage + + resp, err := bot.Request(config) + if err != nil { + return message, err + } + + err = json.Unmarshal(resp.Result, &message) + return message, err +} + // EscapeText takes an input text and escape Telegram markup symbols. // In this way we can send a text without being afraid of having to escape the characters manually. // Note that you don't have to include the formatting style in the input text, or it will be escaped too. @@ -746,3 +759,15 @@ func EscapeText(parseMode string, text string) string { return replacer.Replace(text) } + +func (bot *BotAPI) GetStarTransactions(config GetStarTransactionsConfig) (StarTransactions, error) { + var starTransactions StarTransactions + + resp, err := bot.Request(config) + if err != nil { + return starTransactions, err + } + + err = json.Unmarshal(resp.Result, &starTransactions) + return starTransactions, err +} diff --git a/bot_test.go b/bot_test.go index 7abd790a..10db9fa2 100644 --- a/bot_test.go +++ b/bot_test.go @@ -1,6 +1,7 @@ package tgbotapi import ( + "fmt" "net/http" "os" "testing" @@ -8,7 +9,7 @@ import ( ) const ( - TestToken = "153667468:AAHlSHlMqSt1f_uFmVRJbm5gntu2HI4WW8I" + TestToken = "6766212541:AAGQTAPSbZGQoJ-FmG-nyYZLPCQQCc5wFIw" ChatID = 76918703 Channel = "@tgbotapitest" SupergroupChatID = -1001120141283 @@ -36,7 +37,6 @@ func (t testLogger) Printf(format string, v ...interface{}) { func getBot(t *testing.T) (*BotAPI, error) { bot, err := NewBotAPI(TestToken) - bot.Debug = true logger := testLogger{t} SetLogger(logger) @@ -45,6 +45,8 @@ func getBot(t *testing.T) (*BotAPI, error) { t.Error(err) } + bot.Debug = true + return bot, err } @@ -1048,3 +1050,92 @@ func TestPrepareInputMediaForParams(t *testing.T) { t.Error("Passthrough value was not the same") } } + +func TestCreateInvoiceLink(t *testing.T) { + bot, err := getBot(t) + if err != nil { + t.Fatal(err) + } + resp, err := bot.Request(NewInvoiceLink("Demo Invoice", "This is a demo invoice link", "command", "", "XTR", []int{}, []LabeledPrice{ + { + Label: "Demo Digital Token", + Amount: 100, + }, + })) + + if err != nil { + t.Fatal(err) + } + if !resp.Ok { + t.Fatal("Response not OK", resp.ErrorCode, resp.Description) + } + result, err := resp.Result.MarshalJSON() + if err != nil { + t.Fatal(err) + } + t.Log(string(result)) +} + +func TestSendPhoto(t *testing.T) { + bot, err := getBot(t) + if err != nil { + t.Fatal(err) + } + photo := NewPhoto(1632669575, FileURL("https://pub-4b4332e2985947ceacb0e1bdc9c540bd.r2.dev/novelcoronavirus-optimized.jpg")) + photo.Caption = "Welcome to Follow https://github.com/TUTUBIG" + photo.ShowCaptionAboveMedia = true + _, err = bot.Send(photo) + if err != nil { + t.Fatal(err) + } +} + +func TestSaveInlineMessage(t *testing.T) { + bot, err := NewBotAPI(TestToken) + if err != nil { + t.Fatal(err) + } + + photo := NewInlineQueryResultPhoto(fmt.Sprintf("%d", time.Now().Unix()), "https://pub-6c52100fa9ac41f681f0713eac878541.r2.dev/xxx.png") + photo.Caption = "This is a demo saved inline query messages" + photo.ParseMode = "HTML" + photo.ThumbURL = "https://pub-6c52100fa9ac41f681f0713eac878541.r2.dev/xxx.png" + markup := NewInlineKeyboardMarkup(NewInlineKeyboardRow(NewInlineKeyboardButtonURL("Open in TOMO", fmt.Sprintf("https://www.google.com")))) + photo.ReplyMarkup = &markup + + message, err := bot.SavePreparedInlineMessage(SavePreparedInlineMessageConfig{ + UserId: 1632669575, + Result: photo, + AllowUserChats: true, + AllowBotChats: true, + AllowGroupChats: true, + AllowChannelChats: true, + }) + + if err != nil { + t.Fatal(err) + } + + t.Log(message) +} + +func TestGetStarTransactions(t *testing.T) { + bot, err := getBot(t) + if err != nil { + t.Fatal(err) + } + + response, err := bot.GetStarTransactions(GetStarTransactionsConfig{ + Offset: 200, + Limit: 100, + }) + if err != nil { + t.Fatal(err) + } + + for _, transaction := range response.Transactions { + if transaction.Receiver != nil { + t.Logf("%+v\n", transaction) + } + } +} diff --git a/configs.go b/configs.go index 1831337b..00916dab 100644 --- a/configs.go +++ b/configs.go @@ -405,10 +405,11 @@ func (config CopyMessageConfig) method() string { // PhotoConfig contains information about a SendPhoto request. type PhotoConfig struct { BaseFile - Thumb RequestFileData - Caption string - ParseMode string - CaptionEntities []MessageEntity + Thumb RequestFileData + Caption string + ParseMode string + CaptionEntities []MessageEntity + ShowCaptionAboveMedia bool } func (config PhotoConfig) params() (Params, error) { @@ -420,6 +421,7 @@ func (config PhotoConfig) params() (Params, error) { params.AddNonEmpty("caption", config.Caption) params.AddNonEmpty("parse_mode", config.ParseMode) err = params.AddInterface("caption_entities", config.CaptionEntities) + params.AddBool("show_caption_above_media", config.ShowCaptionAboveMedia) return params, err } @@ -1784,6 +1786,65 @@ func (config InvoiceConfig) method() string { return "sendInvoice" } +// InvoiceLinkConfig contains information for createInvoiceLink request. +type InvoiceLinkConfig struct { + Title string // required + Description string // required + Payload string // required + ProviderToken string // required + Currency string // required + Prices []LabeledPrice // required + MaxTipAmount int + SuggestedTipAmounts []int + ProviderData string + PhotoURL string + PhotoSize int + PhotoWidth int + PhotoHeight int + NeedName bool + NeedPhoneNumber bool + NeedEmail bool + NeedShippingAddress bool + SendPhoneNumberToProvider bool + SendEmailToProvider bool + IsFlexible bool +} + +func (config InvoiceLinkConfig) params() (Params, error) { + params := make(Params) + var err error + + params["title"] = config.Title + params["description"] = config.Description + params["payload"] = config.Payload + params["provider_token"] = config.ProviderToken + params["currency"] = config.Currency + if err = params.AddInterface("prices", config.Prices); err != nil { + return params, err + } + + params.AddNonZero("max_tip_amount", config.MaxTipAmount) + err = params.AddInterface("suggested_tip_amounts", config.SuggestedTipAmounts) + params.AddNonEmpty("provider_data", config.ProviderData) + params.AddNonEmpty("photo_url", config.PhotoURL) + params.AddNonZero("photo_size", config.PhotoSize) + params.AddNonZero("photo_width", config.PhotoWidth) + params.AddNonZero("photo_height", config.PhotoHeight) + params.AddBool("need_name", config.NeedName) + params.AddBool("need_phone_number", config.NeedPhoneNumber) + params.AddBool("need_email", config.NeedEmail) + params.AddBool("need_shipping_address", config.NeedShippingAddress) + params.AddBool("is_flexible", config.IsFlexible) + params.AddBool("send_phone_number_to_provider", config.SendPhoneNumberToProvider) + params.AddBool("send_email_to_provider", config.SendEmailToProvider) + + return params, err +} + +func (config InvoiceLinkConfig) method() string { + return "createInvoiceLink" +} + // ShippingConfig contains information for answerShippingQuery request. type ShippingConfig struct { ShippingQueryID string // required @@ -2566,3 +2627,55 @@ func prepareInputMediaForFiles(inputMedia []interface{}) []RequestFile { return files } + +type SavePreparedInlineMessageConfig struct { + UserId int64 + Result interface{} // Too many definitions to use generics but please make sure it is InlineQueryResult. https://core.telegram.org/bots/api#inlinequeryresult + AllowUserChats bool + AllowBotChats bool + AllowGroupChats bool + AllowChannelChats bool +} + +func (config SavePreparedInlineMessageConfig) method() string { + return "savePreparedInlineMessage" +} + +func (config SavePreparedInlineMessageConfig) params() (Params, error) { + params := make(Params) + + params.AddNonZero64("user_id", config.UserId) + if err := params.AddInterface("result", config.Result); err != nil { + return nil, err + } + params.AddBool("allow_user_chats", config.AllowUserChats) + params.AddBool("allow_bot_chats", config.AllowBotChats) + params.AddBool("allow_group_chats", config.AllowGroupChats) + params.AddBool("allow_channel_chats", config.AllowChannelChats) + + return params, nil +} + +// GetStarTransactionsConfig Returns the bot's Telegram Star transactions in chronological order. On success, returns a StarTransactions object. +type GetStarTransactionsConfig struct { + // Number of transactions to skip in the response + Offset int64 + // The maximum number of transactions to be retrieved. Values between 1-100 are accepted. Defaults to 100. + Limit int64 +} + +func (config GetStarTransactionsConfig) method() string { + return "getStarTransactions" +} + +func (config GetStarTransactionsConfig) params() (Params, error) { + params := make(Params) + + err := params.AddInterface("offset", config.Offset) + if err != nil { + return nil, err + } + params.AddNonZero("limit", int(config.Limit)) + + return params, nil +} diff --git a/go.mod b/go.mod index 167e5e45..b27bc974 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ -module github.com/go-telegram-bot-api/telegram-bot-api/v5 +module github.com/TUTUBIG/telegram-bot-api/v5 go 1.16 diff --git a/helpers.go b/helpers.go index 3a0e8187..97395d6e 100644 --- a/helpers.go +++ b/helpers.go @@ -777,6 +777,19 @@ func NewInvoice(chatID int64, title, description, payload, providerToken, startP Prices: prices} } +// NewInvoiceLink creates a new Invoice link. +func NewInvoiceLink(title, description, payload, providerToken, currency string, suggestedTipAmounts []int, prices []LabeledPrice) InvoiceLinkConfig { + return InvoiceLinkConfig{ + Title: title, + Description: description, + Payload: payload, + ProviderToken: providerToken, + Currency: currency, + Prices: prices, + SuggestedTipAmounts: suggestedTipAmounts, + } +} + // NewChatTitle allows you to update the title of a chat. func NewChatTitle(chatID int64, title string) SetChatTitleConfig { return SetChatTitleConfig{ diff --git a/types.go b/types.go index 36c174b8..9f4c9dc4 100644 --- a/types.go +++ b/types.go @@ -594,6 +594,11 @@ type Message struct { // // optional SuccessfulPayment *SuccessfulPayment `json:"successful_payment,omitempty"` + // RefundedPayment is a service message about a refunded payment, + // information about the payment; + // + // optional + RefundedPayment *RefundedPayment `json:"refunded_payment,omitempty"` // ConnectedWebsite is the domain name of the website on which the user has // logged in; // @@ -3289,6 +3294,20 @@ type SuccessfulPayment struct { ProviderPaymentChargeID string `json:"provider_payment_charge_id"` } +// RefundedPayment This object contains basic information about a refunded payment. +type RefundedPayment struct { + // Three-letter ISO 4217 currency code, or “XTR” for payments in Telegram Stars. Currently, always “XTR” + Currency string `json:"currency"` + // Total refunded price in the smallest units of the currency (integer, not float/double). For example, for a price of US$ 1.45, total_amount = 145. See the exp parameter in currencies.json, it shows the number of digits past the decimal point for each currency (2 for the majority of currencies). + TotalAmount int `json:"total_amount"` + // Bot-specified invoice payload + InvoicePayload string `json:"invoice_payload"` + // Telegram payment identifier + TelegramPaymentChargeId string `json:"telegram_payment_charge_id"` + // Optional. Provider payment identifier + ProviderPaymentChargeId string `json:"provider_payment_charge_id"` +} + // ShippingQuery contains information about an incoming shipping query. type ShippingQuery struct { // ID unique query identifier @@ -3328,3 +3347,39 @@ type PreCheckoutQuery struct { // optional OrderInfo *OrderInfo `json:"order_info,omitempty"` } + +// PreparedInlineMessage describes an inline message to be sent by a user of a Mini App. +type PreparedInlineMessage struct { + // Unique identifier of the prepared message + Id string `json:"id"` + // Expiration date of the prepared message, in Unix time. Expired prepared messages can no longer be used + ExpirationDate int64 `json:"expiration_date"` +} + +// TransactionPartnerUser Describes a transaction with a user. +type TransactionPartnerUser struct { + Type string `json:"type"` + User User `json:"user"` +} + +// StarTransaction Describes a Telegram Star transaction. +type StarTransaction struct { + // Unique identifier of the transaction. Coincides with the identifier of the original transaction for refund transactions. Coincides with SuccessfulPayment.telegram_payment_charge_id for successful incoming payments from users. + Id string `json:"id"` + // Integer amount of Telegram Stars transferred by the transaction + Amount int64 `json:"amount"` + // Optional. The number of 1/1000000000 shares of Telegram Stars transferred by the transaction; from 0 to 999999999 + NanostarAmount int64 `json:"nanostar_amount"` + // Date the transaction was created in Unix time + Date int64 `json:"date"` + // Optional. Source of an incoming transaction (e.g., a user purchasing goods or services, Fragment refunding a failed withdrawal). Only for incoming transactions + Source interface{} `json:"source"` + // Optional. Receiver of an outgoing transaction (e.g., a user for a purchase refund, Fragment for a withdrawal). Only for outgoing transactions + Receiver interface{} `json:"receiver"` +} + +// StarTransactions Contains a list of Telegram Star transactions. +type StarTransactions struct { + // The list of transactions + Transactions []StarTransaction `json:"transactions"` +}