diff --git a/.github/codecov.yml b/.github/codecov.yml index 20b3671..2554522 100644 --- a/.github/codecov.yml +++ b/.github/codecov.yml @@ -1,3 +1,4 @@ ignore: - methods_gen.go + - types_gen.go - examples diff --git a/README.md b/README.md index a935aac..0b50c09 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Go Reference](https://pkg.go.dev/badge/github.com/mr-linch/go-tg.svg)](https://pkg.go.dev/github.com/mr-linch/go-tg) [![go.mod](https://img.shields.io/github/go-mod/go-version/mr-linch/go-tg)](go.mod) [![GitHub release (latest by date)](https://img.shields.io/github/v/release/mr-linch/go-tg?label=latest%20release)](https://github.com/mr-linch/go-tg/releases/latest) -![Telegram Bot API](https://img.shields.io/badge/Telegram%20Bot%20API-7.1-blue?logo=telegram) +![Telegram Bot API](https://img.shields.io/badge/Telegram%20Bot%20API-7.2-blue?logo=telegram) [![CI](https://github.com/mr-linch/go-tg/actions/workflows/ci.yml/badge.svg)](https://github.com/mr-linch/go-tg/actions/workflows/ci.yml) [![codecov](https://codecov.io/gh/mr-linch/go-tg/branch/main/graph/badge.svg?token=9EI5CEIYXL)](https://codecov.io/gh/mr-linch/go-tg) [![Go Report Card](https://goreportcard.com/badge/github.com/mr-linch/go-tg)](https://goreportcard.com/report/github.com/mr-linch/go-tg) @@ -29,9 +29,9 @@ - [Receive updates via Webhook](#receive-updates-via-webhook) - [Routing updates](#routing-updates) - [Extensions](#extensions) - - [Sessions](#sessions) + - [Sessions](#sessions) - [Related Projects](#related-projects) -- [Projects using this package] +- [Projects using this package](#projects-using-this-package) - [Thanks](#thanks) go-tg is a Go client library for accessing [Telegram Bot API](https://core.telegram.org/bots/api), with batteries for building complex bots included. @@ -40,14 +40,16 @@ go-tg is a Go client library for accessing [Telegram Bot API](https://core.teleg ## Features -- Code for Bot API types and methods is generated with embedded official documentation. -- Support [context.Context](https://pkg.go.dev/context). -- API Client and bot framework are strictly separated, you can use them independently. -- No runtime reflection overhead. -- Supports Webhook and Polling natively; -- [Webhook reply](https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates) for high load bots; -- Handlers, filters, and middleware are supported. -- [WebApps](https://core.telegram.org/bots/webapps) and [Login Widget](https://core.telegram.org/widgets/login) helpers. +- :rocket: Code for Bot API types and methods is generated with embedded official documentation. +- :white_check_mark: Support [context.Context](https://pkg.go.dev/context). +- :link: API Client and bot framework are strictly separated, you can use them independently. +- :zap: No runtime reflection overhead. +- :arrows_counterclockwise: Supports Webhook and Polling natively; +- :mailbox_with_mail: [Webhook reply](https://core.telegram.org/bots/faq#how-can-i-make-requests-in-response-to-updates) for high load bots; +- :raised_hands: Handlers, filters, and middleware are supported. +- :globe_with_meridians: [WebApps](https://core.telegram.org/bots/webapps) and [Login Widget](https://core.telegram.org/widgets/login) helpers. +- :handshake: Business connections support + ## Install @@ -375,18 +377,19 @@ client := tg.New("", ) ``` - Arguments of the interceptor are: - - `ctx` - context of the request; - - `req` - request object [tg.Request](https://pkg.go.dev/github.com/mr-linch/go-tg#Request); - - `dst` - pointer to destination for the response, can be `nil` if the request is made with `DoVoid` method; - - `invoker` - function for calling the next interceptor or the actual request. + +- `ctx` - context of the request; +- `req` - request object [tg.Request](https://pkg.go.dev/github.com/mr-linch/go-tg#Request); +- `dst` - pointer to destination for the response, can be `nil` if the request is made with `DoVoid` method; +- `invoker` - function for calling the next interceptor or the actual request. Contrib package has some useful interceptors: - - [InterceptorRetryFloodError](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorRetryFloodError) - retry request if the server returns a flood error. Parameters can be customized via options; - - [InterceptorRetryInternalServerError](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorRetryInternalServerError) - retry request if the server returns an error. Parameters can be customized via options; - - [InterceptorMethodFilter](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorMethodFilter) - call underlying interceptor only for specified methods; - - [InterceptorDefaultParseMethod](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorDefaultParseMethod) - set default `parse_mode` for messages if not specified. + +- [InterceptorRetryFloodError](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorRetryFloodError) - retry request if the server returns a flood error. Parameters can be customized via options; +- [InterceptorRetryInternalServerError](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorRetryInternalServerError) - retry request if the server returns an error. Parameters can be customized via options; +- [InterceptorMethodFilter](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorMethodFilter) - call underlying interceptor only for specified methods; +- [InterceptorDefaultParseMethod](https://pkg.go.dev/github.com/mr-linch/go-tg#NewInterceptorDefaultParseMethod) - set default `parse_mode` for messages if not specified. Interceptors are called in the order they are registered. @@ -451,7 +454,7 @@ These handlers will only be called for updates of a certain type, the rest will List of typed handlers: -- [`tgb.MessageHandler`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#MessageHandler) with [`tgb.MessageUpdate`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#MessageUpdate) for `message`, `edited_message`, `channel_post`, `edited_channel_post`; +- [`tgb.MessageHandler`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#MessageHandler) with [`tgb.MessageUpdate`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#MessageUpdate) for `message`, `edited_message`, `channel_post`, `edited_channel_post`, `business_message`, `edited_business_message`; - [`tgb.InlineQueryHandler`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#InlineQueryHandler) with [`tgb.InlineQueryUpdate`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#InlineQueryUpdate) for `inline_query` - [`tgb.ChosenInlineResult`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#ChosenInlineResult) with [`tgb.ChosenInlineResultUpdate`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#ChosenInlineResultUpdate) for `chosen_inline_result`; - [`tgb.CallbackQueryHandler`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#CallbackQueryHandler) with [`tgb.CallbackQueryUpdate`](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb#CallbackQueryUpdate) for `callback_query`; @@ -752,7 +755,8 @@ See [session](https://pkg.go.dev/github.com/mr-linch/go-tg/tgb/session) package - [`bots-house/docker-telegram-bot-api`](https://github.com/bots-house/docker-telegram-bot-api) - docker image for running self-hosted Telegram Bot API with automated CI build; ## Projects using this package - - [@ttkeeperbot](https://t.me/ttkeeperbot) - Automatically upload tiktoks in groups and verify users đŸ‡ș🇩 + +- [@ttkeeperbot](https://t.me/ttkeeperbot) - Automatically upload tiktoks in groups and verify users đŸ‡ș🇩 ## Thanks diff --git a/examples/README.md b/examples/README.md index 07832aa..b609b4e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -15,5 +15,6 @@ Listen port set to `:8000` by default, you can override it with the `-webhook-li | [text-filter](https://github.com/mr-linch/go-tg/tree/main/examples/text-filter) | Text Filter usage | Text filter, reply keyboard markup | | [webapps](https://github.com/mr-linch/go-tg/tree/main/examples/webapps) | Parse and validate Login Widget & WebApp data, host simple webapp | WebApps, Login Widget, Embed webhook to http.Mux | | [session-filter](https://github.com/mr-linch/go-tg/tree/main/examples/session-filter) | Simple form filling with persistent session | Router, Session Manager, Session Filters | -| [menu](https://github.com/mr-linch/go-tg/tree/main/examples/menu) | Hiearchical menu with API integration | ButtonLayout, TextMessageBuilder, CallbackDataFilter | -| [retry-flood](https://github.com/mr-linch/go-tg/tree/main/examples/retry-flood) | Retry on flood error | Interceptors | \ No newline at end of file +| [menu](https://github.com/mr-linch/go-tg/tree/main/examples/menu) | Hiearchical menu with API integration | ButtonLayout, TextMessageBuilder, CallbackDataFilter | +| [retry-flood](https://github.com/mr-linch/go-tg/tree/main/examples/retry-flood) | Retry on flood error | Interceptors | +| [business-bot](https://github.com/mr-linch/go-tg/tree/main/examples/business-bot) | Business bot with multiple handlers | Router | diff --git a/examples/business-bot/main.go b/examples/business-bot/main.go new file mode 100644 index 0000000..24e59b5 --- /dev/null +++ b/examples/business-bot/main.go @@ -0,0 +1,79 @@ +// Package contains simple echo bot, that demonstrates how to use handlers, filters and file uploads. +package main + +import ( + "context" + "fmt" + "log" + "strings" + + "github.com/mr-linch/go-tg" + "github.com/mr-linch/go-tg/examples" + "github.com/mr-linch/go-tg/tgb" +) + +var pm = tg.HTML + +func main() { + examples.Run(tgb.NewRouter(). + Message(func(ctx context.Context, mu *tgb.MessageUpdate) error { + me, err := mu.Client.GetMe().Do(ctx) + if err != nil { + return fmt.Errorf("get me: %w", err) + } + + if !me.CanConnectToBusiness { + return mu.Answer("Bussines features is not enabled for current bot. Enable it via @BotFather").DoVoid(ctx) + } + + if mu.From != nil && !mu.From.IsPremium { + return mu.Answer("Bussines features works only for Telegram Premium users. Purchase subscription before use that bot.").DoVoid(ctx) + } + + return mu.Answer("Connect bot in Telegram Bussines settings of your account").DoVoid(ctx) + }, tgb.Command("start")). + BusinessMessage(func(ctx context.Context, mu *tgb.MessageUpdate) error { + if strings.Contains(mu.Text, "ping") { + return mu.Answer("Pong!").BusinessConnectionID(mu.BusinessConnectionID).DoVoid(ctx) + } + + log.Printf("New business message #%d: %s", mu.ID, mu.Text) + + return nil + }). + EditedBusinessMessage(func(ctx context.Context, mu *tgb.MessageUpdate) error { + log.Printf("Edited business message: %#v", mu.Message) + + return nil + }). + BusinessConnection(func(ctx context.Context, bcu *tgb.BusinessConnectionUpdate) error { + log.Printf("New business connection: %#v", bcu.BusinessConnection) + + lines := []string{} + + if bcu.IsEnabled { + lines = append(lines, "đŸ€ Business connection estabilished") + } else { + lines = append(lines, "❌ Business connection closed") + } + + lines = append(lines, "") + + lines = append(lines, pm.Line( + pm.Bold("ID: "), pm.Code(bcu.BusinessConnection.ID), + )) + + lines = append(lines, pm.Line( + pm.Bold("Can Reply? "), pm.Code(fmt.Sprintf("%t", bcu.BusinessConnection.CanReply)), + )) + + return bcu.Update.Reply(ctx, + tg.NewSendMessageCall( + bcu.User, + pm.Text(lines...), + ). + ParseMode(pm), + ) + }), + ) +} diff --git a/methods_gen.go b/methods_gen.go index 6e120e4..1232c73 100644 --- a/methods_gen.go +++ b/methods_gen.go @@ -282,6 +282,12 @@ func (client *Client) SendMessage(chatID PeerID, text string) *SendMessageCall { ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendMessageCall) BusinessConnectionID(businessConnectionID string) *SendMessageCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendMessageCall) ChatID(chatID PeerID) *SendMessageCall { call.request.PeerID("chat_id", chatID) @@ -336,7 +342,7 @@ func (call *SendMessageCall) ReplyParameters(replyParameters ReplyParameters) *S return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendMessageCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendMessageCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -422,7 +428,7 @@ type ForwardMessagesCall struct { // NewForwardMessagesCall constructs a new ForwardMessagesCall with required parameters. // chatID - Unique identifier for the target chat or username of the target channel (in the format @channelusername) // fromChatID - Unique identifier for the chat where the original messages were sent (or channel username in the format @channelusername) -// messageIds - Identifiers of 1-100 messages in the chat from_chat_id to forward. The identifiers must be specified in a strictly increasing order. +// messageIds - A JSON-serialized list of 1-100 identifiers of messages in the chat from_chat_id to forward. The identifiers must be specified in a strictly increasing order. func NewForwardMessagesCall(chatID PeerID, fromChatID PeerID, messageIds []int) *ForwardMessagesCall { return &ForwardMessagesCall{ Call[MessageID]{ @@ -460,7 +466,7 @@ func (call *ForwardMessagesCall) FromChatID(fromChatID PeerID) *ForwardMessagesC return call } -// MessageIds Identifiers of 1-100 messages in the chat from_chat_id to forward. The identifiers must be specified in a strictly increasing order. +// MessageIds A JSON-serialized list of 1-100 identifiers of messages in the chat from_chat_id to forward. The identifiers must be specified in a strictly increasing order. func (call *ForwardMessagesCall) MessageIds(messageIds []int) *ForwardMessagesCall { call.request.JSON("message_ids", messageIds) return call @@ -592,7 +598,7 @@ type CopyMessagesCall struct { // NewCopyMessagesCall constructs a new CopyMessagesCall with required parameters. // chatID - Unique identifier for the target chat or username of the target channel (in the format @channelusername) // fromChatID - Unique identifier for the chat where the original messages were sent (or channel username in the format @channelusername) -// messageIds - Identifiers of 1-100 messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly increasing order. +// messageIds - A JSON-serialized list of 1-100 identifiers of messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly increasing order. func NewCopyMessagesCall(chatID PeerID, fromChatID PeerID, messageIds []int) *CopyMessagesCall { return &CopyMessagesCall{ Call[MessageID]{ @@ -630,7 +636,7 @@ func (call *CopyMessagesCall) FromChatID(fromChatID PeerID) *CopyMessagesCall { return call } -// MessageIds Identifiers of 1-100 messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly increasing order. +// MessageIds A JSON-serialized list of 1-100 identifiers of messages in the chat from_chat_id to copy. The identifiers must be specified in a strictly increasing order. func (call *CopyMessagesCall) MessageIds(messageIds []int) *CopyMessagesCall { call.request.JSON("message_ids", messageIds) return call @@ -682,6 +688,12 @@ func (client *Client) SendPhoto(chatID PeerID, photo FileArg) *SendPhotoCall { ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendPhotoCall) BusinessConnectionID(businessConnectionID string) *SendPhotoCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendPhotoCall) ChatID(chatID PeerID) *SendPhotoCall { call.request.PeerID("chat_id", chatID) @@ -742,7 +754,7 @@ func (call *SendPhotoCall) ReplyParameters(replyParameters ReplyParameters) *Sen return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendPhotoCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendPhotoCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -779,6 +791,12 @@ func (client *Client) SendAudio(chatID PeerID, audio FileArg) *SendAudioCall { ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendAudioCall) BusinessConnectionID(businessConnectionID string) *SendAudioCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendAudioCall) ChatID(chatID PeerID) *SendAudioCall { call.request.PeerID("chat_id", chatID) @@ -857,7 +875,7 @@ func (call *SendAudioCall) ReplyParameters(replyParameters ReplyParameters) *Sen return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendAudioCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendAudioCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -892,6 +910,12 @@ func (client *Client) SendDocument(chatID PeerID, document FileArg) *SendDocumen ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendDocumentCall) BusinessConnectionID(businessConnectionID string) *SendDocumentCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendDocumentCall) ChatID(chatID PeerID) *SendDocumentCall { call.request.PeerID("chat_id", chatID) @@ -958,7 +982,7 @@ func (call *SendDocumentCall) ReplyParameters(replyParameters ReplyParameters) * return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendDocumentCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendDocumentCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -993,6 +1017,12 @@ func (client *Client) SendVideo(chatID PeerID, video FileArg) *SendVideoCall { ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendVideoCall) BusinessConnectionID(businessConnectionID string) *SendVideoCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendVideoCall) ChatID(chatID PeerID) *SendVideoCall { call.request.PeerID("chat_id", chatID) @@ -1083,7 +1113,7 @@ func (call *SendVideoCall) ReplyParameters(replyParameters ReplyParameters) *Sen return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendVideoCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendVideoCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1118,6 +1148,12 @@ func (client *Client) SendAnimation(chatID PeerID, animation FileArg) *SendAnima ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendAnimationCall) BusinessConnectionID(businessConnectionID string) *SendAnimationCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendAnimationCall) ChatID(chatID PeerID) *SendAnimationCall { call.request.PeerID("chat_id", chatID) @@ -1202,7 +1238,7 @@ func (call *SendAnimationCall) ReplyParameters(replyParameters ReplyParameters) return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendAnimationCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendAnimationCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1238,6 +1274,12 @@ func (client *Client) SendVoice(chatID PeerID, voice FileArg) *SendVoiceCall { ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendVoiceCall) BusinessConnectionID(businessConnectionID string) *SendVoiceCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendVoiceCall) ChatID(chatID PeerID) *SendVoiceCall { call.request.PeerID("chat_id", chatID) @@ -1298,7 +1340,7 @@ func (call *SendVoiceCall) ReplyParameters(replyParameters ReplyParameters) *Sen return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendVoiceCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendVoiceCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1333,6 +1375,12 @@ func (client *Client) SendVideoNote(chatID PeerID, videoNote FileArg) *SendVideo ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendVideoNoteCall) BusinessConnectionID(businessConnectionID string) *SendVideoNoteCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendVideoNoteCall) ChatID(chatID PeerID) *SendVideoNoteCall { call.request.PeerID("chat_id", chatID) @@ -1387,7 +1435,7 @@ func (call *SendVideoNoteCall) ReplyParameters(replyParameters ReplyParameters) return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendVideoNoteCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendVideoNoteCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1422,6 +1470,12 @@ func (client *Client) SendMediaGroup(chatID PeerID, media []InputMedia) *SendMed ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendMediaGroupCall) BusinessConnectionID(businessConnectionID string) *SendMediaGroupCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendMediaGroupCall) ChatID(chatID PeerID) *SendMediaGroupCall { call.request.PeerID("chat_id", chatID) @@ -1488,6 +1542,12 @@ func (client *Client) SendLocation(chatID PeerID, latitude float64, longitude fl ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendLocationCall) BusinessConnectionID(businessConnectionID string) *SendLocationCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendLocationCall) ChatID(chatID PeerID) *SendLocationCall { call.request.PeerID("chat_id", chatID) @@ -1554,7 +1614,7 @@ func (call *SendLocationCall) ReplyParameters(replyParameters ReplyParameters) * return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendLocationCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendLocationCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1594,6 +1654,12 @@ func (client *Client) SendVenue(chatID PeerID, latitude float64, longitude float ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendVenueCall) BusinessConnectionID(businessConnectionID string) *SendVenueCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendVenueCall) ChatID(chatID PeerID) *SendVenueCall { call.request.PeerID("chat_id", chatID) @@ -1672,7 +1738,7 @@ func (call *SendVenueCall) ReplyParameters(replyParameters ReplyParameters) *Sen return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendVenueCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendVenueCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1708,6 +1774,12 @@ func (client *Client) SendContact(chatID PeerID, phoneNumber string, firstName s ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendContactCall) BusinessConnectionID(businessConnectionID string) *SendContactCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendContactCall) ChatID(chatID PeerID) *SendContactCall { call.request.PeerID("chat_id", chatID) @@ -1762,7 +1834,7 @@ func (call *SendContactCall) ReplyParameters(replyParameters ReplyParameters) *S return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendContactCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendContactCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1798,6 +1870,12 @@ func (client *Client) SendPoll(chatID PeerID, question string, options []string) ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendPollCall) BusinessConnectionID(businessConnectionID string) *SendPollCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendPollCall) ChatID(chatID PeerID) *SendPollCall { call.request.PeerID("chat_id", chatID) @@ -1853,8 +1931,8 @@ func (call *SendPollCall) Explanation(explanation string) *SendPollCall { } // ExplanationParseMode Mode for parsing entities in the explanation. See formatting options for more details. -func (call *SendPollCall) ExplanationParseMode(explanationParseMode string) *SendPollCall { - call.request.String("explanation_parse_mode", explanationParseMode) +func (call *SendPollCall) ExplanationParseMode(explanationParseMode ParseMode) *SendPollCall { + call.request.Stringer("explanation_parse_mode", explanationParseMode) return call } @@ -1900,7 +1978,7 @@ func (call *SendPollCall) ReplyParameters(replyParameters ReplyParameters) *Send return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendPollCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendPollCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -1932,6 +2010,12 @@ func (client *Client) SendDice(chatID PeerID) *SendDiceCall { ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendDiceCall) BusinessConnectionID(businessConnectionID string) *SendDiceCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendDiceCall) ChatID(chatID PeerID) *SendDiceCall { call.request.PeerID("chat_id", chatID) @@ -1968,7 +2052,7 @@ func (call *SendDiceCall) ReplyParameters(replyParameters ReplyParameters) *Send return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove a reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account func (call *SendDiceCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendDiceCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -2006,13 +2090,19 @@ func (client *Client) SendChatAction(chatID PeerID, action ChatAction) *SendChat ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the action will be sent +func (call *SendChatActionCall) BusinessConnectionID(businessConnectionID string) *SendChatActionCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendChatActionCall) ChatID(chatID PeerID) *SendChatActionCall { call.request.PeerID("chat_id", chatID) return call } -// MessageThreadID Unique identifier for the target message thread; supergroups only +// MessageThreadID Unique identifier for the target message thread; for supergroups only func (call *SendChatActionCall) MessageThreadID(messageThreadID int) *SendChatActionCall { call.request.Int("message_thread_id", messageThreadID) return call @@ -2065,7 +2155,7 @@ func (call *SetMessageReactionCall) MessageID(messageID int) *SetMessageReaction return call } -// Reaction New list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message. A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators. +// Reaction A JSON-serialized list of reaction types to set on the message. Currently, as non-premium users, bots can set up to one reaction per message. A custom emoji reaction can be used if it is either already present on the message or explicitly allowed by chat administrators. func (call *SetMessageReactionCall) Reaction(reaction []ReactionType) *SetMessageReactionCall { call.request.JSON("reaction", reaction) return call @@ -2428,25 +2518,25 @@ func (call *PromoteChatMemberCall) CanDeleteStories(canDeleteStories bool) *Prom return call } -// CanPostMessages Pass True if the administrator can post messages in the channel, or access channel statistics; channels only +// CanPostMessages Pass True if the administrator can post messages in the channel, or access channel statistics; for channels only func (call *PromoteChatMemberCall) CanPostMessages(canPostMessages bool) *PromoteChatMemberCall { call.request.Bool("can_post_messages", canPostMessages) return call } -// CanEditMessages Pass True if the administrator can edit messages of other users and can pin messages; channels only +// CanEditMessages Pass True if the administrator can edit messages of other users and can pin messages; for channels only func (call *PromoteChatMemberCall) CanEditMessages(canEditMessages bool) *PromoteChatMemberCall { call.request.Bool("can_edit_messages", canEditMessages) return call } -// CanPinMessages Pass True if the administrator can pin messages, supergroups only +// CanPinMessages Pass True if the administrator can pin messages; for supergroups only func (call *PromoteChatMemberCall) CanPinMessages(canPinMessages bool) *PromoteChatMemberCall { call.request.Bool("can_pin_messages", canPinMessages) return call } -// CanManageTopics Pass True if the user is allowed to create, rename, close, and reopen forum topics, supergroups only +// CanManageTopics Pass True if the user is allowed to create, rename, close, and reopen forum topics; for supergroups only func (call *PromoteChatMemberCall) CanManageTopics(canManageTopics bool) *PromoteChatMemberCall { call.request.Bool("can_manage_topics", canManageTopics) return call @@ -4008,6 +4098,38 @@ func (call *GetUserChatBoostsCall) UserID(userID UserID) *GetUserChatBoostsCall return call } +// GetBusinessConnectionCall reprenesents a call to the getBusinessConnection method. +// Use this method to get information about the connection of the bot with a business account +// Returns a BusinessConnection object on success. +type GetBusinessConnectionCall struct { + Call[BusinessConnection] +} + +// NewGetBusinessConnectionCall constructs a new GetBusinessConnectionCall with required parameters. +// businessConnectionID - Unique identifier of the business connection +func NewGetBusinessConnectionCall(businessConnectionID string) *GetBusinessConnectionCall { + return &GetBusinessConnectionCall{ + Call[BusinessConnection]{ + request: NewRequest("getBusinessConnection"). + String("business_connection_id", businessConnectionID), + }, + } +} + +// GetBusinessConnectionCall constructs a new GetBusinessConnectionCall with required parameters. +func (client *Client) GetBusinessConnection(businessConnectionID string) *GetBusinessConnectionCall { + return BindClient( + NewGetBusinessConnectionCall(businessConnectionID), + client, + ) +} + +// BusinessConnectionID Unique identifier of the business connection +func (call *GetBusinessConnectionCall) BusinessConnectionID(businessConnectionID string) *GetBusinessConnectionCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // SetMyCommandsCall reprenesents a call to the setMyCommands method. // Use this method to change the list of the bot's commands // See this manual for more details about bot commands @@ -5038,7 +5160,7 @@ type DeleteMessagesCall struct { // NewDeleteMessagesCall constructs a new DeleteMessagesCall with required parameters. // chatID - Unique identifier for the target chat or username of the target channel (in the format @channelusername) -// messageIds - Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted +// messageIds - A JSON-serialized list of 1-100 identifiers of messages to delete. See deleteMessage for limitations on which messages can be deleted func NewDeleteMessagesCall(chatID PeerID, messageIds []int) *DeleteMessagesCall { return &DeleteMessagesCall{ CallNoResult{ @@ -5063,7 +5185,7 @@ func (call *DeleteMessagesCall) ChatID(chatID PeerID) *DeleteMessagesCall { return call } -// MessageIds Identifiers of 1-100 messages to delete. See deleteMessage for limitations on which messages can be deleted +// MessageIds A JSON-serialized list of 1-100 identifiers of messages to delete. See deleteMessage for limitations on which messages can be deleted func (call *DeleteMessagesCall) MessageIds(messageIds []int) *DeleteMessagesCall { call.request.JSON("message_ids", messageIds) return call @@ -5078,7 +5200,7 @@ type SendStickerCall struct { // NewSendStickerCall constructs a new SendStickerCall with required parameters. // chatID - Unique identifier for the target chat or username of the target channel (in the format @channelusername) -// sticker - Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .WEBP sticker from the Internet, or upload a new .WEBP or .TGS sticker using multipart/form-data. More information on Sending Files ». Video stickers can only be sent by a file_id. Animated stickers can't be sent via an HTTP URL. +// sticker - Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .WEBP sticker from the Internet, or upload a new .WEBP, .TGS, or .WEBM sticker using multipart/form-data. More information on Sending Files ». Video and animated stickers can't be sent via an HTTP URL. func NewSendStickerCall(chatID PeerID, sticker FileArg) *SendStickerCall { return &SendStickerCall{ Call[Message]{ @@ -5097,6 +5219,12 @@ func (client *Client) SendSticker(chatID PeerID, sticker FileArg) *SendStickerCa ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendStickerCall) BusinessConnectionID(businessConnectionID string) *SendStickerCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat or username of the target channel (in the format @channelusername) func (call *SendStickerCall) ChatID(chatID PeerID) *SendStickerCall { call.request.PeerID("chat_id", chatID) @@ -5109,7 +5237,7 @@ func (call *SendStickerCall) MessageThreadID(messageThreadID int) *SendStickerCa return call } -// Sticker Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .WEBP sticker from the Internet, or upload a new .WEBP or .TGS sticker using multipart/form-data. More information on Sending Files ». Video stickers can only be sent by a file_id. Animated stickers can't be sent via an HTTP URL. +// Sticker Sticker to send. Pass a file_id as String to send a file that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get a .WEBP sticker from the Internet, or upload a new .WEBP, .TGS, or .WEBM sticker using multipart/form-data. More information on Sending Files ». Video and animated stickers can't be sent via an HTTP URL. func (call *SendStickerCall) Sticker(sticker FileArg) *SendStickerCall { call.request.File("sticker", sticker) return call @@ -5139,7 +5267,7 @@ func (call *SendStickerCall) ReplyParameters(replyParameters ReplyParameters) *S return call } -// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. +// ReplyMarkup Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user. Not supported for messages sent on behalf of a business account. func (call *SendStickerCall) ReplyMarkup(replyMarkup ReplyMarkup) *SendStickerCall { call.request.JSON("reply_markup", replyMarkup) return call @@ -5185,7 +5313,7 @@ type GetCustomEmojiStickersCall struct { } // NewGetCustomEmojiStickersCall constructs a new GetCustomEmojiStickersCall with required parameters. -// customEmojiIds - List of custom emoji identifiers. At most 200 custom emoji identifiers can be specified. +// customEmojiIds - A JSON-serialized list of custom emoji identifiers. At most 200 custom emoji identifiers can be specified. func NewGetCustomEmojiStickersCall(customEmojiIds []string) *GetCustomEmojiStickersCall { return &GetCustomEmojiStickersCall{ Call[[]Sticker]{ @@ -5203,14 +5331,14 @@ func (client *Client) GetCustomEmojiStickers(customEmojiIds []string) *GetCustom ) } -// CustomEmojiIds List of custom emoji identifiers. At most 200 custom emoji identifiers can be specified. +// CustomEmojiIds A JSON-serialized list of custom emoji identifiers. At most 200 custom emoji identifiers can be specified. func (call *GetCustomEmojiStickersCall) CustomEmojiIds(customEmojiIds []string) *GetCustomEmojiStickersCall { call.request.JSON("custom_emoji_ids", customEmojiIds) return call } // UploadStickerFileCall reprenesents a call to the uploadStickerFile method. -// Use this method to upload a file with a sticker for later use in the createNewStickerSet and addStickerToSet methods (the file can be used multiple times) +// Use this method to upload a file with a sticker for later use in the createNewStickerSet, addStickerToSet, or replaceStickerInSet methods (the file can be used multiple times) // Returns the uploaded File on success. type UploadStickerFileCall struct { Call[File] @@ -5269,24 +5397,22 @@ type CreateNewStickerSetCall struct { // name - Short name of sticker set, to be used in t.me/addstickers/ URLs (e.g., animals). Can contain only English letters, digits and underscores. Must begin with a letter, can't contain consecutive underscores and must end in "_by_". is case insensitive. 1-64 characters. // title - Sticker set title, 1-64 characters // stickers - A JSON-serialized list of 1-50 initial stickers to be added to the sticker set -// stickerFormat - Format of stickers in the set, must be one of “static”, “animated”, “video” -func NewCreateNewStickerSetCall(userID UserID, name string, title string, stickers []InputSticker, stickerFormat string) *CreateNewStickerSetCall { +func NewCreateNewStickerSetCall(userID UserID, name string, title string, stickers []InputSticker) *CreateNewStickerSetCall { return &CreateNewStickerSetCall{ CallNoResult{ request: NewRequest("createNewStickerSet"). UserID("user_id", userID). String("name", name). String("title", title). - JSON("stickers", stickers). - String("sticker_format", stickerFormat), + JSON("stickers", stickers), }, } } // CreateNewStickerSetCall constructs a new CreateNewStickerSetCall with required parameters. -func (client *Client) CreateNewStickerSet(userID UserID, name string, title string, stickers []InputSticker, stickerFormat string) *CreateNewStickerSetCall { +func (client *Client) CreateNewStickerSet(userID UserID, name string, title string, stickers []InputSticker) *CreateNewStickerSetCall { return BindClient( - NewCreateNewStickerSetCall(userID, name, title, stickers, stickerFormat), + NewCreateNewStickerSetCall(userID, name, title, stickers), client, ) } @@ -5315,12 +5441,6 @@ func (call *CreateNewStickerSetCall) Stickers(stickers []InputSticker) *CreateNe return call } -// StickerFormat Format of stickers in the set, must be one of “static”, “animated”, “video” -func (call *CreateNewStickerSetCall) StickerFormat(stickerFormat string) *CreateNewStickerSetCall { - call.request.String("sticker_format", stickerFormat) - return call -} - // StickerType Type of stickers in the set, pass “regular”, “mask”, or “custom_emoji”. By default, a regular sticker set is created. func (call *CreateNewStickerSetCall) StickerType(stickerType StickerType) *CreateNewStickerSetCall { call.request.Stringer("sticker_type", stickerType) @@ -5335,10 +5455,8 @@ func (call *CreateNewStickerSetCall) NeedsRepainting(needsRepainting bool) *Crea // AddStickerToSetCall reprenesents a call to the addStickerToSet method. // Use this method to add a new sticker to a set created by the bot -// The format of the added sticker must match the format of the other stickers in the set // Emoji sticker sets can have up to 200 stickers -// Animated and video sticker sets can have up to 50 stickers -// Static sticker sets can have up to 120 stickers +// Other sticker sets can have up to 120 stickers type AddStickerToSetCall struct { CallNoResult } @@ -5454,6 +5572,62 @@ func (call *DeleteStickerFromSetCall) Sticker(sticker string) *DeleteStickerFrom return call } +// ReplaceStickerInSetCall reprenesents a call to the replaceStickerInSet method. +// Use this method to replace an existing sticker in a sticker set with a new one +// The method is equivalent to calling deleteStickerFromSet, then addStickerToSet, then setStickerPositionInSet +type ReplaceStickerInSetCall struct { + CallNoResult +} + +// NewReplaceStickerInSetCall constructs a new ReplaceStickerInSetCall with required parameters. +// userID - User identifier of the sticker set owner +// name - Sticker set name +// oldSticker - File identifier of the replaced sticker +// sticker - A JSON-serialized object with information about the added sticker. If exactly the same sticker had already been added to the set, then the set remains unchanged. +func NewReplaceStickerInSetCall(userID UserID, name string, oldSticker string, sticker InputSticker) *ReplaceStickerInSetCall { + return &ReplaceStickerInSetCall{ + CallNoResult{ + request: NewRequest("replaceStickerInSet"). + UserID("user_id", userID). + String("name", name). + String("old_sticker", oldSticker). + JSON("sticker", sticker), + }, + } +} + +// ReplaceStickerInSetCall constructs a new ReplaceStickerInSetCall with required parameters. +func (client *Client) ReplaceStickerInSet(userID UserID, name string, oldSticker string, sticker InputSticker) *ReplaceStickerInSetCall { + return BindClient( + NewReplaceStickerInSetCall(userID, name, oldSticker, sticker), + client, + ) +} + +// UserID User identifier of the sticker set owner +func (call *ReplaceStickerInSetCall) UserID(userID UserID) *ReplaceStickerInSetCall { + call.request.UserID("user_id", userID) + return call +} + +// Name Sticker set name +func (call *ReplaceStickerInSetCall) Name(name string) *ReplaceStickerInSetCall { + call.request.String("name", name) + return call +} + +// OldSticker File identifier of the replaced sticker +func (call *ReplaceStickerInSetCall) OldSticker(oldSticker string) *ReplaceStickerInSetCall { + call.request.String("old_sticker", oldSticker) + return call +} + +// Sticker A JSON-serialized object with information about the added sticker. If exactly the same sticker had already been added to the set, then the set remains unchanged. +func (call *ReplaceStickerInSetCall) Sticker(sticker InputSticker) *ReplaceStickerInSetCall { + call.request.JSON("sticker", sticker) + return call +} + // SetStickerEmojiListCall reprenesents a call to the setStickerEmojiList method. // Use this method to change the list of emoji assigned to a regular or custom emoji sticker // The sticker must belong to a sticker set created by the bot @@ -5619,20 +5793,22 @@ type SetStickerSetThumbnailCall struct { // NewSetStickerSetThumbnailCall constructs a new SetStickerSetThumbnailCall with required parameters. // name - Sticker set name // userID - User identifier of the sticker set owner -func NewSetStickerSetThumbnailCall(name string, userID UserID) *SetStickerSetThumbnailCall { +// format - Format of the thumbnail, must be one of “static” for a .WEBP or .PNG image, “animated” for a .TGS animation, or “video” for a WEBM video +func NewSetStickerSetThumbnailCall(name string, userID UserID, format string) *SetStickerSetThumbnailCall { return &SetStickerSetThumbnailCall{ CallNoResult{ request: NewRequest("setStickerSetThumbnail"). String("name", name). - UserID("user_id", userID), + UserID("user_id", userID). + String("format", format), }, } } // SetStickerSetThumbnailCall constructs a new SetStickerSetThumbnailCall with required parameters. -func (client *Client) SetStickerSetThumbnail(name string, userID UserID) *SetStickerSetThumbnailCall { +func (client *Client) SetStickerSetThumbnail(name string, userID UserID, format string) *SetStickerSetThumbnailCall { return BindClient( - NewSetStickerSetThumbnailCall(name, userID), + NewSetStickerSetThumbnailCall(name, userID, format), client, ) } @@ -5655,6 +5831,12 @@ func (call *SetStickerSetThumbnailCall) Thumbnail(thumbnail FileArg) *SetSticker return call } +// Format Format of the thumbnail, must be one of “static” for a .WEBP or .PNG image, “animated” for a .TGS animation, or “video” for a WEBM video +func (call *SetStickerSetThumbnailCall) Format(format string) *SetStickerSetThumbnailCall { + call.request.String("format", format) + return call +} + // SetCustomEmojiStickerSetThumbnailCall reprenesents a call to the setCustomEmojiStickerSetThumbnail method. // Use this method to set the thumbnail of a custom emoji sticker set type SetCustomEmojiStickerSetThumbnailCall struct { @@ -6355,6 +6537,12 @@ func (client *Client) SendGame(chatID ChatID, gameShortName string) *SendGameCal ) } +// BusinessConnectionID Unique identifier of the business connection on behalf of which the message will be sent +func (call *SendGameCall) BusinessConnectionID(businessConnectionID string) *SendGameCall { + call.request.String("business_connection_id", businessConnectionID) + return call +} + // ChatID Unique identifier for the target chat func (call *SendGameCall) ChatID(chatID ChatID) *SendGameCall { call.request.ChatID("chat_id", chatID) @@ -6391,7 +6579,7 @@ func (call *SendGameCall) ReplyParameters(replyParameters ReplyParameters) *Send return call } -// ReplyMarkup A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. +// ReplyMarkup A JSON-serialized object for an inline keyboard. If empty, one 'Play game_title' button will be shown. If not empty, the first button must launch the game. Not supported for messages sent on behalf of a business account. func (call *SendGameCall) ReplyMarkup(replyMarkup InlineKeyboardMarkup) *SendGameCall { call.request.JSON("reply_markup", replyMarkup) return call diff --git a/tgb/handler.go b/tgb/handler.go index dd82b26..15ab3dc 100644 --- a/tgb/handler.go +++ b/tgb/handler.go @@ -27,6 +27,8 @@ func (handler MessageHandler) Handle(ctx context.Context, update *Update) error update.EditedMessage, update.ChannelPost, update.EditedChannelPost, + update.BusinessMessage, + update.EditedBusinessMessage, ); msg != nil { return handler(ctx, &MessageUpdate{ Message: msg, @@ -199,3 +201,25 @@ func (handler RemovedChatBoostHandler) Handle(ctx context.Context, update *Updat Client: update.Client, }) } + +// BusinessConnection it's typed handler for [BusinessConnectionUpdate]. +type BusinessConnectionHandler func(context.Context, *BusinessConnectionUpdate) error + +func (handler BusinessConnectionHandler) Handle(ctx context.Context, update *Update) error { + return handler(ctx, &BusinessConnectionUpdate{ + BusinessConnection: update.BusinessConnection, + Update: update, + Client: update.Client, + }) +} + +// DeletedBusinessMessageHandler it's typed handler for [DeletedBusinessMessage] +type DeletedBusinessMessageHandler func(context.Context, *DeletedBusinessMessagesUpdate) error + +func (handler DeletedBusinessMessageHandler) Handle(ctx context.Context, update *Update) error { + return handler(ctx, &DeletedBusinessMessagesUpdate{ + BusinessMessagesDeleted: update.DeletedBusinessMessages, + Update: update, + Client: update.Client, + }) +} diff --git a/tgb/router.go b/tgb/router.go index dea89c7..c7c4c5d 100644 --- a/tgb/router.go +++ b/tgb/router.go @@ -177,6 +177,26 @@ func (bot *Router) RemovedChatBoost(handler RemovedChatBoostHandler, filters ... return bot.register(tg.UpdateTypeRemovedChatBoost, handler, filters...) } +// BusinessConnection register handlers for Update with not empty BusinessConnection field. +func (bot *Router) BusinessConnection(handler BusinessConnectionHandler, filters ...Filter) *Router { + return bot.register(tg.UpdateTypeBusinessConnection, handler, filters...) +} + +// BusinessMessage register handlers for Update with not empty BusinessMessage field. +func (bot *Router) BusinessMessage(handler MessageHandler, filters ...Filter) *Router { + return bot.register(tg.UpdateTypeBusinessMessage, handler, filters...) +} + +// EditedBusinessMessage register handlers for Update with not empty EditedBusinessMessage field. +func (bot *Router) EditedBusinessMessage(handler MessageHandler, filters ...Filter) *Router { + return bot.register(tg.UpdateTypeEditedBusinessMessage, handler, filters...) +} + +// DeletedBusinessMessages register handlers for Update with not empty DeletedBusinessMessages field. +func (bot *Router) DeletedBusinessMessages(handler DeletedBusinessMessageHandler, filters ...Filter) *Router { + return bot.register(tg.UpdateTypeDeletedBusinessMessages, handler, filters...) +} + // Error registers a handler for errors. // If any error occurs in the chain, it will be passed to that handler. // By default, errors are returned back by handler method. diff --git a/tgb/router_test.go b/tgb/router_test.go index 7000b53..9ee9249 100644 --- a/tgb/router_test.go +++ b/tgb/router_test.go @@ -443,6 +443,74 @@ func TestRouter(t *testing.T) { assert.NoError(t, err) assert.True(t, isRemovedChatBoostHandlerCalled, "removed chat boosted handler should be called") } + + { + isBusinessConnectionHandlerCalled := false + + router.BusinessConnection(func(ctx context.Context, msg *BusinessConnectionUpdate) error { + assert.NotNil(t, msg.BusinessConnection) + isBusinessConnectionHandlerCalled = true + return nil + }) + + err := router.Handle(ctx, &Update{Update: &tg.Update{ + BusinessConnection: &tg.BusinessConnection{}, + }}) + + assert.NoError(t, err) + assert.True(t, isBusinessConnectionHandlerCalled, "business connection handler should be called") + } + + { + isBusinessMessageHandlerCalled := false + + router.BusinessMessage(func(ctx context.Context, msg *MessageUpdate) error { + assert.NotNil(t, msg.Message) + isBusinessMessageHandlerCalled = true + return nil + }) + + err := router.Handle(ctx, &Update{Update: &tg.Update{ + BusinessMessage: &tg.Message{}, + }}) + + assert.NoError(t, err) + assert.True(t, isBusinessMessageHandlerCalled, "business message handler should be called") + } + + { + isEditedBusinessMessageHandlerCalled := false + + router.EditedBusinessMessage(func(ctx context.Context, msg *MessageUpdate) error { + assert.NotNil(t, msg.Message) + isEditedBusinessMessageHandlerCalled = true + return nil + }) + + err := router.Handle(ctx, &Update{Update: &tg.Update{ + EditedBusinessMessage: &tg.Message{}, + }}) + + assert.NoError(t, err) + assert.True(t, isEditedBusinessMessageHandlerCalled, "edited business message handler should be called") + } + + { + isDeletedBusinessMessagesHandlerCalled := false + + router.DeletedBusinessMessages(func(ctx context.Context, msg *DeletedBusinessMessagesUpdate) error { + assert.NotNil(t, msg.BusinessMessagesDeleted) + isDeletedBusinessMessagesHandlerCalled = true + return nil + }) + + err := router.Handle(ctx, &Update{Update: &tg.Update{ + DeletedBusinessMessages: &tg.BusinessMessagesDeleted{}, + }}) + + assert.NoError(t, err) + assert.True(t, isDeletedBusinessMessagesHandlerCalled, "deleted business messages handler should be called") + } }) t.Run("FilterNotAllow", func(t *testing.T) { diff --git a/tgb/update.go b/tgb/update.go index 02c10c4..ab2d4ae 100644 --- a/tgb/update.go +++ b/tgb/update.go @@ -304,3 +304,16 @@ type RemovedChatBoostUpdate struct { Update *Update Client *tg.Client } + +// BusinessConnectionUpdate it's extend wrapper around [tg.BusinessConnectionUpdate] +type BusinessConnectionUpdate struct { + *tg.BusinessConnection + Update *Update + Client *tg.Client +} + +type DeletedBusinessMessagesUpdate struct { + *tg.BusinessMessagesDeleted + Update *Update + Client *tg.Client +} diff --git a/types_gen.go b/types_gen.go index a2f397c..0132412 100644 --- a/types_gen.go +++ b/types_gen.go @@ -5,6 +5,7 @@ package tg import ( "net/url" + "time" ) // Update this object represents an incoming update.At most one of the optional parameters can be present in any given update. @@ -24,6 +25,18 @@ type Update struct { // Optional. New version of a channel post that is known to the bot and was edited. This update may at times be triggered by changes to message fields that are either unavailable or not actively used by your bot. EditedChannelPost *Message `json:"edited_channel_post,omitempty"` + // Optional. The bot was connected to or disconnected from a business account, or a user edited an existing connection with the bot + BusinessConnection *BusinessConnection `json:"business_connection,omitempty"` + + // Optional. New non-service message from a connected business account + BusinessMessage *Message `json:"business_message,omitempty"` + + // Optional. New version of a message from a connected business account + EditedBusinessMessage *Message `json:"edited_business_message,omitempty"` + + // Optional. Messages were deleted from a connected business account + DeletedBusinessMessages *BusinessMessagesDeleted `json:"deleted_business_messages,omitempty"` + // Optional. A reaction to a message was changed by a user. The bot must be an administrator in the chat and must explicitly specify "message_reaction" in the list of allowed_updates to receive these updates. The update isn't received for reactions set by bots. MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"` @@ -97,6 +110,16 @@ type WebhookInfo struct { AllowedUpdates []UpdateType `json:"allowed_updates,omitempty"` } +// LastErrorDateTime returns time.Time representation of LastErrorDate field. +func (s *WebhookInfo) LastErrorDateTime() time.Time { + return time.Unix(s.LastErrorDate, 0) +} + +// LastSynchronizationErrorDateTime returns time.Time representation of LastSynchronizationErrorDate field. +func (s *WebhookInfo) LastSynchronizationErrorDateTime() time.Time { + return time.Unix(s.LastSynchronizationErrorDate, 0) +} + // User this object represents a Telegram user or bot. type User struct { // Unique identifier for this user or bot. @@ -131,6 +154,9 @@ type User struct { // Optional. True, if the bot supports inline queries. Returned only in getMe. SupportsInlineQueries bool `json:"supports_inline_queries,omitempty"` + + // Optional. True, if the bot can be connected to a Telegram Business account to receive its messages. Returned only in getMe. + CanConnectToBusiness bool `json:"can_connect_to_business,omitempty"` } // Chat this object represents a chat. @@ -162,6 +188,21 @@ type Chat struct { // Optional. If non-empty, the list of all active chat usernames; for private chats, supergroups and channels. Returned only in getChat. ActiveUsernames []string `json:"active_usernames,omitempty"` + // Optional. For private chats, the date of birth of the user. Returned only in getChat. + Birthdate int64 `json:"birthdate,omitempty"` + + // Optional. For private chats with business accounts, the intro of the business. Returned only in getChat. + BusinessIntro *BusinessIntro `json:"business_intro,omitempty"` + + // Optional. For private chats with business accounts, the location of the business. Returned only in getChat. + BusinessLocation *BusinessLocation `json:"business_location,omitempty"` + + // Optional. For private chats with business accounts, the opening hours of the business. Returned only in getChat. + BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours,omitempty"` + + // Optional. For private chats, the personal channel of the user. Returned only in getChat. + PersonalChat *Chat `json:"personal_chat,omitempty"` + // Optional. List of available reactions allowed in the chat. If omitted, then all emoji reactions are allowed. Returned only in getChat. AvailableReactions []ReactionType `json:"available_reactions,omitempty"` @@ -181,7 +222,7 @@ type Chat struct { EmojiStatusCustomEmojiID string `json:"emoji_status_custom_emoji_id,omitempty"` // Optional. Expiration date of the emoji status of the chat or the other party in a private chat, in Unix time, if any. Returned only in getChat. - EmojiStatusExpirationDate int `json:"emoji_status_expiration_date,omitempty"` + EmojiStatusExpirationDate int64 `json:"emoji_status_expiration_date,omitempty"` // Optional. Bio of the other party in a private chat. Returned only in getChat. Bio string `json:"bio,omitempty"` @@ -247,6 +288,16 @@ type Chat struct { Location *ChatLocation `json:"location,omitempty"` } +// BirthdateTime returns time.Time representation of Birthdate field. +func (s *Chat) BirthdateTime() time.Time { + return time.Unix(s.Birthdate, 0) +} + +// EmojiStatusExpirationDateTime returns time.Time representation of EmojiStatusExpirationDate field. +func (s *Chat) EmojiStatusExpirationDateTime() time.Time { + return time.Unix(s.EmojiStatusExpirationDate, 0) +} + // Message this object represents a message. type Message struct { // Unique message identifier inside this chat @@ -264,9 +315,15 @@ type Message struct { // Optional. If the sender of the message boosted the chat, the number of boosts added by the user SenderBoostCount int `json:"sender_boost_count,omitempty"` + // Optional. The bot that actually sent the message on behalf of the business account. Available only for outgoing messages sent on behalf of the connected business account. + SenderBusinessBot *User `json:"sender_business_bot,omitempty"` + // Date the message was sent in Unix time. It is always a positive number, representing a valid date. Date int64 `json:"date"` + // Optional. Unique identifier of the business connection from which the message was received. If non-empty, the message belongs to a chat of the corresponding business account that is independent from any potential bot chat which might share the same identifier. + BusinessConnectionID string `json:"business_connection_id,omitempty"` + // Chat the message belongs to Chat Chat `json:"chat"` @@ -300,6 +357,9 @@ type Message struct { // Optional. True, if the message can't be forwarded HasProtectedContent bool `json:"has_protected_content,omitempty"` + // Optional. True, if the message was sent by an implicit action, for example, as an away or a greeting business message, or as a scheduled message + IsFromOffline bool `json:"is_from_offline,omitempty"` + // Optional. The unique identifier of a media message group this message belongs to MediaGroupID string `json:"media_group_id,omitempty"` @@ -481,6 +541,16 @@ type Message struct { ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"` } +// DateTime returns time.Time representation of Date field. +func (s *Message) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + +// EditDateTime returns time.Time representation of EditDate field. +func (s *Message) EditDateTime() time.Time { + return time.Unix(s.EditDate, 0) +} + // MessageID this object represents a unique message identifier. type MessageID struct { // Unique message identifier @@ -499,6 +569,11 @@ type InaccessibleMessage struct { Date int64 `json:"date"` } +// DateTime returns time.Time representation of Date field. +func (s *InaccessibleMessage) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // MessageEntity this object represents one special entity in a text message. For example, hashtags, usernames, URLs, etc. type MessageEntity struct { // Type of the entity. Currently, can be “mention” (@username), “hashtag” (#hashtag), “cashtag” ($USD), “bot_command” (/start@jobs_bot), “url” (https://telegram.org), “email” (do-not-reply@telegram.org), “phone_number” (+1-212-555-0123), “bold” (bold text), “italic” (italic text), “underline” (underlined text), “strikethrough” (strikethrough text), “spoiler” (spoiler message), “blockquote” (block quotation), “code” (monowidth string), “pre” (monowidth block), “text_link” (for clickable text URLs), “text_mention” (for users without usernames), “custom_emoji” (for inline custom emoji stickers) @@ -615,10 +690,10 @@ type ReplyParameters struct { // Identifier of the message that will be replied to in the current chat, or in the chat chat_id if it is specified MessageID int `json:"message_id"` - // Optional. If the message to be replied to is from a different chat, unique identifier for the chat or username of the channel (in the format @channelusername) + // Optional. If the message to be replied to is from a different chat, unique identifier for the chat or username of the channel (in the format @channelusername). Not supported for messages sent on behalf of a business account. ChatID PeerID `json:"chat_id,omitempty"` - // Optional. Pass True if the message should be sent even if the specified message to be replied to is not found; can be used only for replies in the same chat and forum topic. + // Optional. Pass True if the message should be sent even if the specified message to be replied to is not found. Always False for replies in another chat or forum topic. Always True for messages sent on behalf of a business account. AllowSendingWithoutReply bool `json:"allow_sending_without_reply,omitempty"` // Optional. Quoted part of the message to be replied to; 0-1024 characters after entities parsing. The quote must be an exact substring of the message to be replied to, including bold, italic, underline, strikethrough, spoiler, and custom_emoji entities. The message will fail to send if the quote isn't found in the original message. @@ -646,6 +721,11 @@ type MessageOriginUser struct { SenderUser User `json:"sender_user"` } +// DateTime returns time.Time representation of Date field. +func (s *MessageOriginUser) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // MessageOriginHiddenUser the message was originally sent by an unknown user. type MessageOriginHiddenUser struct { // Type of the message origin, always “hidden_user” @@ -658,6 +738,11 @@ type MessageOriginHiddenUser struct { SenderUserName string `json:"sender_user_name"` } +// DateTime returns time.Time representation of Date field. +func (s *MessageOriginHiddenUser) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // MessageOriginChat the message was originally sent on behalf of a chat to a group chat. type MessageOriginChat struct { // Type of the message origin, always “chat” @@ -673,6 +758,11 @@ type MessageOriginChat struct { AuthorSignature string `json:"author_signature,omitempty"` } +// DateTime returns time.Time representation of Date field. +func (s *MessageOriginChat) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // MessageOriginChannel the message was originally sent to a channel chat. type MessageOriginChannel struct { // Type of the message origin, always “channel” @@ -691,6 +781,11 @@ type MessageOriginChannel struct { AuthorSignature string `json:"author_signature,omitempty"` } +// DateTime returns time.Time representation of Date field. +func (s *MessageOriginChannel) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // PhotoSize this object represents one size of a photo or a file / sticker thumbnail. type PhotoSize struct { // Identifier for this file, which can be used to download or reuse the file @@ -958,17 +1053,22 @@ type Poll struct { OpenPeriod int `json:"open_period,omitempty"` // Optional. Point in time (Unix timestamp) when the poll will be automatically closed - CloseDate int `json:"close_date,omitempty"` + CloseDate int64 `json:"close_date,omitempty"` +} + +// CloseDateTime returns time.Time representation of CloseDate field. +func (s *Poll) CloseDateTime() time.Time { + return time.Unix(s.CloseDate, 0) } // Location this object represents a point on the map. type Location struct { - // Longitude as defined by sender - Longitude float64 `json:"longitude"` - // Latitude as defined by sender Latitude float64 `json:"latitude"` + // Longitude as defined by sender + Longitude float64 `json:"longitude"` + // Optional. The radius of uncertainty for the location, measured in meters; 0-1500 HorizontalAccuracy float64 `json:"horizontal_accuracy,omitempty"` @@ -1060,22 +1160,49 @@ type ForumTopicEdited struct { IconCustomEmojiID string `json:"icon_custom_emoji_id,omitempty"` } +// SharedUser this object contains information about a user that was shared with the bot using a KeyboardButtonRequestUser button. +type SharedUser struct { + // Identifier of the shared user. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. But it has at most 52 significant bits, so 64-bit integers or double-precision float types are safe for storing these identifiers. The bot may not have access to the user and could be unable to use this identifier, unless the user is already known to the bot by some other means. + UserID int `json:"user_id"` + + // Optional. First name of the user, if the name was requested by the bot + FirstName string `json:"first_name,omitempty"` + + // Optional. Last name of the user, if the name was requested by the bot + LastName string `json:"last_name,omitempty"` + + // Optional. Username of the user, if the username was requested by the bot + Username string `json:"username,omitempty"` + + // Optional. Available sizes of the chat photo, if the photo was requested by the bot + Photo []PhotoSize `json:"photo,omitempty"` +} + // UsersShared this object contains information about the users whose identifiers were shared with the bot using a KeyboardButtonRequestUsers button. type UsersShared struct { // Identifier of the request RequestID int `json:"request_id"` - // Identifiers of the shared users. These numbers may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting them. But they have at most 52 significant bits, so 64-bit integers or double-precision float types are safe for storing these identifiers. The bot may not have access to the users and could be unable to use these identifiers, unless the users are already known to the bot by some other means. - UserIDs []UserID `json:"user_ids"` + // Information about users shared with the bot. + Users []SharedUser `json:"users"` } -// ChatShared this object contains information about the chat whose identifier was shared with the bot using a KeyboardButtonRequestChat button. +// ChatShared this object contains information about a chat that was shared with the bot using a KeyboardButtonRequestChat button. type ChatShared struct { // Identifier of the request RequestID int `json:"request_id"` // Identifier of the shared chat. The bot may not have access to the chat and could be unable to use this identifier, unless the chat is already known to the bot by some other means. ChatID ChatID `json:"chat_id"` + + // Optional. Title of the chat, if the title was requested by the bot. + Title string `json:"title,omitempty"` + + // Optional. Username of the chat, if the username was requested by the bot and available. + Username string `json:"username,omitempty"` + + // Optional. Available sizes of the chat photo, if the photo was requested by the bot + Photo []PhotoSize `json:"photo,omitempty"` } // WriteAccessAllowed this object represents a service message about a user allowing a bot to write messages after adding it to the attachment menu, launching a Web App from a link, or accepting an explicit request from a Web App sent by the method requestWriteAccess. @@ -1093,7 +1220,12 @@ type WriteAccessAllowed struct { // VideoChatScheduled this object represents a service message about a video chat scheduled in the chat. type VideoChatScheduled struct { // Point in time (Unix timestamp) when the video chat is supposed to be started by a chat administrator - StartDate int `json:"start_date"` + StartDate int64 `json:"start_date"` +} + +// StartDateTime returns time.Time representation of StartDate field. +func (s *VideoChatScheduled) StartDateTime() time.Time { + return time.Unix(s.StartDate, 0) } // VideoChatEnded this object represents a service message about a video chat ended in the chat. @@ -1114,7 +1246,7 @@ type Giveaway struct { Chats []Chat `json:"chats"` // Point in time (Unix timestamp) when winners of the giveaway will be selected - WinnersSelectionDate int `json:"winners_selection_date"` + WinnersSelectionDate int64 `json:"winners_selection_date"` // The number of users which are supposed to be selected as winners of the giveaway WinnerCount int `json:"winner_count"` @@ -1135,6 +1267,11 @@ type Giveaway struct { PremiumSubscriptionMonthCount int `json:"premium_subscription_month_count,omitempty"` } +// WinnersSelectionDateTime returns time.Time representation of WinnersSelectionDate field. +func (s *Giveaway) WinnersSelectionDateTime() time.Time { + return time.Unix(s.WinnersSelectionDate, 0) +} + // GiveawayWinners this object represents a message about the completion of a giveaway with public winners. type GiveawayWinners struct { // The chat that created the giveaway @@ -1144,7 +1281,7 @@ type GiveawayWinners struct { GiveawayMessageID int `json:"giveaway_message_id"` // Point in time (Unix timestamp) when winners of the giveaway were selected - WinnersSelectionDate int `json:"winners_selection_date"` + WinnersSelectionDate int64 `json:"winners_selection_date"` // Total number of winners in the giveaway WinnerCount int `json:"winner_count"` @@ -1171,6 +1308,11 @@ type GiveawayWinners struct { PrizeDescription string `json:"prize_description,omitempty"` } +// WinnersSelectionDateTime returns time.Time representation of WinnersSelectionDate field. +func (s *GiveawayWinners) WinnersSelectionDateTime() time.Time { + return time.Unix(s.WinnersSelectionDate, 0) +} + // GiveawayCompleted this object represents a service message about the completion of a giveaway without public winners. type GiveawayCompleted struct { // Number of winners in the giveaway @@ -1276,7 +1418,7 @@ type KeyboardButton struct { WebApp *WebAppInfo `json:"web_app,omitempty"` } -// KeyboardButtonRequestUsers this object defines the criteria used to request suitable users. The identifiers of the selected users will be shared with the bot when the corresponding button is pressed. More about requesting users » +// KeyboardButtonRequestUsers this object defines the criteria used to request suitable users. Information about the selected users will be shared with the bot when the corresponding button is pressed. More about requesting users » type KeyboardButtonRequestUsers struct { // Signed 32-bit identifier of the request that will be received back in the UsersShared object. Must be unique within the message RequestID int `json:"request_id"` @@ -1289,9 +1431,18 @@ type KeyboardButtonRequestUsers struct { // Optional. The maximum number of users to be selected; 1-10. Defaults to 1. MaxQuantity int `json:"max_quantity,omitempty"` + + // Optional. Pass True to request the users' first and last name + RequestName bool `json:"request_name,omitempty"` + + // Optional. Pass True to request the users' username + RequestUsername bool `json:"request_username,omitempty"` + + // Optional. Pass True to request the users' photo + RequestPhoto bool `json:"request_photo,omitempty"` } -// KeyboardButtonRequestChat this object defines the criteria used to request a suitable chat. The identifier of the selected chat will be shared with the bot when the corresponding button is pressed. More about requesting chats » +// KeyboardButtonRequestChat this object defines the criteria used to request a suitable chat. Information about the selected chat will be shared with the bot when the corresponding button is pressed. The bot will be granted requested rights in the сhat if appropriate More about requesting chats » type KeyboardButtonRequestChat struct { // Signed 32-bit identifier of the request, which will be received back in the ChatShared object. Must be unique within the message RequestID int `json:"request_id"` @@ -1316,6 +1467,15 @@ type KeyboardButtonRequestChat struct { // Optional. Pass True to request a chat with the bot as a member. Otherwise, no additional restrictions are applied. BotIsMember bool `json:"bot_is_member,omitempty"` + + // Optional. Pass True to request the chat's title + RequestTitle bool `json:"request_title,omitempty"` + + // Optional. Pass True to request the chat's username + RequestUsername bool `json:"request_username,omitempty"` + + // Optional. Pass True to request the chat's photo + RequestPhoto bool `json:"request_photo,omitempty"` } // KeyboardButtonPollType this object represents type of a poll, which is allowed to be created and sent when the corresponding button is pressed. @@ -1477,7 +1637,7 @@ type ChatInviteLink struct { Name string `json:"name,omitempty"` // Optional. Point in time (Unix timestamp) when the link will expire or has been expired - ExpireDate int `json:"expire_date,omitempty"` + ExpireDate int64 `json:"expire_date,omitempty"` // Optional. The maximum number of users that can be members of the chat simultaneously after joining the chat via this invite link; 1-99999 MemberLimit int `json:"member_limit,omitempty"` @@ -1486,6 +1646,11 @@ type ChatInviteLink struct { PendingJoinRequestCount int `json:"pending_join_request_count,omitempty"` } +// ExpireDateTime returns time.Time representation of ExpireDate field. +func (s *ChatInviteLink) ExpireDateTime() time.Time { + return time.Unix(s.ExpireDate, 0) +} + // ChatAdministratorRights represents the rights of an administrator in a chat. type ChatAdministratorRights struct { // True, if the user's presence in the chat is hidden @@ -1521,16 +1686,16 @@ type ChatAdministratorRights struct { // True, if the administrator can delete stories posted by other users CanDeleteStories bool `json:"can_delete_stories"` - // Optional. True, if the administrator can post messages in the channel, or access channel statistics; channels only + // Optional. True, if the administrator can post messages in the channel, or access channel statistics; for channels only CanPostMessages bool `json:"can_post_messages,omitempty"` - // Optional. True, if the administrator can edit messages of other users and can pin messages; channels only + // Optional. True, if the administrator can edit messages of other users and can pin messages; for channels only CanEditMessages bool `json:"can_edit_messages,omitempty"` - // Optional. True, if the user is allowed to pin messages; groups and supergroups only + // Optional. True, if the user is allowed to pin messages; for groups and supergroups only CanPinMessages bool `json:"can_pin_messages,omitempty"` - // Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only + // Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; for supergroups only CanManageTopics bool `json:"can_manage_topics,omitempty"` } @@ -1543,7 +1708,7 @@ type ChatMemberUpdated struct { From User `json:"from"` // Date the change was done in Unix time - Date int `json:"date"` + Date int64 `json:"date"` // Previous information about the chat member OldChatMember ChatMember `json:"old_chat_member"` @@ -1558,6 +1723,11 @@ type ChatMemberUpdated struct { ViaChatFolderInviteLink bool `json:"via_chat_folder_invite_link,omitempty"` } +// DateTime returns time.Time representation of Date field. +func (s *ChatMemberUpdated) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // ChatMember this object contains information about one member of a chat. Currently, the following 6 types of chat members are supported: type ChatMember struct { // The member's status in the chat, always “creator” @@ -1632,16 +1802,16 @@ type ChatMemberAdministrator struct { // True, if the administrator can delete stories posted by other users CanDeleteStories bool `json:"can_delete_stories"` - // Optional. True, if the administrator can post messages in the channel, or access channel statistics; channels only + // Optional. True, if the administrator can post messages in the channel, or access channel statistics; for channels only CanPostMessages bool `json:"can_post_messages,omitempty"` - // Optional. True, if the administrator can edit messages of other users and can pin messages; channels only + // Optional. True, if the administrator can edit messages of other users and can pin messages; for channels only CanEditMessages bool `json:"can_edit_messages,omitempty"` - // Optional. True, if the user is allowed to pin messages; groups and supergroups only + // Optional. True, if the user is allowed to pin messages; for groups and supergroups only CanPinMessages bool `json:"can_pin_messages,omitempty"` - // Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; supergroups only + // Optional. True, if the user is allowed to create, rename, close, and reopen forum topics; for supergroups only CanManageTopics bool `json:"can_manage_topics,omitempty"` // Optional. Custom title for this user @@ -1711,7 +1881,12 @@ type ChatMemberRestricted struct { CanManageTopics bool `json:"can_manage_topics"` // Date when restrictions will be lifted for this user; Unix time. If 0, then the user is restricted forever - UntilDate int `json:"until_date"` + UntilDate int64 `json:"until_date"` +} + +// UntilDateTime returns time.Time representation of UntilDate field. +func (s *ChatMemberRestricted) UntilDateTime() time.Time { + return time.Unix(s.UntilDate, 0) } // ChatMemberLeft represents a chat member that isn't currently a member of the chat, but may join it themselves. @@ -1732,7 +1907,12 @@ type ChatMemberBanned struct { User User `json:"user"` // Date when restrictions will be lifted for this user; Unix time. If 0, then the user is banned forever - UntilDate int `json:"until_date"` + UntilDate int64 `json:"until_date"` +} + +// UntilDateTime returns time.Time representation of UntilDate field. +func (s *ChatMemberBanned) UntilDateTime() time.Time { + return time.Unix(s.UntilDate, 0) } // ChatJoinRequest represents a join request sent to a chat. @@ -1747,7 +1927,7 @@ type ChatJoinRequest struct { UserChatID ChatID `json:"user_chat_id"` // Date the request was sent in Unix time - Date int `json:"date"` + Date int64 `json:"date"` // Optional. Bio of the user. Bio string `json:"bio,omitempty"` @@ -1756,6 +1936,11 @@ type ChatJoinRequest struct { InviteLink *ChatInviteLink `json:"invite_link,omitempty"` } +// DateTime returns time.Time representation of Date field. +func (s *ChatJoinRequest) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // ChatPermissions describes actions that a non-administrator user is allowed to take in a chat. type ChatPermissions struct { // Optional. True, if the user is allowed to send text messages, contacts, giveaways, giveaway winners, invoices, locations and venues @@ -1801,6 +1986,57 @@ type ChatPermissions struct { CanManageTopics bool `json:"can_manage_topics,omitempty"` } +// Birthdate +type Birthdate struct { + // Day of the user's birth; 1-31 + Day int `json:"day"` + + // Month of the user's birth; 1-12 + Month int `json:"month"` + + // Optional. Year of the user's birth + Year int `json:"year,omitempty"` +} + +// BusinessIntro +type BusinessIntro struct { + // Optional. Title text of the business intro + Title string `json:"title,omitempty"` + + // Optional. Message text of the business intro + Message string `json:"message,omitempty"` + + // Optional. Sticker of the business intro + Sticker *Sticker `json:"sticker,omitempty"` +} + +// BusinessLocation +type BusinessLocation struct { + // Address of the business + Address string `json:"address"` + + // Optional. Location of the business + Location *Location `json:"location,omitempty"` +} + +// BusinessOpeningHoursInterval +type BusinessOpeningHoursInterval struct { + // The minute's sequence number in a week, starting on Monday, marking the start of the time interval during which the business is open; 0 - 7 * 24 * 60 + OpeningMinute int `json:"opening_minute"` + + // The minute's sequence number in a week, starting on Monday, marking the end of the time interval during which the business is open; 0 - 8 * 24 * 60 + ClosingMinute int `json:"closing_minute"` +} + +// BusinessOpeningHours +type BusinessOpeningHours struct { + // Unique name of the time zone for which the opening hours are defined + TimeZoneName string `json:"time_zone_name"` + + // List of time intervals describing business opening hours + OpeningHours []BusinessOpeningHoursInterval `json:"opening_hours"` +} + // ChatLocation represents a location to which a chat is connected. type ChatLocation struct { // The location to which the supergroup is connected. Can't be a live location. @@ -1852,7 +2088,7 @@ type MessageReactionUpdated struct { ActorChat *Chat `json:"actor_chat,omitempty"` // Date of the change in Unix time - Date int `json:"date"` + Date int64 `json:"date"` // Previous list of reaction types that were set by the user OldReaction []ReactionType `json:"old_reaction"` @@ -1861,6 +2097,11 @@ type MessageReactionUpdated struct { NewReaction []ReactionType `json:"new_reaction"` } +// DateTime returns time.Time representation of Date field. +func (s *MessageReactionUpdated) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // MessageReactionCountUpdated this object represents reaction changes on a message with anonymous reactions. type MessageReactionCountUpdated struct { // The chat containing the message @@ -1870,12 +2111,17 @@ type MessageReactionCountUpdated struct { MessageID int `json:"message_id"` // Date of the change in Unix time - Date int `json:"date"` + Date int64 `json:"date"` // List of reactions that are present on the message Reactions []ReactionCount `json:"reactions"` } +// DateTime returns time.Time representation of Date field. +func (s *MessageReactionCountUpdated) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + // ForumTopic this object represents a forum topic. type ForumTopic struct { // Unique identifier of the forum topic @@ -2044,15 +2290,25 @@ type ChatBoost struct { BoostID string `json:"boost_id"` // Point in time (Unix timestamp) when the chat was boosted - AddDate int `json:"add_date"` + AddDate int64 `json:"add_date"` // Point in time (Unix timestamp) when the boost will automatically expire, unless the booster's Telegram Premium subscription is prolonged - ExpirationDate int `json:"expiration_date"` + ExpirationDate int64 `json:"expiration_date"` // Source of the added boost Source ChatBoostSource `json:"source"` } +// AddDateTime returns time.Time representation of AddDate field. +func (s *ChatBoost) AddDateTime() time.Time { + return time.Unix(s.AddDate, 0) +} + +// ExpirationDateTime returns time.Time representation of ExpirationDate field. +func (s *ChatBoost) ExpirationDateTime() time.Time { + return time.Unix(s.ExpirationDate, 0) +} + // ChatBoostUpdated this object represents a boost added to a chat or changed. type ChatBoostUpdated struct { // Chat which was boosted @@ -2071,18 +2327,61 @@ type ChatBoostRemoved struct { BoostID string `json:"boost_id"` // Point in time (Unix timestamp) when the boost was removed - RemoveDate int `json:"remove_date"` + RemoveDate int64 `json:"remove_date"` // Source of the removed boost Source ChatBoostSource `json:"source"` } +// RemoveDateTime returns time.Time representation of RemoveDate field. +func (s *ChatBoostRemoved) RemoveDateTime() time.Time { + return time.Unix(s.RemoveDate, 0) +} + // UserChatBoosts this object represents a list of boosts added to a chat by a user. type UserChatBoosts struct { // The list of boosts added to the chat by the user Boosts []ChatBoost `json:"boosts"` } +// BusinessConnection describes the connection of the bot with a business account. +type BusinessConnection struct { + // Unique identifier of the business connection + ID string `json:"id"` + + // Business account user that created the business connection + User User `json:"user"` + + // Identifier of a private chat with the user who created the business connection. + UserChatID int64 `json:"user_chat_id"` + + // Date the connection was established in Unix time + Date int64 `json:"date"` + + // True, if the bot can act on behalf of the business account in chats that were active in the last 24 hours + CanReply bool `json:"can_reply"` + + // True, if the connection is active + IsEnabled bool `json:"is_enabled"` +} + +// DateTime returns time.Time representation of Date field. +func (s *BusinessConnection) DateTime() time.Time { + return time.Unix(s.Date, 0) +} + +// BusinessMessagesDeleted this object is received when messages are deleted from a connected business account. +type BusinessMessagesDeleted struct { + // Unique identifier of the business connection + BusinessConnectionID string `json:"business_connection_id"` + + // Information about a chat in the business account. The bot may not have access to the chat or the corresponding user. + Chat Chat `json:"chat"` + + // A JSON-serialized list of identifiers of deleted messages in the chat of the business account + MessageIds []int `json:"message_ids"` +} + // ResponseParameters describes why a request was unsuccessful. type ResponseParameters struct { // Optional. The group has been migrated to a supergroup with the specified identifier. @@ -2295,12 +2594,6 @@ type StickerSet struct { // Type of stickers in the set, currently one of “regular”, “mask”, “custom_emoji” StickerType StickerType `json:"sticker_type"` - // True, if the sticker set contains animated stickers - IsAnimated bool `json:"is_animated"` - - // True, if the sticker set contains video stickers - IsVideo bool `json:"is_video"` - // List of all set stickers Stickers []Sticker `json:"stickers"` @@ -2328,6 +2621,9 @@ type InputSticker struct { // The added sticker. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, upload a new one using multipart/form-data, or pass “attach://” to upload a new one using multipart/form-data under name. Animated and video stickers can't be uploaded via HTTP URL. More information on Sending Files » Sticker FileArg `json:"sticker"` + // Format of the added sticker, must be one of “static” for a .WEBP or .PNG image, “animated” for a .TGS animation, “video” for a WEBM video + Format string `json:"format"` + // List of 1-20 emoji associated with the sticker EmojiList []string `json:"emoji_list"` @@ -3403,7 +3699,12 @@ type PassportFile struct { FileSize int `json:"file_size"` // Unix time when the file was uploaded - FileDate int `json:"file_date"` + FileDate int64 `json:"file_date"` +} + +// FileDateTime returns time.Time representation of FileDate field. +func (s *PassportFile) FileDateTime() time.Time { + return time.Unix(s.FileDate, 0) } // EncryptedPassportElement describes documents or other Telegram Passport elements shared with the bot by the user. @@ -3411,28 +3712,28 @@ type EncryptedPassportElement struct { // Element type. One of “personal_details”, “passport”, “driver_license”, “identity_card”, “internal_passport”, “address”, “utility_bill”, “bank_statement”, “rental_agreement”, “passport_registration”, “temporary_registration”, “phone_number”, “email”. Type string `json:"type"` - // Optional. Base64-encoded encrypted Telegram Passport element data provided by the user, available for “personal_details”, “passport”, “driver_license”, “identity_card”, “internal_passport” and “address” types. Can be decrypted and verified using the accompanying EncryptedCredentials. + // Optional. Base64-encoded encrypted Telegram Passport element data provided by the user; available only for “personal_details”, “passport”, “driver_license”, “identity_card”, “internal_passport” and “address” types. Can be decrypted and verified using the accompanying EncryptedCredentials. Data string `json:"data,omitempty"` - // Optional. User's verified phone number, available only for “phone_number” type + // Optional. User's verified phone number; available only for “phone_number” type PhoneNumber string `json:"phone_number,omitempty"` - // Optional. User's verified email address, available only for “email” type + // Optional. User's verified email address; available only for “email” type Email string `json:"email,omitempty"` - // Optional. Array of encrypted files with documents provided by the user, available for “utility_bill”, “bank_statement”, “rental_agreement”, “passport_registration” and “temporary_registration” types. Files can be decrypted and verified using the accompanying EncryptedCredentials. + // Optional. Array of encrypted files with documents provided by the user; available only for “utility_bill”, “bank_statement”, “rental_agreement”, “passport_registration” and “temporary_registration” types. Files can be decrypted and verified using the accompanying EncryptedCredentials. Files []PassportFile `json:"files,omitempty"` - // Optional. Encrypted file with the front side of the document, provided by the user. Available for “passport”, “driver_license”, “identity_card” and “internal_passport”. The file can be decrypted and verified using the accompanying EncryptedCredentials. + // Optional. Encrypted file with the front side of the document, provided by the user; available only for “passport”, “driver_license”, “identity_card” and “internal_passport”. The file can be decrypted and verified using the accompanying EncryptedCredentials. FrontSide *PassportFile `json:"front_side,omitempty"` - // Optional. Encrypted file with the reverse side of the document, provided by the user. Available for “driver_license” and “identity_card”. The file can be decrypted and verified using the accompanying EncryptedCredentials. + // Optional. Encrypted file with the reverse side of the document, provided by the user; available only for “driver_license” and “identity_card”. The file can be decrypted and verified using the accompanying EncryptedCredentials. ReverseSide *PassportFile `json:"reverse_side,omitempty"` - // Optional. Encrypted file with the selfie of the user holding a document, provided by the user; available for “passport”, “driver_license”, “identity_card” and “internal_passport”. The file can be decrypted and verified using the accompanying EncryptedCredentials. + // Optional. Encrypted file with the selfie of the user holding a document, provided by the user; available if requested for “passport”, “driver_license”, “identity_card” and “internal_passport”. The file can be decrypted and verified using the accompanying EncryptedCredentials. Selfie *PassportFile `json:"selfie,omitempty"` - // Optional. Array of encrypted files with translated versions of documents provided by the user. Available if requested for “passport”, “driver_license”, “identity_card”, “internal_passport”, “utility_bill”, “bank_statement”, “rental_agreement”, “passport_registration” and “temporary_registration” types. Files can be decrypted and verified using the accompanying EncryptedCredentials. + // Optional. Array of encrypted files with translated versions of documents provided by the user; available if requested for “passport”, “driver_license”, “identity_card”, “internal_passport”, “utility_bill”, “bank_statement”, “rental_agreement”, “passport_registration” and “temporary_registration” types. Files can be decrypted and verified using the accompanying EncryptedCredentials. Translation []PassportFile `json:"translation,omitempty"` // Base64-encoded element hash for using in PassportElementErrorUnspecified @@ -3675,6 +3976,11 @@ type WebAppInitData struct { raw url.Values } +// AuthDateTime returns time.Time representation of AuthDate field. +func (s *WebAppInitData) AuthDateTime() time.Time { + return time.Unix(s.AuthDate, 0) +} + // WebAppUser this object contains the data of the Mini App user. type WebAppUser struct { // A unique identifier for the user or bot. This number may have more than 32 significant bits and some programming languages may have difficulty/silent defects in interpreting it. It has at most 52 significant bits, so a 64-bit integer or a double-precision float type is safe for storing this identifier. diff --git a/types_gen_ext.go b/types_gen_ext.go index b6fbd21..6dce6d5 100644 --- a/types_gen_ext.go +++ b/types_gen_ext.go @@ -1082,6 +1082,10 @@ const ( UpdateTypeMessageReactionCount UpdateTypeChatBoost UpdateTypeRemovedChatBoost + UpdateTypeBusinessConnection + UpdateTypeBusinessMessage + UpdateTypeEditedBusinessMessage + UpdateTypeDeletedBusinessMessages ) // MarshalText implements encoding.TextMarshaler. @@ -1132,6 +1136,14 @@ func (typ *UpdateType) UnmarshalText(v []byte) error { *typ = UpdateTypeChatBoost case "removed_chat_boost": *typ = UpdateTypeRemovedChatBoost + case "business_connection": + *typ = UpdateTypeBusinessConnection + case "business_message": + *typ = UpdateTypeBusinessMessage + case "edited_business_message": + *typ = UpdateTypeEditedBusinessMessage + case "deleted_business_messages": + *typ = UpdateTypeDeletedBusinessMessages default: return fmt.Errorf("unknown update type") } @@ -1161,6 +1173,10 @@ func (typ UpdateType) String() string { "message_reaction_count", "chat_boost", "removed_chat_boost", + "business_connection", + "business_message", + "edited_business_message", + "deleted_business_messages", }[typ-1] } @@ -1205,6 +1221,14 @@ func (update *Update) Type() UpdateType { return UpdateTypeChatBoost case update.RemovedChatBoost != nil: return UpdateTypeRemovedChatBoost + case update.BusinessConnection != nil: + return UpdateTypeBusinessConnection + case update.BusinessMessage != nil: + return UpdateTypeBusinessMessage + case update.EditedBusinessMessage != nil: + return UpdateTypeEditedBusinessMessage + case update.DeletedBusinessMessages != nil: + return UpdateTypeDeletedBusinessMessages default: return UpdateTypeUnknown } @@ -1226,6 +1250,10 @@ func (update *Update) Msg() *Message { return update.EditedChannelPost case update.CallbackQuery != nil && update.CallbackQuery.Message != nil && update.CallbackQuery.Message.Message != nil: return update.CallbackQuery.Message.Message + case update.BusinessMessage != nil: + return update.BusinessMessage + case update.EditedBusinessMessage != nil: + return update.EditedBusinessMessage default: return nil } diff --git a/types_gen_ext_test.go b/types_gen_ext_test.go index 5c731ca..0699322 100644 --- a/types_gen_ext_test.go +++ b/types_gen_ext_test.go @@ -839,6 +839,10 @@ func TestUpdateType_UnmarshalText(t *testing.T) { {"message_reaction_count", UpdateTypeMessageReactionCount, false}, {"chat_boost", UpdateTypeChatBoost, false}, {"removed_chat_boost", UpdateTypeRemovedChatBoost, false}, + {"business_connection", UpdateTypeBusinessConnection, false}, + {"business_message", UpdateTypeBusinessMessage, false}, + {"edited_business_message", UpdateTypeEditedBusinessMessage, false}, + {"deleted_business_messages", UpdateTypeDeletedBusinessMessages, false}, {"test", UpdateTypeUnknown, true}, } { t.Run(test.Text, func(t *testing.T) { @@ -959,6 +963,22 @@ func TestUpdate_Type(t *testing.T) { Update: &Update{RemovedChatBoost: &ChatBoostRemoved{}}, Want: UpdateTypeRemovedChatBoost, }, + { + Update: &Update{BusinessConnection: &BusinessConnection{}}, + Want: UpdateTypeBusinessConnection, + }, + { + Update: &Update{BusinessMessage: &Message{}}, + Want: UpdateTypeBusinessMessage, + }, + { + Update: &Update{EditedBusinessMessage: &Message{}}, + Want: UpdateTypeEditedBusinessMessage, + }, + { + Update: &Update{DeletedBusinessMessages: &BusinessMessagesDeleted{}}, + Want: UpdateTypeDeletedBusinessMessages, + }, } { assert.Equal(t, test.Want, test.Update.Type()) } @@ -1104,6 +1124,8 @@ func TestUpdate_Msg(t *testing.T) { Message: msg, }}}, msg}, {&Update{CallbackQuery: &CallbackQuery{}}, nil}, + {&Update{BusinessMessage: msg}, msg}, + {&Update{EditedBusinessMessage: msg}, msg}, } { assert.Equal(t, test.Message, test.Update.Msg()) }