0

[WIP] Update deps

This commit is contained in:
eleksir
2024-07-24 22:38:25 +03:00
parent 618110a7b2
commit a6960d0e86
253 changed files with 15130 additions and 5831 deletions

View File

@@ -1,4 +1,4 @@
| <img src="assets/readme_banner.png" alt="logo" width="800"><br/><br/> [![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/) [![PkgGoDev](https://pkg.go.dev/badge/github.com/NicoNex/echotron/v3)](https://pkg.go.dev/github.com/NicoNex/echotron/v3) [![Go Report Card](https://goreportcard.com/badge/github.com/NicoNex/echotron/v3)](https://goreportcard.com/report/github.com/NicoNex/echotron/v3) [![License](http://img.shields.io/badge/license-LGPL3.0-orange.svg?style=flat)](https://github.com/NicoNex/echotron/blob/master/LICENSE) [![Coverage Status](https://coveralls.io/repos/github/NicoNex/echotron/badge.svg?branch=master)](https://coveralls.io/github/NicoNex/echotron?branch=master) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go) [![Telegram](https://img.shields.io/badge/Echotron%20News-blue?logo=telegram&style=flat)](https://t.me/echotronnews) |
| <img src="assets/readme_banner.png" alt="logo" width="800"><br/><br/> [![Language](https://img.shields.io/badge/Language-Go-blue.svg)](https://golang.org/) [![PkgGoDev](https://pkg.go.dev/badge/github.com/NicoNex/echotron/v3)](https://pkg.go.dev/github.com/NicoNex/echotron/v3) [![Go Report Card](https://goreportcard.com/badge/github.com/NicoNex/echotron/v3)](https://goreportcard.com/report/github.com/NicoNex/echotron/v3) [![codecov](https://codecov.io/gh/NicoNex/echotron/graph/badge.svg?token=LVJGOEYL5M)](https://codecov.io/gh/NicoNex/echotron) [![License](http://img.shields.io/badge/license-LGPL3.0-orange.svg?style=flat)](https://github.com/NicoNex/echotron/blob/master/LICENSE) [![Mentioned in Awesome Go](https://awesome.re/mentioned-badge.svg)](https://github.com/avelino/awesome-go) [![Telegram](https://img.shields.io/badge/Echotron%20News-blue?logo=telegram&style=flat)](https://t.me/echotronnews) |
| :------: |
**Echotron** is an elegant and concurrent library for the Telegram bot API in Go.

View File

@@ -27,21 +27,32 @@ import (
// API is the object that contains all the functions that wrap those of the Telegram Bot API.
type API struct {
token string
base string
client *client
token string
base string
}
// NewAPI returns a new API object.
func NewAPI(token string) API {
return API{
token: token,
base: fmt.Sprintf("https://api.telegram.org/bot%s/", token),
token: token,
base: fmt.Sprintf("https://api.telegram.org/bot%s/", token),
client: lclient,
}
}
// NewLocalAPI is like NewAPI but allows to use a local API server.
func NewLocalAPI(url, token string) API {
return API{
token: token,
base: url,
client: lclient,
}
}
// GetUpdates is used to receive incoming updates using long polling.
func (a API) GetUpdates(opts *UpdateOptions) (res APIResponseUpdate, err error) {
return get[APIResponseUpdate](a.base, "getUpdates", urlValues(opts))
return res, a.client.get(a.base, "getUpdates", urlValues(opts), &res)
}
// SetWebhook is used to specify a url and receive incoming updates via an outgoing webhook.
@@ -60,7 +71,7 @@ func (a API) SetWebhook(webhookURL string, dropPendingUpdates bool, opts *Webhoo
addValues(vals, opts)
url = fmt.Sprintf("%s?%s", strings.TrimSuffix(url, "/"), vals.Encode())
cnt, err := sendPostForm(url, keyVal)
cnt, err := a.client.doPostForm(url, keyVal)
if err != nil {
return
}
@@ -78,17 +89,17 @@ func (a API) DeleteWebhook(dropPendingUpdates bool) (res APIResponseBase, err er
var vals = make(url.Values)
vals.Set("drop_pending_updates", btoa(dropPendingUpdates))
return get[APIResponseBase](a.base, "deleteWebhook", vals)
return res, a.client.get(a.base, "deleteWebhook", vals, &res)
}
// GetWebhookInfo is used to get current webhook status.
func (a API) GetWebhookInfo() (res APIResponseWebhook, err error) {
return get[APIResponseWebhook](a.base, "getWebhookInfo", nil)
return res, a.client.get(a.base, "getWebhookInfo", nil, &res)
}
// GetMe is a simple method for testing your bot's auth token.
func (a API) GetMe() (res APIResponseUser, err error) {
return get[APIResponseUser](a.base, "getMe", nil)
return res, a.client.get(a.base, "getMe", nil, &res)
}
// LogOut is used to log out from the cloud Bot API server before launching the bot locally.
@@ -96,14 +107,14 @@ func (a API) GetMe() (res APIResponseUser, err error) {
// After a successful call, you can immediately log in on a local server,
// but will not be able to log in back to the cloud Bot API server for 10 minutes.
func (a API) LogOut() (res APIResponseBool, err error) {
return get[APIResponseBool](a.base, "logOut", nil)
return res, a.client.get(a.base, "logOut", nil, &res)
}
// Close is used to close the bot instance before moving it from one local server to another.
// You need to delete the webhook before calling this method to ensure that the bot isn't launched again after server restart.
// The method will return error 429 in the first 10 minutes after the bot is launched.
func (a API) Close() (res APIResponseBool, err error) {
return get[APIResponseBool](a.base, "close", nil)
return res, a.client.get(a.base, "close", nil, &res)
}
// SendMessage is used to send text messages.
@@ -112,7 +123,7 @@ func (a API) SendMessage(text string, chatID int64, opts *MessageOptions) (res A
vals.Set("text", text)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseMessage](a.base, "sendMessage", addValues(vals, opts))
return res, a.client.get(a.base, "sendMessage", addValues(vals, opts), &res)
}
// ForwardMessage is used to forward messages of any kind.
@@ -123,7 +134,7 @@ func (a API) ForwardMessage(chatID, fromChatID int64, messageID int, opts *Forwa
vals.Set("chat_id", itoa(chatID))
vals.Set("from_chat_id", itoa(fromChatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponseMessage](a.base, "forwardMessage", addValues(vals, opts))
return res, a.client.get(a.base, "forwardMessage", addValues(vals, opts), &res)
}
// ForwardMessages is used to forward multiple messages of any kind.
@@ -141,7 +152,7 @@ func (a API) ForwardMessages(chatID, fromChatID int64, messageIDs []int, opts *F
vals.Set("chat_id", itoa(chatID))
vals.Set("from_chat_id", itoa(fromChatID))
vals.Set("message_ids", string(msgIDs))
return get[APIResponseMessageIDs](a.base, "forwardMessages", addValues(vals, opts))
return res, a.client.get(a.base, "forwardMessages", addValues(vals, opts), &res)
}
// CopyMessage is used to copy messages of any kind.
@@ -154,7 +165,7 @@ func (a API) CopyMessage(chatID, fromChatID int64, messageID int, opts *CopyOpti
vals.Set("chat_id", itoa(chatID))
vals.Set("from_chat_id", itoa(fromChatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponseMessageID](a.base, "copyMessage", addValues(vals, opts))
return res, a.client.get(a.base, "copyMessage", addValues(vals, opts), &res)
}
// CopyMessages is used to copy messages of any kind.
@@ -174,7 +185,7 @@ func (a API) CopyMessages(chatID, fromChatID int64, messageIDs []int, opts *Copy
vals.Set("chat_id", itoa(chatID))
vals.Set("from_chat_id", itoa(fromChatID))
vals.Set("message_ids", string(msgIDs))
return get[APIResponseMessageIDs](a.base, "copyMessages", addValues(vals, opts))
return res, a.client.get(a.base, "copyMessages", addValues(vals, opts), &res)
}
// SendPhoto is used to send photos.
@@ -182,7 +193,7 @@ func (a API) SendPhoto(file InputFile, chatID int64, opts *PhotoOptions) (res AP
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendPhoto", "photo", file, InputFile{}, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendPhoto", "photo", file, InputFile{}, addValues(vals, opts), &res)
}
// SendAudio is used to send audio files,
@@ -199,7 +210,7 @@ func (a API) SendAudio(file InputFile, chatID int64, opts *AudioOptions) (res AP
}
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendAudio", "audio", file, thumbnail, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendAudio", "audio", file, thumbnail, addValues(vals, opts), &res)
}
// SendDocument is used to send general files.
@@ -214,7 +225,7 @@ func (a API) SendDocument(file InputFile, chatID int64, opts *DocumentOptions) (
}
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendDocument", "document", file, thumbnail, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendDocument", "document", file, thumbnail, addValues(vals, opts), &res)
}
// SendVideo is used to send video files.
@@ -230,7 +241,7 @@ func (a API) SendVideo(file InputFile, chatID int64, opts *VideoOptions) (res AP
}
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendVideo", "video", file, thumbnail, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendVideo", "video", file, thumbnail, addValues(vals, opts), &res)
}
// SendAnimation is used to send animation files (GIF or H.264/MPEG-4 AVC video without sound).
@@ -245,7 +256,7 @@ func (a API) SendAnimation(file InputFile, chatID int64, opts *AnimationOptions)
}
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendAnimation", "animation", file, thumbnail, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendAnimation", "animation", file, thumbnail, addValues(vals, opts), &res)
}
// SendVoice is used to send audio files, if you want Telegram clients to display the file as a playable voice message.
@@ -254,7 +265,7 @@ func (a API) SendVoice(file InputFile, chatID int64, opts *VoiceOptions) (res AP
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendVoice", "voice", file, InputFile{}, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendVoice", "voice", file, InputFile{}, addValues(vals, opts), &res)
}
// SendVideoNote is used to send video messages.
@@ -269,7 +280,7 @@ func (a API) SendVideoNote(file InputFile, chatID int64, opts *VideoNoteOptions)
}
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseMessage](a.base, "sendVideoNote", "video_note", file, thumbnail, addValues(vals, opts))
return res, a.client.postFile(a.base, "sendVideoNote", "video_note", file, thumbnail, addValues(vals, opts), &res)
}
// SendMediaGroup is used to send a group of photos, videos, documents or audios as an album.
@@ -278,7 +289,7 @@ func (a API) SendMediaGroup(chatID int64, media []GroupableInputMedia, opts *Med
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return postMedia[APIResponseMessageArray](a.base, "sendMediaGroup", false, addValues(vals, opts), toInputMedia(media)...)
return res, a.client.postMedia(a.base, "sendMediaGroup", false, addValues(vals, opts), &res, toInputMedia(media)...)
}
// SendLocation is used to send point on the map.
@@ -288,7 +299,7 @@ func (a API) SendLocation(chatID int64, latitude, longitude float64, opts *Locat
vals.Set("chat_id", itoa(chatID))
vals.Set("latitude", ftoa(latitude))
vals.Set("longitude", ftoa(longitude))
return get[APIResponseMessage](a.base, "sendLocation", addValues(vals, opts))
return res, a.client.get(a.base, "sendLocation", addValues(vals, opts), &res)
}
// EditMessageLiveLocation is used to edit live location messages.
@@ -298,12 +309,12 @@ func (a API) EditMessageLiveLocation(msg MessageIDOptions, latitude, longitude f
vals.Set("latitude", ftoa(latitude))
vals.Set("longitude", ftoa(longitude))
return get[APIResponseMessage](a.base, "editMessageLiveLocation", addValues(addValues(vals, msg), opts))
return res, a.client.get(a.base, "editMessageLiveLocation", addValues(addValues(vals, msg), opts), &res)
}
// StopMessageLiveLocation is used to stop updating a live location message before `LivePeriod` expires.
func (a API) StopMessageLiveLocation(msg MessageIDOptions, opts *MessageReplyMarkup) (res APIResponseMessage, err error) {
return get[APIResponseMessage](a.base, "stopMessageLiveLocation", addValues(urlValues(msg), opts))
func (a API) StopMessageLiveLocation(msg MessageIDOptions, opts *StopLocationOptions) (res APIResponseMessage, err error) {
return res, a.client.get(a.base, "stopMessageLiveLocation", addValues(urlValues(msg), opts), &res)
}
// SendVenue is used to send information about a venue.
@@ -315,7 +326,7 @@ func (a API) SendVenue(chatID int64, latitude, longitude float64, title, address
vals.Set("longitude", ftoa(longitude))
vals.Set("title", title)
vals.Set("address", address)
return get[APIResponseMessage](a.base, "sendVenue", addValues(vals, opts))
return res, a.client.get(a.base, "sendVenue", addValues(vals, opts), &res)
}
// SendContact is used to send phone contacts.
@@ -325,11 +336,11 @@ func (a API) SendContact(phoneNumber, firstName string, chatID int64, opts *Cont
vals.Set("chat_id", itoa(chatID))
vals.Set("phone_number", phoneNumber)
vals.Set("first_name", firstName)
return get[APIResponseMessage](a.base, "sendContact", addValues(vals, opts))
return res, a.client.get(a.base, "sendContact", addValues(vals, opts), &res)
}
// SendPoll is used to send a native poll.
func (a API) SendPoll(chatID int64, question string, options []string, opts *PollOptions) (res APIResponseMessage, err error) {
func (a API) SendPoll(chatID int64, question string, options []InputPollOption, opts *PollOptions) (res APIResponseMessage, err error) {
var vals = make(url.Values)
pollOpts, err := json.Marshal(options)
@@ -340,7 +351,7 @@ func (a API) SendPoll(chatID int64, question string, options []string, opts *Pol
vals.Set("chat_id", itoa(chatID))
vals.Set("question", question)
vals.Set("options", string(pollOpts))
return get[APIResponseMessage](a.base, "sendPoll", addValues(vals, opts))
return res, a.client.get(a.base, "sendPoll", addValues(vals, opts), &res)
}
// SendDice is used to send an animated emoji that will display a random value.
@@ -349,7 +360,7 @@ func (a API) SendDice(chatID int64, emoji DiceEmoji, opts *BaseOptions) (res API
vals.Set("chat_id", itoa(chatID))
vals.Set("emoji", string(emoji))
return get[APIResponseMessage](a.base, "sendDice", addValues(vals, opts))
return res, a.client.get(a.base, "sendDice", addValues(vals, opts), &res)
}
// SendChatAction is used to tell the user that something is happening on the bot's side.
@@ -359,7 +370,7 @@ func (a API) SendChatAction(action ChatAction, chatID int64, opts *ChatActionOpt
vals.Set("chat_id", itoa(chatID))
vals.Set("action", string(action))
return get[APIResponseBool](a.base, "sendChatAction", addValues(vals, opts))
return res, a.client.get(a.base, "sendChatAction", addValues(vals, opts), &res)
}
// SetMessageReaction is used to change the chosen reactions on a message.
@@ -371,7 +382,7 @@ func (a API) SetMessageReaction(chatID int64, messageID int, opts *MessageReacti
vals.Set("chat_id", itoa(chatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponseBool](a.base, "setMessageReaction", addValues(vals, opts))
return res, a.client.get(a.base, "setMessageReaction", addValues(vals, opts), &res)
}
// GetUserProfilePhotos is used to get a list of profile pictures for a user.
@@ -379,7 +390,7 @@ func (a API) GetUserProfilePhotos(userID int64, opts *UserProfileOptions) (res A
var vals = make(url.Values)
vals.Set("user_id", itoa(userID))
return get[APIResponseUserProfile](a.base, "getUserProfilePhotos", addValues(vals, opts))
return res, a.client.get(a.base, "getUserProfilePhotos", addValues(vals, opts), &res)
}
// GetFile returns the basic info about a file and prepares it for downloading.
@@ -391,14 +402,14 @@ func (a API) GetFile(fileID string) (res APIResponseFile, err error) {
var vals = make(url.Values)
vals.Set("file_id", fileID)
return get[APIResponseFile](a.base, "getFile", vals)
return res, a.client.get(a.base, "getFile", vals, &res)
}
// DownloadFile returns the bytes of the file corresponding to the given filePath.
// This function is callable for at least 1 hour since the call to GetFile.
// When the download expires a new one can be requested by calling GetFile again.
func (a API) DownloadFile(filePath string) ([]byte, error) {
return sendGetRequest(fmt.Sprintf(
return a.client.doGet(fmt.Sprintf(
"https://api.telegram.org/file/bot%s/%s",
a.token,
filePath,
@@ -414,7 +425,7 @@ func (a API) BanChatMember(chatID, userID int64, opts *BanOptions) (res APIRespo
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseBool](a.base, "banChatMember", addValues(vals, opts))
return res, a.client.get(a.base, "banChatMember", addValues(vals, opts), &res)
}
// UnbanChatMember is used to unban a previously banned user in a supergroup or channel.
@@ -428,7 +439,7 @@ func (a API) UnbanChatMember(chatID, userID int64, opts *UnbanOptions) (res APIR
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseBool](a.base, "unbanChatMember", addValues(vals, opts))
return res, a.client.get(a.base, "unbanChatMember", addValues(vals, opts), &res)
}
// RestrictChatMember is used to restrict a user in a supergroup.
@@ -436,15 +447,15 @@ func (a API) UnbanChatMember(chatID, userID int64, opts *UnbanOptions) (res APIR
func (a API) RestrictChatMember(chatID, userID int64, permissions ChatPermissions, opts *RestrictOptions) (res APIResponseBool, err error) {
var vals = make(url.Values)
perm, err := serializePerms(permissions)
perm, err := json.Marshal(permissions)
if err != nil {
return
}
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
vals.Set("permissions", perm)
return get[APIResponseBool](a.base, "restrictChatMember", addValues(vals, opts))
vals.Set("permissions", string(perm))
return res, a.client.get(a.base, "restrictChatMember", addValues(vals, opts), &res)
}
// PromoteChatMember is used to promote or demote a user in a supergroup or a channel.
@@ -454,7 +465,7 @@ func (a API) PromoteChatMember(chatID, userID int64, opts *PromoteOptions) (res
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseBool](a.base, "promoteChatMember", addValues(vals, opts))
return res, a.client.get(a.base, "promoteChatMember", addValues(vals, opts), &res)
}
// SetChatAdministratorCustomTitle is used to set a custom title for an administrator in a supergroup promoted by the bot.
@@ -464,7 +475,7 @@ func (a API) SetChatAdministratorCustomTitle(chatID, userID int64, customTitle s
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
vals.Set("custom_title", customTitle)
return get[APIResponseBool](a.base, "setChatAdministratorCustomTitle", vals)
return res, a.client.get(a.base, "setChatAdministratorCustomTitle", vals, &res)
}
// BanChatSenderChat is used to ban a channel chat in a supergroup or a channel.
@@ -475,7 +486,7 @@ func (a API) BanChatSenderChat(chatID, senderChatID int64) (res APIResponseBool,
vals.Set("chat_id", itoa(chatID))
vals.Set("sender_chat_id", itoa(senderChatID))
return get[APIResponseBool](a.base, "banChatSenderChat", vals)
return res, a.client.get(a.base, "banChatSenderChat", vals, &res)
}
// UnbanChatSenderChat is used to unban a previously channel chat in a supergroup or channel.
@@ -485,7 +496,7 @@ func (a API) UnbanChatSenderChat(chatID, senderChatID int64) (res APIResponseBoo
vals.Set("chat_id", itoa(chatID))
vals.Set("sender_chat_id", itoa(senderChatID))
return get[APIResponseBool](a.base, "unbanChatSenderChat", vals)
return res, a.client.get(a.base, "unbanChatSenderChat", vals, &res)
}
// SetChatPermissions is used to set default chat permissions for all members.
@@ -493,14 +504,14 @@ func (a API) UnbanChatSenderChat(chatID, senderChatID int64) (res APIResponseBoo
func (a API) SetChatPermissions(chatID int64, permissions ChatPermissions, opts *ChatPermissionsOptions) (res APIResponseBool, err error) {
var vals = make(url.Values)
perm, err := serializePerms(permissions)
perm, err := json.Marshal(permissions)
if err != nil {
return
}
vals.Set("chat_id", itoa(chatID))
vals.Set("permissions", perm)
return get[APIResponseBool](a.base, "setChatPermissions", addValues(vals, opts))
vals.Set("permissions", string(perm))
return res, a.client.get(a.base, "setChatPermissions", addValues(vals, opts), &res)
}
// ExportChatInviteLink is used to generate a new primary invite link for a chat;
@@ -510,7 +521,7 @@ func (a API) ExportChatInviteLink(chatID int64) (res APIResponseString, err erro
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseString](a.base, "exportChatInviteLink", vals)
return res, a.client.get(a.base, "exportChatInviteLink", vals, &res)
}
// CreateChatInviteLink is used to create an additional invite link for a chat.
@@ -520,7 +531,7 @@ func (a API) CreateChatInviteLink(chatID int64, opts *InviteLinkOptions) (res AP
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseInviteLink](a.base, "createChatInviteLink", addValues(vals, opts))
return res, a.client.get(a.base, "createChatInviteLink", addValues(vals, opts), &res)
}
// EditChatInviteLink is used to edit a non-primary invite link created by the bot.
@@ -530,7 +541,7 @@ func (a API) EditChatInviteLink(chatID int64, inviteLink string, opts *InviteLin
vals.Set("chat_id", itoa(chatID))
vals.Set("invite_link", inviteLink)
return get[APIResponseInviteLink](a.base, "editChatInviteLink", addValues(vals, opts))
return res, a.client.get(a.base, "editChatInviteLink", addValues(vals, opts), &res)
}
// RevokeChatInviteLink is used to revoke an invite link created by the bot.
@@ -541,7 +552,7 @@ func (a API) RevokeChatInviteLink(chatID int64, inviteLink string) (res APIRespo
vals.Set("chat_id", itoa(chatID))
vals.Set("invite_link", inviteLink)
return get[APIResponseInviteLink](a.base, "editChatInviteLink", vals)
return res, a.client.get(a.base, "editChatInviteLink", vals, &res)
}
// ApproveChatJoinRequest is used to approve a chat join request.
@@ -551,7 +562,7 @@ func (a API) ApproveChatJoinRequest(chatID, userID int64) (res APIResponseBool,
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseBool](a.base, "approveChatJoinRequest", vals)
return res, a.client.get(a.base, "approveChatJoinRequest", vals, &res)
}
// DeclineChatJoinRequest is used to decline a chat join request.
@@ -561,7 +572,7 @@ func (a API) DeclineChatJoinRequest(chatID, userID int64) (res APIResponseBool,
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseBool](a.base, "declineChatJoinRequest", vals)
return res, a.client.get(a.base, "declineChatJoinRequest", vals, &res)
}
// SetChatPhoto is used to set a new profile photo for the chat.
@@ -571,7 +582,7 @@ func (a API) SetChatPhoto(file InputFile, chatID int64) (res APIResponseBool, er
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return postFile[APIResponseBool](a.base, "setChatPhoto", "photo", file, InputFile{}, vals)
return res, a.client.postFile(a.base, "setChatPhoto", "photo", file, InputFile{}, vals, &res)
}
// DeleteChatPhoto is used to delete a chat photo.
@@ -581,7 +592,7 @@ func (a API) DeleteChatPhoto(chatID int64) (res APIResponseBool, err error) {
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "deleteChatPhoto", vals)
return res, a.client.get(a.base, "deleteChatPhoto", vals, &res)
}
// SetChatTitle is used to change the title of a chat.
@@ -592,7 +603,7 @@ func (a API) SetChatTitle(chatID int64, title string) (res APIResponseBool, err
vals.Set("chat_id", itoa(chatID))
vals.Set("title", title)
return get[APIResponseBool](a.base, "setChatTitle", vals)
return res, a.client.get(a.base, "setChatTitle", vals, &res)
}
// SetChatDescription is used to change the description of a group, a supergroup or a channel.
@@ -602,7 +613,7 @@ func (a API) SetChatDescription(chatID int64, description string) (res APIRespon
vals.Set("chat_id", itoa(chatID))
vals.Set("description", description)
return get[APIResponseBool](a.base, "setChatDescription", vals)
return res, a.client.get(a.base, "setChatDescription", vals, &res)
}
// PinChatMessage is used to add a message to the list of pinned messages in the chat.
@@ -613,7 +624,7 @@ func (a API) PinChatMessage(chatID int64, messageID int, opts *PinMessageOptions
vals.Set("chat_id", itoa(chatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponseBool](a.base, "pinChatMessage", addValues(vals, opts))
return res, a.client.get(a.base, "pinChatMessage", addValues(vals, opts), &res)
}
// UnpinChatMessage is used to remove a message from the list of pinned messages in the chat.
@@ -624,7 +635,7 @@ func (a API) UnpinChatMessage(chatID int64, messageID int) (res APIResponseBool,
vals.Set("chat_id", itoa(chatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponseBool](a.base, "unpinChatMessage", vals)
return res, a.client.get(a.base, "unpinChatMessage", vals, &res)
}
// UnpinAllChatMessages is used to clear the list of pinned messages in a chat.
@@ -634,7 +645,7 @@ func (a API) UnpinAllChatMessages(chatID int64) (res APIResponseBool, err error)
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "unpinAllChatMessages", vals)
return res, a.client.get(a.base, "unpinAllChatMessages", vals, &res)
}
// LeaveChat is used to make the bot leave a group, supergroup or channel.
@@ -642,7 +653,7 @@ func (a API) LeaveChat(chatID int64) (res APIResponseBool, err error) {
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "leaveChat", vals)
return res, a.client.get(a.base, "leaveChat", vals, &res)
}
// GetChat is used to get up to date information about the chat.
@@ -651,7 +662,7 @@ func (a API) GetChat(chatID int64) (res APIResponseChat, err error) {
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseChat](a.base, "getChat", vals)
return res, a.client.get(a.base, "getChat", vals, &res)
}
// GetChatAdministrators is used to get a list of administrators in a chat.
@@ -659,7 +670,7 @@ func (a API) GetChatAdministrators(chatID int64) (res APIResponseAdministrators,
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseAdministrators](a.base, "getChatAdministrators", vals)
return res, a.client.get(a.base, "getChatAdministrators", vals, &res)
}
// GetChatMemberCount is used to get the number of members in a chat.
@@ -667,7 +678,7 @@ func (a API) GetChatMemberCount(chatID int64) (res APIResponseInteger, err error
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseInteger](a.base, "getChatMemberCount", vals)
return res, a.client.get(a.base, "getChatMemberCount", vals, &res)
}
// GetChatMember is used to get information about a member of a chat.
@@ -676,7 +687,7 @@ func (a API) GetChatMember(chatID, userID int64) (res APIResponseChatMember, err
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseChatMember](a.base, "getChatMember", vals)
return res, a.client.get(a.base, "getChatMember", vals, &res)
}
// SetChatStickerSet is used to set a new group sticker set for a supergroup.
@@ -687,7 +698,7 @@ func (a API) SetChatStickerSet(chatID int64, stickerSetName string) (res APIResp
vals.Set("chat_id", itoa(chatID))
vals.Set("sticker_set_name", stickerSetName)
return get[APIResponseBool](a.base, "setChatStickerSet", vals)
return res, a.client.get(a.base, "setChatStickerSet", vals, &res)
}
// DeleteChatStickerSet is used to delete a group sticker set for a supergroup.
@@ -697,7 +708,7 @@ func (a API) DeleteChatStickerSet(chatID int64) (res APIResponseBool, err error)
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "deleteChatStickerSet", vals)
return res, a.client.get(a.base, "deleteChatStickerSet", vals, &res)
}
// CreateForumTopic is used to create a topic in a forum supergroup chat.
@@ -707,7 +718,7 @@ func (a API) CreateForumTopic(chatID int64, name string, opts *CreateTopicOption
vals.Set("chat_id", itoa(chatID))
vals.Set("name", name)
return get[APIResponseForumTopic](a.base, "createForumTopic", addValues(vals, opts))
return res, a.client.get(a.base, "createForumTopic", addValues(vals, opts), &res)
}
// EditForumTopic is used to edit name and icon of a topic in a forum supergroup chat.
@@ -717,7 +728,7 @@ func (a API) EditForumTopic(chatID, messageThreadID int64, opts *EditTopicOption
vals.Set("chat_id", itoa(chatID))
vals.Set("message_thread_id", itoa(messageThreadID))
return get[APIResponseBool](a.base, "editForumTopic", addValues(vals, opts))
return res, a.client.get(a.base, "editForumTopic", addValues(vals, opts), &res)
}
// CloseForumTopic is used to close an open topic in a forum supergroup chat.
@@ -727,7 +738,7 @@ func (a API) CloseForumTopic(chatID, messageThreadID int64) (res APIResponseBool
vals.Set("chat_id", itoa(chatID))
vals.Set("message_thread_id", itoa(messageThreadID))
return get[APIResponseBool](a.base, "closeForumTopic", vals)
return res, a.client.get(a.base, "closeForumTopic", vals, &res)
}
// ReopenForumTopic is used to reopen a closed topic in a forum supergroup chat.
@@ -737,7 +748,7 @@ func (a API) ReopenForumTopic(chatID, messageThreadID int64) (res APIResponseBoo
vals.Set("chat_id", itoa(chatID))
vals.Set("message_thread_id", itoa(messageThreadID))
return get[APIResponseBool](a.base, "reopenForumTopic", vals)
return res, a.client.get(a.base, "reopenForumTopic", vals, &res)
}
// DeleteForumTopic is used to delete a forum topic along with all its messages in a forum supergroup chat.
@@ -747,7 +758,7 @@ func (a API) DeleteForumTopic(chatID, messageThreadID int64) (res APIResponseBoo
vals.Set("chat_id", itoa(chatID))
vals.Set("message_thread_id", itoa(messageThreadID))
return get[APIResponseBool](a.base, "deleteForumTopic", vals)
return res, a.client.get(a.base, "deleteForumTopic", vals, &res)
}
// UnpinAllForumTopicMessages is used to clear the list of pinned messages in a forum topic.
@@ -757,7 +768,7 @@ func (a API) UnpinAllForumTopicMessages(chatID, messageThreadID int64) (res APIR
vals.Set("chat_id", itoa(chatID))
vals.Set("message_thread_id", itoa(messageThreadID))
return get[APIResponseBool](a.base, "unpinAllForumTopicMessages", vals)
return res, a.client.get(a.base, "unpinAllForumTopicMessages", vals, &res)
}
// EditGeneralForumTopic is used to edit the name of the 'General' topic in a forum supergroup chat.
@@ -767,7 +778,7 @@ func (a API) EditGeneralForumTopic(chatID int64, name string) (res APIResponseBo
vals.Set("chat_id", itoa(chatID))
vals.Set("name", name)
return get[APIResponseBool](a.base, "editGeneralForumTopic", vals)
return res, a.client.get(a.base, "editGeneralForumTopic", vals, &res)
}
// CloseGeneralForumTopic is used to close an open 'General' topic in a forum supergroup chat.
@@ -776,7 +787,7 @@ func (a API) CloseGeneralForumTopic(chatID int64) (res APIResponseBool, err erro
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "closeGeneralForumTopic", vals)
return res, a.client.get(a.base, "closeGeneralForumTopic", vals, &res)
}
// ReopenGeneralForumTopic is used to reopen a closed 'General' topic in a forum supergroup chat.
@@ -786,7 +797,7 @@ func (a API) ReopenGeneralForumTopic(chatID int64) (res APIResponseBool, err err
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "reopenGeneralForumTopic", vals)
return res, a.client.get(a.base, "reopenGeneralForumTopic", vals, &res)
}
// HideGeneralForumTopic is used to hide the 'General' topic in a forum supergroup chat.
@@ -796,7 +807,7 @@ func (a API) HideGeneralForumTopic(chatID int64) (res APIResponseBool, err error
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "hideGeneralForumTopic", vals)
return res, a.client.get(a.base, "hideGeneralForumTopic", vals, &res)
}
// UnhideGeneralForumTopic is used to unhide the 'General' topic in a forum supergroup chat.
@@ -805,7 +816,7 @@ func (a API) UnhideGeneralForumTopic(chatID int64) (res APIResponseBool, err err
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "unhideGeneralForumTopic", vals)
return res, a.client.get(a.base, "unhideGeneralForumTopic", vals, &res)
}
// UnpinAllGeneralForumTopicMessages is used to clear the list of pinned messages in a General forum topic.
@@ -814,7 +825,7 @@ func (a API) UnpinAllGeneralForumTopicMessages(chatID int64) (res APIResponseBoo
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseBool](a.base, "unpinAllGeneralForumTopicMessages", vals)
return res, a.client.get(a.base, "unpinAllGeneralForumTopicMessages", vals, &res)
}
// AnswerCallbackQuery is used to send answers to callback queries sent from inline keyboards.
@@ -823,7 +834,7 @@ func (a API) AnswerCallbackQuery(callbackID string, opts *CallbackQueryOptions)
var vals = make(url.Values)
vals.Set("callback_query_id", callbackID)
return get[APIResponseBool](a.base, "answerCallbackQuery", addValues(vals, opts))
return res, a.client.get(a.base, "answerCallbackQuery", addValues(vals, opts), &res)
}
// GetUserChatBoosts is used to get the list of boosts added to a chat by a user.
@@ -833,7 +844,15 @@ func (a API) GetUserChatBoosts(chatID, userID int64) (res APIResponseUserChatBoo
vals.Set("chat_id", itoa(chatID))
vals.Set("user_id", itoa(userID))
return get[APIResponseUserChatBoosts](a.base, "getUserChatBoosts", vals)
return res, a.client.get(a.base, "getUserChatBoosts", vals, &res)
}
// GetBusinessConnection is used to get information about the connection of the bot with a business account.
func (a API) GetBusinessConnection(business_connection_id string) (res APIResponseBusinessConnection, err error) {
var vals = make(url.Values)
vals.Set("business_connection_id", business_connection_id)
return res, a.client.get(a.base, "getBusinessConnection", vals, &res)
}
// SetMyCommands is used to change the list of the bot's commands for the given scope and user language.
@@ -842,17 +861,17 @@ func (a API) SetMyCommands(opts *CommandOptions, commands ...BotCommand) (res AP
jsn, _ := json.Marshal(commands)
vals.Set("commands", string(jsn))
return get[APIResponseBool](a.base, "setMyCommands", addValues(vals, opts))
return res, a.client.get(a.base, "setMyCommands", addValues(vals, opts), &res)
}
// DeleteMyCommands is used to delete the list of the bot's commands for the given scope and user language.
func (a API) DeleteMyCommands(opts *CommandOptions) (res APIResponseBool, err error) {
return get[APIResponseBool](a.base, "deleteMyCommands", urlValues(opts))
return res, a.client.get(a.base, "deleteMyCommands", urlValues(opts), &res)
}
// GetMyCommands is used to get the current list of the bot's commands for the given scope and user language.
func (a API) GetMyCommands(opts *CommandOptions) (res APIResponseCommands, err error) {
return get[APIResponseCommands](a.base, "getMyCommands", urlValues(opts))
return res, a.client.get(a.base, "getMyCommands", urlValues(opts), &res)
}
// SetMyName is used to change the bot's name.
@@ -861,7 +880,7 @@ func (a API) SetMyName(name, languageCode string) (res APIResponseBool, err erro
vals.Set("name", name)
vals.Set("language_code", languageCode)
return get[APIResponseBool](a.base, "setMyName", vals)
return res, a.client.get(a.base, "setMyName", vals, &res)
}
// GetMyName is used to get the current bot name for the given user language.
@@ -869,7 +888,7 @@ func (a API) GetMyName(languageCode string) (res APIResponseBotName, err error)
var vals = make(url.Values)
vals.Set("language_code", languageCode)
return get[APIResponseBotName](a.base, "getMyName", vals)
return res, a.client.get(a.base, "getMyName", vals, &res)
}
// SetMyDescription is used to to change the bot's description, which is shown in the chat with the bot if the chat is empty.
@@ -878,7 +897,7 @@ func (a API) SetMyDescription(description, languageCode string) (res APIResponse
vals.Set("description", description)
vals.Set("language_code", languageCode)
return get[APIResponseBool](a.base, "setMyDescription", vals)
return res, a.client.get(a.base, "setMyDescription", vals, &res)
}
// GetMyDescription is used to get the current bot description for the given user language.
@@ -886,7 +905,7 @@ func (a API) GetMyDescription(languageCode string) (res APIResponseBotDescriptio
var vals = make(url.Values)
vals.Set("language_code", languageCode)
return get[APIResponseBotDescription](a.base, "getMyDescription", vals)
return res, a.client.get(a.base, "getMyDescription", vals, &res)
}
// SetMyShortDescription is used to to change the bot's short description,
@@ -896,7 +915,7 @@ func (a API) SetMyShortDescription(shortDescription, languageCode string) (res A
vals.Set("short_description", shortDescription)
vals.Set("language_code", languageCode)
return get[APIResponseBool](a.base, "setMyShortDescription", vals)
return res, a.client.get(a.base, "setMyShortDescription", vals, &res)
}
// GetMyShortDescription is used to get the current bot short description for the given user language.
@@ -904,7 +923,7 @@ func (a API) GetMyShortDescription(languageCode string) (res APIResponseBotShort
var vals = make(url.Values)
vals.Set("language_code", languageCode)
return get[APIResponseBotShortDescription](a.base, "getMyDescription", vals)
return res, a.client.get(a.base, "getMyDescription", vals, &res)
}
// EditMessageText is used to edit text and game messages.
@@ -912,12 +931,12 @@ func (a API) EditMessageText(text string, msg MessageIDOptions, opts *MessageTex
var vals = make(url.Values)
vals.Set("text", text)
return get[APIResponseMessage](a.base, "editMessageText", addValues(addValues(vals, msg), opts))
return res, a.client.get(a.base, "editMessageText", addValues(addValues(vals, msg), opts), &res)
}
// EditMessageCaption is used to edit captions of messages.
func (a API) EditMessageCaption(msg MessageIDOptions, opts *MessageCaptionOptions) (res APIResponseMessage, err error) {
return get[APIResponseMessage](a.base, "editMessageCaption", addValues(urlValues(msg), opts))
return res, a.client.get(a.base, "editMessageCaption", addValues(urlValues(msg), opts), &res)
}
// EditMessageMedia is used to edit animation, audio, document, photo or video messages.
@@ -925,22 +944,22 @@ func (a API) EditMessageCaption(msg MessageIDOptions, opts *MessageCaptionOption
// only to a document for document albums and to a photo or a video otherwise.
// When an inline message is edited, a new file can't be uploaded.
// Use a previously uploaded file via its file_id or specify a URL.
func (a API) EditMessageMedia(msg MessageIDOptions, media InputMedia, opts *MessageReplyMarkup) (res APIResponseMessage, err error) {
return postMedia[APIResponseMessage](a.base, "editMessageMedia", true, addValues(urlValues(msg), opts), media)
func (a API) EditMessageMedia(msg MessageIDOptions, media InputMedia, opts *MessageMediaOptions) (res APIResponseMessage, err error) {
return res, a.client.postMedia(a.base, "editMessageMedia", true, addValues(urlValues(msg), opts), &res, media)
}
// EditMessageReplyMarkup is used to edit only the reply markup of messages.
func (a API) EditMessageReplyMarkup(msg MessageIDOptions, opts *MessageReplyMarkup) (res APIResponseMessage, err error) {
return get[APIResponseMessage](a.base, "editMessageReplyMarkup", addValues(urlValues(msg), opts))
func (a API) EditMessageReplyMarkup(msg MessageIDOptions, opts *MessageReplyMarkupOptions) (res APIResponseMessage, err error) {
return res, a.client.get(a.base, "editMessageReplyMarkup", addValues(urlValues(msg), opts), &res)
}
// StopPoll is used to stop a poll which was sent by the bot.
func (a API) StopPoll(chatID int64, messageID int, opts *MessageReplyMarkup) (res APIResponsePoll, err error) {
func (a API) StopPoll(chatID int64, messageID int, opts *StopPollOptions) (res APIResponsePoll, err error) {
var vals = make(url.Values)
vals.Set("chat_id", itoa(chatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponsePoll](a.base, "stopPoll", addValues(vals, opts))
return res, a.client.get(a.base, "stopPoll", addValues(vals, opts), &res)
}
// DeleteMessage is used to delete a message, including service messages, with the following limitations:
@@ -956,7 +975,7 @@ func (a API) DeleteMessage(chatID int64, messageID int) (res APIResponseBase, er
vals.Set("chat_id", itoa(chatID))
vals.Set("message_id", itoa(int64(messageID)))
return get[APIResponseBase](a.base, "deleteMessage", vals)
return res, a.client.get(a.base, "deleteMessage", vals, &res)
}
// DeleteMessages is used to delete multiple messages simultaneously.
@@ -971,5 +990,5 @@ func (a API) DeleteMessages(chatID int64, messageIDs []int) (res APIResponseBool
vals.Set("chat_id", itoa(chatID))
vals.Set("message_ids", string(msgIDs))
return get[APIResponseBool](a.base, "deleteMessages", vals)
return res, a.client.get(a.base, "deleteMessages", vals, &res)
}

View File

@@ -54,11 +54,11 @@ type GetMyDefaultAdministratorRightsOptions struct {
// requested by the bot when it's added as an administrator to groups or channels.
// These rights will be suggested to users, but they are are free to modify the list
// before adding the bot.
func (a API) SetMyDefaultAdministratorRights(opts SetMyDefaultAdministratorRightsOptions) (res APIResponseBool, err error) {
return get[APIResponseBool](a.base, "setMyDefaultAdministratorRights", urlValues(opts))
func (a API) SetMyDefaultAdministratorRights(opts *SetMyDefaultAdministratorRightsOptions) (res APIResponseBool, err error) {
return res, a.client.get(a.base, "setMyDefaultAdministratorRights", urlValues(opts), &res)
}
// GetMyDefaultAdministratorRights is used to get the current default administrator rights of the bot.
func (a API) GetMyDefaultAdministratorRights(opts GetMyDefaultAdministratorRightsOptions) (res APIResponseChatAdministratorRights, err error) {
return get[APIResponseChatAdministratorRights](a.base, "getMyDefaultAdministratorRights", urlValues(opts))
func (a API) GetMyDefaultAdministratorRights(opts *GetMyDefaultAdministratorRightsOptions) (res APIResponseChatAdministratorRights, err error) {
return res, a.client.get(a.base, "getMyDefaultAdministratorRights", urlValues(opts), &res)
}

View File

@@ -52,7 +52,7 @@ func (a API) SendGame(gameShortName string, chatID int64, opts *BaseOptions) (re
vals.Set("chat_id", itoa(chatID))
vals.Set("game_short_name", gameShortName)
return get[APIResponseMessage](a.base, "sendGame", addValues(vals, opts))
return res, a.client.get(a.base, "sendGame", addValues(vals, opts), &res)
}
// SetGameScore is used to set the score of the specified user in a game.
@@ -61,7 +61,7 @@ func (a API) SetGameScore(userID int64, score int, msgID MessageIDOptions, opts
vals.Set("user_id", itoa(userID))
vals.Set("score", itoa(int64(score)))
return get[APIResponseMessage](a.base, "setGameScore", addValues(addValues(vals, msgID), opts))
return res, a.client.get(a.base, "setGameScore", addValues(addValues(vals, msgID), opts), &res)
}
// GetGameHighScores is used to get data for high score tables.
@@ -69,5 +69,5 @@ func (a API) GetGameHighScores(userID int64, opts MessageIDOptions) (res APIResp
var vals = make(url.Values)
vals.Set("user_id", itoa(userID))
return get[APIResponseGameHighScore](a.base, "getGameHighScores", addValues(vals, opts))
return res, a.client.get(a.base, "getGameHighScores", addValues(vals, opts), &res)
}

View File

@@ -19,7 +19,6 @@
package echotron
import (
"encoding/json"
"fmt"
"net/url"
"os"
@@ -27,6 +26,13 @@ import (
"strconv"
)
// content contains a file's name, its type and its data.
type content struct {
fname string
ftype string
fdata []byte
}
func check(r APIResponse) error {
if b := r.Base(); !b.Ok {
return &APIError{code: b.ErrorCode, desc: b.Description}
@@ -109,123 +115,6 @@ func readFile(im InputFile) (content []byte, path string, err error) {
return
}
func sendFile(file, thumbnail InputFile, url, fileType string) (res []byte, err error) {
var cnt []content
if file.id != "" {
url = fmt.Sprintf("%s&%s=%s", url, fileType, file.id)
} else if file.url != "" {
url = fmt.Sprintf("%s&%s=%s", url, fileType, file.url)
} else if c, e := toContent(fileType, file); e == nil {
cnt = append(cnt, c)
} else {
err = e
}
if c, e := toContent("thumbnail", thumbnail); e == nil {
cnt = append(cnt, c)
} else {
err = e
}
if len(cnt) > 0 {
res, err = sendPostRequest(url, cnt...)
} else {
res, err = sendGetRequest(url)
}
return
}
func sendMediaFiles(url string, editSingle bool, files ...InputMedia) (res []byte, err error) {
var (
med []mediaEnvelope
cnt []content
jsn []byte
)
for _, file := range files {
var im mediaEnvelope
var cntArr []content
media := file.media()
thumbnail := file.thumbnail()
im, cntArr, err = processMedia(media, thumbnail)
if err != nil {
return
}
im.InputMedia = file
med = append(med, im)
cnt = append(cnt, cntArr...)
}
if editSingle {
jsn, err = json.Marshal(med[0])
} else {
jsn, err = json.Marshal(med)
}
if err != nil {
return
}
url = fmt.Sprintf("%s&media=%s", url, jsn)
if len(cnt) > 0 {
return sendPostRequest(url, cnt...)
}
return sendGetRequest(url)
}
func sendStickers(url string, stickers ...InputSticker) (res []byte, err error) {
var (
sti []stickerEnvelope
cnt []content
jsn []byte
)
for _, s := range stickers {
var se stickerEnvelope
var cntArr []content
se, cntArr, err = processSticker(s.Sticker)
if err != nil {
return
}
se.InputSticker = s
sti = append(sti, se)
cnt = append(cnt, cntArr...)
}
if len(sti) == 1 {
jsn, _ = json.Marshal(sti[0])
url = fmt.Sprintf("%s&sticker=%s", url, jsn)
} else {
jsn, _ = json.Marshal(sti)
url = fmt.Sprintf("%s&stickers=%s", url, jsn)
}
if len(cnt) > 0 {
return sendPostRequest(url, cnt...)
}
return sendGetRequest(url)
}
func serializePerms(permissions ChatPermissions) (string, error) {
perm, err := json.Marshal(permissions)
if err != nil {
return "", err
}
return string(perm), nil
}
func toContent(ftype string, f InputFile) (content, error) {
if f.path != "" && len(f.content) == 0 {
var err error
@@ -247,87 +136,6 @@ func toInputMedia(media []GroupableInputMedia) (ret []InputMedia) {
return ret
}
func get[T APIResponse](base, endpoint string, vals url.Values) (res T, err error) {
url, err := url.JoinPath(base, endpoint)
if err != nil {
return res, err
}
if vals != nil {
if queries := vals.Encode(); queries != "" {
url = fmt.Sprintf("%s?%s", url, queries)
}
}
cnt, err := sendGetRequest(url)
if err != nil {
return res, err
}
if err = json.Unmarshal(cnt, &res); err != nil {
return
}
err = check(res)
return
}
func postFile[T APIResponse](base, endpoint, fileType string, file, thumbnail InputFile, vals url.Values) (res T, err error) {
url, err := joinURL(base, endpoint, vals)
if err != nil {
return res, err
}
cnt, err := sendFile(file, thumbnail, url, fileType)
if err != nil {
return res, err
}
if err = json.Unmarshal(cnt, &res); err != nil {
return
}
err = check(res)
return
}
func postMedia[T APIResponse](base, endpoint string, editSingle bool, vals url.Values, files ...InputMedia) (res T, err error) {
url, err := joinURL(base, endpoint, vals)
if err != nil {
return res, err
}
cnt, err := sendMediaFiles(url, editSingle, files...)
if err != nil {
return res, err
}
if err = json.Unmarshal(cnt, &res); err != nil {
return
}
err = check(res)
return
}
func postStickers[T APIResponse](base, endpoint string, vals url.Values, stickers ...InputSticker) (res T, err error) {
url, err := joinURL(base, endpoint, vals)
if err != nil {
return res, err
}
cnt, err := sendStickers(url, stickers...)
if err != nil {
return res, err
}
if err = json.Unmarshal(cnt, &res); err != nil {
return
}
err = check(res)
return
}
func joinURL(base, endpoint string, vals url.Values) (addr string, err error) {
addr, err = url.JoinPath(base, endpoint)
if err != nil {

View File

@@ -90,19 +90,20 @@ func (i InlineQueryResultArticle) ImplementsInlineQueryResult() {}
// By default, this photo will be sent by the user with optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the photo.
type InlineQueryResultPhoto struct {
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Title string `json:"title,omitempty"`
ThumbnailURL string `json:"thumbnail_url"`
PhotoURL string `json:"photo_url"`
ParseMode string `json:"parse_mode,omitempty"`
ID string `json:"id"`
Description string `json:"description,omitempty"`
Caption string `json:"caption,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
PhotoHeight int `json:"photo_height,omitempty"`
PhotoWidth int `json:"photo_width,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Title string `json:"title,omitempty"`
ThumbnailURL string `json:"thumbnail_url"`
PhotoURL string `json:"photo_url"`
ParseMode string `json:"parse_mode,omitempty"`
ID string `json:"id"`
Description string `json:"description,omitempty"`
Caption string `json:"caption,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
PhotoHeight int `json:"photo_height,omitempty"`
PhotoWidth int `json:"photo_width,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -112,20 +113,21 @@ func (i InlineQueryResultPhoto) ImplementsInlineQueryResult() {}
// By default, this animated GIF file will be sent by the user with optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the animation.
type InlineQueryResultGif struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
Title string `json:"title,omitempty"`
GifURL string `json:"gif_url"`
ParseMode string `json:"parse_mode,omitempty"`
Caption string `json:"caption,omitempty"`
ThumbnailURL string `json:"thumbnail_url"`
ID string `json:"id"`
ThumbnailMimeType string `json:"thumbnail_mime_type,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
GifDuration int `json:"gif_duration,omitempty"`
GifHeight int `json:"gif_height,omitempty"`
GifWidth int `json:"gif_width,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
Title string `json:"title,omitempty"`
GifURL string `json:"gif_url"`
ParseMode string `json:"parse_mode,omitempty"`
Caption string `json:"caption,omitempty"`
ThumbnailURL string `json:"thumbnail_url"`
ID string `json:"id"`
ThumbnailMimeType string `json:"thumbnail_mime_type,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
GifDuration int `json:"gif_duration,omitempty"`
GifHeight int `json:"gif_height,omitempty"`
GifWidth int `json:"gif_width,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -135,20 +137,21 @@ func (i InlineQueryResultGif) ImplementsInlineQueryResult() {}
// By default, this animated MPEG-4 file will be sent by the user with optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the animation.
type InlineQueryResultMpeg4Gif struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
Title string `json:"title,omitempty"`
Mpeg4URL string `json:"mpeg4_url"`
ParseMode string `json:"parse_mode,omitempty"`
Caption string `json:"caption,omitempty"`
ThumbnailURL string `json:"thumbnail_url"`
ID string `json:"id"`
ThumbnailMimeType string `json:"thumbnail_mime_type,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Mpeg4Duration int `json:"mpeg4_duration,omitempty"`
Mpeg4Height int `json:"mpeg4_height,omitempty"`
Mpeg4Width int `json:"mpeg4_width,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
Title string `json:"title,omitempty"`
Mpeg4URL string `json:"mpeg4_url"`
ParseMode string `json:"parse_mode,omitempty"`
Caption string `json:"caption,omitempty"`
ThumbnailURL string `json:"thumbnail_url"`
ID string `json:"id"`
ThumbnailMimeType string `json:"thumbnail_mime_type,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Mpeg4Duration int `json:"mpeg4_duration,omitempty"`
Mpeg4Height int `json:"mpeg4_height,omitempty"`
Mpeg4Width int `json:"mpeg4_width,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -158,21 +161,22 @@ func (i InlineQueryResultMpeg4Gif) ImplementsInlineQueryResult() {}
// By default, this video file will be sent by the user with an optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the video.
type InlineQueryResultVideo struct {
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
Description string `json:"description,omitempty"`
MimeType string `json:"mime_type"`
ThumbnailURL string `json:"thumbnail_url"`
Title string `json:"title"`
Caption string `json:"caption,omitempty"`
ID string `json:"id"`
VideoURL string `json:"video_url"`
ParseMode string `json:"parse_mode,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
VideoHeight int `json:"video_height,omitempty"`
VideoDuration int `json:"video_duration,omitempty"`
VideoWidth int `json:"video_width,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
Description string `json:"description,omitempty"`
MimeType string `json:"mime_type"`
ThumbnailURL string `json:"thumbnail_url"`
Title string `json:"title"`
Caption string `json:"caption,omitempty"`
ID string `json:"id"`
VideoURL string `json:"video_url"`
ParseMode string `json:"parse_mode,omitempty"`
Type InlineQueryType `json:"type"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
VideoHeight int `json:"video_height,omitempty"`
VideoDuration int `json:"video_duration,omitempty"`
VideoWidth int `json:"video_width,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -323,16 +327,17 @@ func (i InlineQueryResultGame) ImplementsInlineQueryResult() {}
// By default, this photo will be sent by the user with an optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the photo.
type InlineQueryResultCachedPhoto struct {
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
ID string `json:"id"`
Description string `json:"description,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
PhotoFileID string `json:"photo_file_id"`
Title string `json:"title,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
ID string `json:"id"`
Description string `json:"description,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
PhotoFileID string `json:"photo_file_id"`
Title string `json:"title,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -342,15 +347,16 @@ func (i InlineQueryResultCachedPhoto) ImplementsInlineQueryResult() {}
// By default, this animated GIF file will be sent by the user with an optional caption.
// Alternatively, you can use InputMessageContent to send a message with specified content instead of the animation.
type InlineQueryResultCachedGif struct {
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
Title string `json:"title,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
ID string `json:"id"`
GifFileID string `json:"gif_file_id"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
Title string `json:"title,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
ID string `json:"id"`
GifFileID string `json:"gif_file_id"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -360,15 +366,16 @@ func (i InlineQueryResultCachedGif) ImplementsInlineQueryResult() {}
// By default, this animated MPEG-4 file will be sent by the user with an optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the animation.
type InlineQueryResultCachedMpeg4Gif struct {
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
Title string `json:"title,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
ID string `json:"id"`
Mpeg4FileID string `json:"mpeg4_file_id"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
Title string `json:"title,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
ID string `json:"id"`
Mpeg4FileID string `json:"mpeg4_file_id"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -411,16 +418,17 @@ func (i InlineQueryResultCachedDocument) ImplementsInlineQueryResult() {}
// By default, this video file will be sent by the user with an optional caption.
// Alternatively, you can use InputMessageContent to send a message with the specified content instead of the video.
type InlineQueryResultCachedVideo struct {
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
ID string `json:"id"`
Description string `json:"description,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
VideoFileID string `json:"video_file_id"`
Title string `json:"title"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
InputMessageContent InputMessageContent `json:"input_message_content,omitempty"`
Type InlineQueryType `json:"type"`
ID string `json:"id"`
Description string `json:"description,omitempty"`
Caption string `json:"caption,omitempty"`
ParseMode string `json:"parse_mode,omitempty"`
VideoFileID string `json:"video_file_id"`
Title string `json:"title"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// ImplementsInlineQueryResult is used to implement the InlineQueryResult interface.
@@ -468,10 +476,10 @@ type InputMessageContent interface {
// InputTextMessageContent represents the content of a text message to be sent as the result of an inline query.
type InputTextMessageContent struct {
LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"`
MessageText string `json:"message_text"`
ParseMode string `json:"parse_mode,omitempty"`
Entities []*MessageEntity `json:"entities,omitempty"`
LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"`
}
// ImplementsInputMessageContent is used to implement the InputMessageContent interface.
@@ -516,6 +524,33 @@ type InputContactMessageContent struct {
// ImplementsInputMessageContent is used to implement the InputMessageContent interface.
func (i InputContactMessageContent) ImplementsInputMessageContent() {}
// InputInvoiceMessageContent represents the content of an invoice message to be sent as the result of an inline query.
type InputInvoiceMessageContent struct {
SuggestedTipAmounts *[]int `json:"suggested_tip_amounts,omitempty"`
PhotoURL string `json:"photo_url,omitempty"`
Description string `json:"description"`
Payload string `json:"string"`
ProviderToken string `json:"provider_token,omitempty"`
Currency string `json:"currency"`
Title string `json:"title"`
ProviderData string `json:"provider_data,omitempty"`
Prices []LabeledPrice `json:"prices"`
PhotoSize int `json:"photo_size,omitempty"`
MaxTipAmount int `json:"max_tip_amount,omitempty"`
PhotoWidth int `json:"photo_width,omitempty"`
PhotoHeight int `json:"photo_height,omitempty"`
NeedName bool `json:"need_name,omitempty"`
NeedPhoneNumber bool `json:"need_phone_number,omitempty"`
NeedEmail bool `json:"need_email,omitempty"`
NeedShippingAddress bool `json:"need_shipping_address,omitempty"`
SendPhoneNumberToProvider bool `json:"send_phone_number_to_provider,omitempty"`
SendEmailToProvider bool `json:"send_email_to_provider,omitempty"`
IsFlexible bool `json:"is_flexible,omitempty"`
}
// ImplementsInputMessageContent is used to implement the InputMessageContent interface.
func (i InputInvoiceMessageContent) ImplementsInputMessageContent() {}
// InlineQueryResultsButton represents a button to be shown above inline query results.
// You MUST use exactly one of the fields.
type InlineQueryResultsButton struct {
@@ -539,5 +574,5 @@ func (a API) AnswerInlineQuery(inlineQueryID string, results []InlineQueryResult
jsn, _ := json.Marshal(results)
vals.Set("inline_query_id", inlineQueryID)
vals.Set("results", string(jsn))
return get[APIResponseBase](a.base, "answerInlineQuery", addValues(vals, opts))
return res, a.client.get(a.base, "answerInlineQuery", addValues(vals, opts), &res)
}

View File

@@ -47,11 +47,11 @@ type GetChatMenuButtonOptions struct {
}
// SetChatMenuButton is used to change the bot's menu button in a private chat, or the default menu button.
func (a API) SetChatMenuButton(opts SetChatMenuButtonOptions) (res APIResponseBool, err error) {
return get[APIResponseBool](a.base, "setChatMenuButton", urlValues(opts))
func (a API) SetChatMenuButton(opts *SetChatMenuButtonOptions) (res APIResponseBool, err error) {
return res, a.client.get(a.base, "setChatMenuButton", urlValues(opts), &res)
}
// GetChatMenuButton is used to get the current value of the bot's menu button in a private chat, or the default menu button.
func (a API) GetChatMenuButton(opts GetChatMenuButtonOptions) (res APIResponseMenuButton, err error) {
return get[APIResponseMenuButton](a.base, "getChatMenuButton", urlValues(opts))
func (a API) GetChatMenuButton(opts *GetChatMenuButtonOptions) (res APIResponseMenuButton, err error) {
return res, a.client.get(a.base, "getChatMenuButton", urlValues(opts), &res)
}

View File

@@ -20,99 +20,345 @@ package echotron
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"mime/multipart"
"net/http"
"net/url"
"path/filepath"
"strings"
"sync"
"time"
"golang.org/x/time/rate"
)
// content is a struct which contains a file's name, its type and its data.
type content struct {
fname string
ftype string
fdata []byte
type client struct {
*http.Client
*sync.RWMutex
cl map[string]*rate.Limiter // chat based limiter
gl *rate.Limiter // global limiter
climiter func() *rate.Limiter
}
// sendGetRequest is used to send an HTTP GET request.
func sendGetRequest(url string) ([]byte, error) {
resp, err := http.Get(url)
var lclient = newClient()
// SetGlobalRequestLimit sets the global rate limit for requests to the Telegram API.
// A duration of 0 disables the rate limiter, allowing unlimited requests.
// By default the duration of this limiter is set to time.Second/30.
func SetGlobalRequestLimit(d time.Duration) {
lclient.Lock()
lclient.gl = rate.NewLimiter(rate.Every(d), 10)
lclient.Unlock()
}
// SetChatRequestLimit sets the per-chat rate limit for requests to the Telegram API.
// A duration of 0 disables the rate limiter, allowing unlimited requests.
// By default the duration of this limiter is set to time.Minute/20.
func SetChatRequestLimit(d time.Duration) {
lclient.Lock()
lclient.cl = make(map[string]*rate.Limiter)
lclient.climiter = func() *rate.Limiter {
return rate.NewLimiter(rate.Every(d), 1)
}
lclient.Unlock()
}
func newClient() *client {
return &client{
Client: new(http.Client),
RWMutex: new(sync.RWMutex),
cl: make(map[string]*rate.Limiter),
gl: rate.NewLimiter(rate.Every(time.Second/30), 10),
climiter: func() *rate.Limiter {
return rate.NewLimiter(rate.Every(time.Minute/20), 1)
},
}
}
func (c client) wait(chatID string) error {
c.RLock()
defer c.RUnlock()
ctx := context.Background()
// If the chatID is empty, it's a general API call like GetUpdates, GetMe
// and similar, so skip the per-chat request limit wait.
if chatID != "" {
// If no limiter exists for a chat, create one.
l, ok := c.cl[chatID]
if !ok {
l = c.climiter()
c.cl[chatID] = l
}
// Make sure to respect the single chat limit of requests.
if err := l.Wait(ctx); err != nil {
return err
}
}
// Make sure to respect the global limit of requests.
return c.gl.Wait(ctx)
}
func (c client) doGet(reqURL string) ([]byte, error) {
resp, err := c.Get(reqURL)
if err != nil {
return []byte{}, err
return nil, err
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
return []byte{}, err
return nil, err
}
return data, nil
}
// sendPostRequest is used to send an HTTP POST request.
func sendPostRequest(url string, files ...content) ([]byte, error) {
var buf = new(bytes.Buffer)
var w = multipart.NewWriter(buf)
func (c client) doPost(reqURL string, files ...content) ([]byte, error) {
var (
buf = new(bytes.Buffer)
w = multipart.NewWriter(buf)
)
for _, f := range files {
part, err := w.CreateFormFile(f.ftype, filepath.Base(f.fname))
if err != nil {
return []byte{}, err
return nil, err
}
part.Write(f.fdata)
}
w.Close()
req, err := http.NewRequest("POST", url, buf)
req, err := http.NewRequest(http.MethodPost, reqURL, buf)
if err != nil {
return []byte{}, err
return nil, err
}
req.Header.Add("Content-Type", w.FormDataContentType())
var client = new(http.Client)
res, err := client.Do(req)
res, err := c.Do(req)
if err != nil {
return []byte{}, err
return nil, err
}
defer res.Body.Close()
cnt, err := io.ReadAll(res.Body)
if err != nil {
return []byte{}, err
}
return cnt, nil
return io.ReadAll(res.Body)
}
// sendPostForm is used to send an "application/x-www-form-urlencoded" through an HTTP POST request.
func sendPostForm(reqURL string, keyVals map[string]string) ([]byte, error) {
func (c client) doPostForm(reqURL string, keyVals map[string]string) ([]byte, error) {
var form = make(url.Values)
for k, v := range keyVals {
form.Add(k, v)
}
request, err := http.NewRequest("POST", reqURL, strings.NewReader(form.Encode()))
req, err := http.NewRequest(http.MethodPost, reqURL, strings.NewReader(form.Encode()))
if err != nil {
return []byte{}, err
return nil, err
}
request.PostForm = form
request.Header.Add("Content-Type", "application/x-www-form-urlencoded")
req.PostForm = form
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
var client http.Client
response, err := client.Do(request)
res, err := c.Do(req)
if err != nil {
return []byte{}, err
return nil, err
}
defer response.Body.Close()
content, err := io.ReadAll(response.Body)
if err != nil {
return []byte{}, err
}
return content, nil
defer res.Body.Close()
return io.ReadAll(res.Body)
}
func (c client) sendFile(file, thumbnail InputFile, url, fileType string) (res []byte, err error) {
var cnt []content
if file.id != "" {
url = fmt.Sprintf("%s&%s=%s", url, fileType, file.id)
} else if file.url != "" {
url = fmt.Sprintf("%s&%s=%s", url, fileType, file.url)
} else if c, e := toContent(fileType, file); e == nil {
cnt = append(cnt, c)
} else {
err = e
}
if c, e := toContent("thumbnail", thumbnail); e == nil {
cnt = append(cnt, c)
} else {
err = e
}
if len(cnt) > 0 {
res, err = c.doPost(url, cnt...)
} else {
res, err = c.doGet(url)
}
return
}
func (c client) get(base, endpoint string, vals url.Values, v APIResponse) error {
url, err := url.JoinPath(base, endpoint)
if err != nil {
return err
}
if vals != nil {
if queries := vals.Encode(); queries != "" {
url = fmt.Sprintf("%s?%s", url, queries)
}
}
if err := c.wait(vals.Get("chat_id")); err != nil {
return err
}
cnt, err := c.doGet(url)
if err != nil {
return err
}
if err := json.Unmarshal(cnt, v); err != nil {
return err
}
return check(v)
}
func (c client) postFile(base, endpoint, fileType string, file, thumbnail InputFile, vals url.Values, v APIResponse) error {
url, err := joinURL(base, endpoint, vals)
if err != nil {
return err
}
if err := c.wait(vals.Get("chat_id")); err != nil {
return err
}
cnt, err := c.sendFile(file, thumbnail, url, fileType)
if err != nil {
return err
}
if err := json.Unmarshal(cnt, v); err != nil {
return err
}
return check(v)
}
func (c client) postMedia(base, endpoint string, editSingle bool, vals url.Values, v APIResponse, files ...InputMedia) error {
url, err := joinURL(base, endpoint, vals)
if err != nil {
return err
}
if err := c.wait(vals.Get("chat_id")); err != nil {
return err
}
cnt, err := c.sendMediaFiles(url, editSingle, files...)
if err != nil {
return err
}
if err := json.Unmarshal(cnt, v); err != nil {
return err
}
return check(v)
}
func (c client) postStickers(base, endpoint string, vals url.Values, v APIResponse, stickers ...InputSticker) error {
url, err := joinURL(base, endpoint, vals)
if err != nil {
return err
}
if err := c.wait(vals.Get("chat_id")); err != nil {
return err
}
cnt, err := c.sendStickers(url, stickers...)
if err != nil {
return err
}
if err := json.Unmarshal(cnt, v); err != nil {
return err
}
return check(v)
}
func (c client) sendMediaFiles(url string, editSingle bool, files ...InputMedia) (res []byte, err error) {
var (
med []mediaEnvelope
cnt []content
jsn []byte
)
for _, file := range files {
var im mediaEnvelope
var cntArr []content
media := file.media()
thumbnail := file.thumbnail()
im, cntArr, err = processMedia(media, thumbnail)
if err != nil {
return
}
im.InputMedia = file
med = append(med, im)
cnt = append(cnt, cntArr...)
}
if editSingle {
jsn, err = json.Marshal(med[0])
} else {
jsn, err = json.Marshal(med)
}
if err != nil {
return
}
url = fmt.Sprintf("%s&media=%s", url, jsn)
if len(cnt) > 0 {
return c.doPost(url, cnt...)
}
return c.doGet(url)
}
func (c client) sendStickers(url string, stickers ...InputSticker) (res []byte, err error) {
var (
sti []stickerEnvelope
cnt []content
jsn []byte
)
for _, s := range stickers {
var se stickerEnvelope
var cntArr []content
se, cntArr, err = processSticker(s.Sticker)
if err != nil {
return
}
se.InputSticker = s
sti = append(sti, se)
cnt = append(cnt, cntArr...)
}
if len(sti) == 1 {
jsn, _ = json.Marshal(sti[0])
url = fmt.Sprintf("%s&sticker=%s", url, jsn)
} else {
jsn, _ = json.Marshal(sti)
url = fmt.Sprintf("%s&stickers=%s", url, jsn)
}
if len(cnt) > 0 {
return c.doPost(url, cnt...)
}
return c.doGet(url)
}

View File

@@ -74,23 +74,25 @@ type MessageEntityType string
// These are all the possible types for MessageEntityType.
const (
MentionEntity MessageEntityType = "mention"
HashtagEntity = "hashtag"
CashtagEntity = "cashtag"
BotCommandEntity = "bot_command"
UrlEntity = "url"
EmailEntity = "email"
PhoneNumberEntity = "phone_number"
BoldEntity = "bold"
ItalicEntity = "italic"
UnderlineEntity = "underline"
StrikethroughEntity = "strikethrough"
SpoilerEntity = "spoiler"
CodeEntity = "code"
PreEntity = "pre"
TextLinkEntity = "text_link"
TextMentionEntity = "text_mention"
CustomEmojiEntity = "custom_emoji"
MentionEntity MessageEntityType = "mention"
HashtagEntity = "hashtag"
CashtagEntity = "cashtag"
BotCommandEntity = "bot_command"
UrlEntity = "url"
EmailEntity = "email"
PhoneNumberEntity = "phone_number"
BoldEntity = "bold"
ItalicEntity = "italic"
UnderlineEntity = "underline"
StrikethroughEntity = "strikethrough"
SpoilerEntity = "spoiler"
BlockQuoteEntity = "blockquote"
ExpandableBlockQuoteEntity = "expandable_blockquote"
CodeEntity = "code"
PreEntity = "pre"
TextLinkEntity = "text_link"
TextMentionEntity = "text_mention"
CustomEmojiEntity = "custom_emoji"
)
// UpdateType is a custom type for the various update types that a bot can be subscribed to.
@@ -137,10 +139,13 @@ type KeyboardButtonPollType struct {
// KeyboardButtonRequestUsers 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.
type KeyboardButtonRequestUsers struct {
RequestID int `json:"request_id"`
MaxQuantity int `json:"max_quantity,omitempty"`
UserIsBot bool `json:"user_is_bot,omitempty"`
UserIsPremium bool `json:"user_is_premium,omitempty"`
RequestID int `json:"request_id"`
MaxQuantity int `json:"max_quantity,omitempty"`
UserIsBot bool `json:"user_is_bot,omitempty"`
UserIsPremium bool `json:"user_is_premium,omitempty"`
RequestName bool `json:"request_name,omitempty"`
RequestUsername bool `json:"request_username,omitempty"`
RequestPhoto bool `json:"request_photo,omitempty"`
}
// KeyboardButtonRequestChat defines the criteria used to request a suitable chat.
@@ -154,6 +159,9 @@ type KeyboardButtonRequestChat struct {
ChatHasUsername bool `json:"chat_has_username,omitempty"`
ChatIsCreated bool `json:"chat_is_created,omitempty"`
BotIsMember bool `json:"bot_is_member,omitempty"`
RequestName bool `json:"request_name,omitempty"`
RequestUsername bool `json:"request_username,omitempty"`
RequestPhoto bool `json:"request_photo,omitempty"`
}
// ReplyKeyboardMarkup represents a custom keyboard with reply options.
@@ -233,23 +241,27 @@ type WebhookOptions struct {
// BaseOptions contains the optional parameters used frequently in some Telegram API methods.
type BaseOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// MessageOptions contains the optional parameters used by some Telegram API methods.
type MessageOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
LinkPreviewOptions LinkPreviewOptions `query:"link_preview_options"`
Entities []MessageEntity `query:"entities"`
MessageThreadID int64 `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
LinkPreviewOptions LinkPreviewOptions `query:"link_preview_options"`
Entities []MessageEntity `query:"entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int64 `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// PinMessageOptions contains the optional parameters used by the PinChatMember method.
@@ -266,14 +278,15 @@ type ForwardOptions struct {
// CopyOptions contains the optional parameters used by the CopyMessage method.
type CopyOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
CaptionEntities []MessageEntity `query:"caption_entities"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ShowCaptionAboveMedia bool `query:"show_caption_above_media"`
}
// CopyMessagesOptions contains the optional parameters used by the CopyMessages methods.
@@ -286,12 +299,14 @@ type CopyMessagesOptions struct {
// StickerOptions contains the optional parameters used by the SendSticker method.
type StickerOptions struct {
Emoji string `query:"emoji"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
BusinessConnectionID string `query:"business_connection_id"`
Emoji string `query:"emoji"`
MessageEffectID string `query:"message_effect_id"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// InputFile is a struct which contains data about a file to be sent.
@@ -299,7 +314,6 @@ type InputFile struct {
id string
path string
url string
ftype string
content []byte
}
@@ -325,41 +339,48 @@ func NewInputFileBytes(fileName string, content []byte) InputFile {
// PhotoOptions contains the optional parameters used by the SendPhoto method.
type PhotoOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
CaptionEntities []MessageEntity `query:"caption_entities"`
MessageThreadID int `query:"message_thread_id"`
HasSpoiler bool `query:"has_spoiler"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
HasSpoiler bool `query:"has_spoiler"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ShowCaptionAboveMedia bool `query:"show_caption_above_media"`
}
// AudioOptions contains the optional parameters used by the SendAudio method.
type AudioOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
Performer string `query:"performer"`
Title string `query:"title"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
Title string `query:"title"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
Performer string `query:"performer"`
BusinessConnectionID string `query:"business_connection_id"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// DocumentOptions contains the optional parameters used by the SendDocument method.
type DocumentOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
@@ -368,74 +389,91 @@ type DocumentOptions struct {
// VideoOptions contains the optional parameters used by the SendVideo method.
type VideoOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
Caption string `query:"caption"`
ParseMode ParseMode `query:"parse_mode"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
Width int `query:"width"`
Height int `query:"height"`
HasSpoiler bool `query:"has_spoiler"`
SupportsStreaming bool `query:"supports_streaming"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
Caption string `query:"caption"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
Width int `query:"width"`
Height int `query:"height"`
HasSpoiler bool `query:"has_spoiler"`
SupportsStreaming bool `query:"supports_streaming"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ShowCaptionAboveMedia bool `query:"show_caption_above_media"`
}
// AnimationOptions contains the optional parameters used by the SendAnimation method.
type AnimationOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
Width int `query:"width"`
Height int `query:"height"`
HasSpoiler bool `query:"has_spoiler"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
Thumbnail InputFile
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
Width int `query:"width"`
Height int `query:"height"`
HasSpoiler bool `query:"has_spoiler"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ShowCaptionAboveMedia bool `query:"show_caption_above_media"`
}
// VoiceOptions contains the optional parameters used by the SendVoice method.
type VoiceOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
CaptionEntities []MessageEntity `query:"caption_entities"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ParseMode ParseMode `query:"parse_mode"`
Caption string `query:"caption"`
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// VideoNoteOptions contains the optional parameters used by the SendVideoNote method.
type VideoNoteOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
Thumbnail InputFile
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
Length int `query:"length"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
Thumbnail InputFile
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
Duration int `query:"duration"`
Length int `query:"length"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// MediaGroupOptions contains the optional parameters used by the SendMediaGroup method.
type MediaGroupOptions struct {
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// This is a custom constant to set an infinite live period value in LocationOptions and EditLocationOptions.
const InfiniteLivePeriod = 0x7FFFFFFF
// LocationOptions contains the optional parameters used by the SendLocation method.
type LocationOptions struct {
BusinessConnectionID string `query:"business_connection_id"`
MessageEffectID string `query:"message_effect_id"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
HorizontalAccuracy float64 `query:"horizontal_accuracy"`
@@ -449,46 +487,62 @@ type LocationOptions struct {
// EditLocationOptions contains the optional parameters used by the EditMessageLiveLocation method.
type EditLocationOptions struct {
BusinessConnectionID string `query:"business_connection_id"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
HorizontalAccuracy float64 `query:"horizontal_accuracy"`
Heading int `query:"heading"`
LivePeriod int `query:"live_period"`
ProximityAlertRadius int `query:"proximity_alert_radius"`
}
// StopLocationOptions contains the optional parameters used by the StopMessageLiveLocation method.
type StopLocationOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
}
// VenueOptions contains the optional parameters used by the SendVenue method.
type VenueOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
FoursquareID string `query:"foursquare_id"`
FoursquareType string `query:"foursquare_type"`
GooglePlaceType string `query:"google_place_type"`
GooglePlaceID string `query:"google_place_id"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
FoursquareID string `query:"foursquare_id"`
FoursquareType string `query:"foursquare_type"`
GooglePlaceType string `query:"google_place_type"`
GooglePlaceID string `query:"google_place_id"`
MessageEffectID string `query:"message_effect_id"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// ContactOptions contains the optional parameters used by the SendContact method.
type ContactOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
VCard string `query:"vcard"`
LastName string `query:"last_name"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
VCard string `query:"vcard"`
LastName string `query:"last_name"`
MessageEffectID string `query:"message_effect_id"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MessageThreadID int `query:"message_thread_id"`
DisableNotification bool `query:"disable_notification"`
ProtectContent bool `query:"protect_content"`
}
// PollOptions contains the optional parameters used by the SendPoll method.
type PollOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
BusinessConnectionID string `query:"business_connection_id"`
Explanation string `query:"explanation"`
MessageEffectID string `query:"message_effect_id"`
ExplanationParseMode ParseMode `query:"explanation_parse_mode"`
QuestionParseMode ParseMode `query:"question_parse_mode"`
Type PollType `query:"type"`
ExplanationEntities []MessageEntity `query:"explanation_entities"`
MessageThreadID int `query:"message_thread_id"`
QuestionEntities []MessageEntity `query:"question_entities"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
CorrectOptionID int `query:"correct_option_id"`
MessageThreadID int `query:"message_thread_id"`
CloseDate int `query:"close_date"`
OpenPeriod int `query:"open_period"`
IsClosed bool `query:"is_closed"`
@@ -498,6 +552,12 @@ type PollOptions struct {
IsAnonymous bool `query:"is_anonymous"`
}
// StopPollOptions contains the optional parameters used by the StopPoll method.
type StopPollOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
}
// BanOptions contains the optional parameters used by the BanChatMember method.
type BanOptions struct {
UntilDate int `query:"until_date"`
@@ -580,23 +640,33 @@ func NewInlineMessageID(ID string) MessageIDOptions {
// MessageTextOptions contains the optional parameters used by the EditMessageText method.
type MessageTextOptions struct {
ParseMode ParseMode `query:"parse_mode"`
Entities []MessageEntity `query:"entities"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
LinkPreviewOptions LinkPreviewOptions `query:"link_preview_options"`
ParseMode ParseMode `query:"parse_mode"`
BusinessConnectionID string `query:"business_connection_id"`
Entities []MessageEntity `query:"entities"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
LinkPreviewOptions LinkPreviewOptions `query:"link_preview_options"`
}
// MessageCaptionOptions contains the optional parameters used by the EditMessageCaption method.
type MessageCaptionOptions struct {
Caption string `query:"caption"`
ParseMode ParseMode `query:"parse_mode"`
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
Caption string `query:"caption"`
BusinessConnectionID string `query:"business_connection_id"`
ParseMode ParseMode `query:"parse_mode"`
CaptionEntities []MessageEntity `query:"caption_entities"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
ShowCaptionAboveMedia bool `query:"show_caption_above_media"`
}
// MessageReplyMarkup contains the optional parameters used by the method which only require reply_markup.
type MessageReplyMarkup struct {
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
// MessageMediaOptions contains the optional parameters used by the EditMessageMedia method.
type MessageMediaOptions struct {
ReplyMarkup ReplyMarkup `query:"reply_markup"`
BusinessConnectionID string `query:"business_connection_id"`
}
// MessageReplyMarkupOptions contains the optional parameters used by the EditMessageReplyMarkup method.
type MessageReplyMarkupOptions struct {
BusinessConnectionID string `query:"business_connection_id"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
}
// CommandOptions contains the optional parameters used by the SetMyCommands, DeleteMyCommands and GetMyCommands methods.
@@ -610,17 +680,19 @@ type InvoiceOptions struct {
StartParameter string `query:"start_parameter"`
ProviderData string `query:"provider_data"`
PhotoURL string `query:"photo_url"`
ProviderToken string `query:"provider_token"`
MessageEffectID string `query:"message_effect_id"`
ReplyMarkup InlineKeyboardMarkup `query:"reply_markup"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
SuggestedTipAmount []int `query:"suggested_tip_amounts"`
MessageThreadID int `query:"message_thread_id"`
ReplyParameters ReplyParameters `query:"reply_parameters"`
MaxTipAmount int `query:"max_tip_amount"`
PhotoSize int `query:"photo_size"`
PhotoWidth int `query:"photo_width"`
PhotoHeight int `query:"photo_height"`
MaxTipAmount int `query:"max_tip_amount"`
NeedPhoneNumber bool `query:"need_phone_number"`
NeepShippingAddress bool `query:"need_shipping_address"`
MessageThreadID int `query:"message_thread_id"`
SendPhoneNumberToProvider bool `query:"send_phone_number_to_provider"`
NeepShippingAddress bool `query:"need_shipping_address"`
NeedPhoneNumber bool `query:"need_phone_number"`
SendEmailToProvider bool `query:"send_email_to_provider"`
IsFlexible bool `query:"is_flexible"`
DisableNotification bool `query:"disable_notification"`
@@ -633,6 +705,7 @@ type InvoiceOptions struct {
type CreateInvoiceLinkOptions struct {
ProviderData string `query:"provider_data"`
PhotoURL string `query:"photo_url"`
ProviderToken string `query:"provider_token"`
SuggestedTipAmounts []int `query:"suggested_tip_amounts"`
PhotoSize int `query:"photo_size"`
PhotoWidth int `query:"photo_width"`
@@ -679,7 +752,8 @@ type EditTopicOptions struct {
// ChatActionOptions contains the optional parameters used by the SendChatAction API method.
type ChatActionOptions struct {
MessageThreadID int `query:"message_thread_id"`
BusinessConnectionID string `query:"business_connection_id"`
MessageThreadID int `query:"message_thread_id"`
}
// MessageReactionOptions contains the optional parameters used by the SetMessageReaction API method.

View File

@@ -224,5 +224,5 @@ func (a API) SetPassportDataErrors(userID int64, errors []PassportElementError)
vals.Set("user_id", itoa(userID))
vals.Set("errors", string(errorsArr))
return get[APIResponseBool](a.base, "setPassportDataErrors", vals)
return res, a.client.get(a.base, "setPassportDataErrors", vals, &res)
}

View File

@@ -96,8 +96,90 @@ type PreCheckoutQuery struct {
TotalAmount int `json:"total_amount"`
}
// RevenueWithdrawalState describes the state of a revenue withdrawal operation.
type RevenueWithdrawalState interface {
ImplementsRevenueWithdrawalState()
}
// RevenueWithdrawalStatePending describes the state of a withdrawal in progress.
type RevenueWithdrawalStatePending struct {
Type string `json:"type"`
}
// ImplementsRevenueWithdrawalState is used to implement the RevenueWithdrawalState interface.
func (r RevenueWithdrawalStatePending) ImplementsRevenueWithdrawalState() {}
// RevenueWithdrawalStateSucceeded describes the state of a succeeded withdrawal.
type RevenueWithdrawalStateSucceeded struct {
Type string `json:"type"`
URL string `json:"url"`
Date int `json:"date"`
}
// ImplementsRevenueWithdrawalState is used to implement the RevenueWithdrawalState interface.
func (r RevenueWithdrawalStateSucceeded) ImplementsRevenueWithdrawalState() {}
// RevenueWithdrawalStateFailed describes the state of a failed withdrawal, in which the transaction was refunded.
type RevenueWithdrawalStateFailed struct {
Type string `json:"type"`
}
// ImplementsRevenueWithdrawalState is used to implement the RevenueWithdrawalState interface.
func (r RevenueWithdrawalStateFailed) ImplementsRevenueWithdrawalState() {}
// TransactionPartner describes the source of a transaction, or its recipient for outgoing transactions.
type TransactionPartner interface {
ImplementsTransactionPartner()
}
// TransactionPartnerFragment describes a withdrawal transaction with Fragment.
type TransactionPartnerFragment struct {
WithdrawalState RevenueWithdrawalState `json:"withdrawal_state"`
Type string `json:"type"`
}
// ImplementsTransactionPartner is used to implement the TransactionPartner interface.
func (t TransactionPartnerFragment) ImplementsTransactionPartner() {}
// TransactionPartnerUser describes a transaction with a user.
type TransactionPartnerUser struct {
Type string `json:"type"`
User User `json:"user"`
}
// ImplementsTransactionPartner is used to implement the TransactionPartner interface.
func (t TransactionPartnerUser) ImplementsTransactionPartner() {}
// TransactionPartnerOther describes a transaction with an unknown source or recipient.
type TransactionPartnerOther struct {
Type string `json:"type"`
}
// ImplementsTransactionPartner is used to implement the TransactionPartner interface.
func (t TransactionPartnerOther) ImplementsTransactionPartner() {}
// StarTransaction describes a Telegram Star transaction.
type StarTransaction struct {
Source TransactionPartner `json:"source"`
Receiver TransactionPartner `json:"receiver"`
ID string `json:"id"`
Amount int `json:"amount"`
Date int `json:"date"`
}
// StarTransactions contains a list of Telegram Star transactions.
type StarTransactions struct {
Transaction []StarTransaction `json:"transaction"`
}
// StarTransactionsOptions contains the optional parameters used by the GetStarTransactions method.
type StarTransactionsOptions struct {
Offset int `query:"offset"`
Limit int `query:"limit"`
}
// SendInvoice is used to send invoices.
func (a API) SendInvoice(chatID int64, title, description, payload, providerToken, currency string, prices []LabeledPrice, opts *InvoiceOptions) (res APIResponseMessage, err error) {
func (a API) SendInvoice(chatID int64, title, description, payload, currency string, prices []LabeledPrice, opts *InvoiceOptions) (res APIResponseMessage, err error) {
var vals = make(url.Values)
p, err := json.Marshal(prices)
@@ -109,10 +191,26 @@ func (a API) SendInvoice(chatID int64, title, description, payload, providerToke
vals.Set("title", title)
vals.Set("description", description)
vals.Set("payload", payload)
vals.Set("provider_token", providerToken)
vals.Set("currency", currency)
vals.Set("prices", string(p))
return get[APIResponseMessage](a.base, "sendInvoice", addValues(vals, opts))
return res, a.client.get(a.base, "sendInvoice", addValues(vals, opts), &res)
}
// CreateInvoiceLink creates a link for an invoice.
func (a API) CreateInvoiceLink(title, description, payload, currency string, prices []LabeledPrice, opts *CreateInvoiceLinkOptions) (res APIResponseBase, err error) {
var vals = make(url.Values)
p, err := json.Marshal(prices)
if err != nil {
return res, err
}
vals.Set("title", title)
vals.Set("description", description)
vals.Set("payload", payload)
vals.Set("currency", currency)
vals.Set("prices", string(p))
return res, a.client.get(a.base, "createInvoiceLink", addValues(vals, opts), &res)
}
// AnswerShippingQuery is used to reply to shipping queries.
@@ -123,7 +221,7 @@ func (a API) AnswerShippingQuery(shippingQueryID string, ok bool, opts *Shipping
vals.Set("shipping_query_id", shippingQueryID)
vals.Set("ok", btoa(ok))
return get[APIResponseBase](a.base, "answerShippingQuery", addValues(vals, opts))
return res, a.client.get(a.base, "answerShippingQuery", addValues(vals, opts), &res)
}
// AnswerPreCheckoutQuery is used to respond to such pre-checkout queries.
@@ -135,23 +233,19 @@ func (a API) AnswerPreCheckoutQuery(preCheckoutQueryID string, ok bool, opts *Pr
vals.Set("pre_checkout_query_id", preCheckoutQueryID)
vals.Set("ok", btoa(ok))
return get[APIResponseBase](a.base, "answerPreCheckoutQuery", addValues(vals, opts))
return res, a.client.get(a.base, "answerPreCheckoutQuery", addValues(vals, opts), &res)
}
// CreateInvoiceLink creates a link for an invoice.
func (a API) CreateInvoiceLink(title, description, payload, providerToken, currency string, prices []LabeledPrice, opts *CreateInvoiceLinkOptions) (res APIResponseBase, err error) {
// GetStarTransactions returns the bot's Telegram Star transactions in chronological order.
func (a API) GetStarTransactions(opts *StarTransactionsOptions) (res APIResponseStarTransactions, err error) {
return res, a.client.get(a.base, "getStarTransactions", urlValues(opts), &res)
}
// RefundStarPayment refunds a successful payment in Telegram Stars.
func (a API) RefundStarPayment(userID int64, telegramPaymentChargeID string) (res APIResponseBool, err error) {
var vals = make(url.Values)
p, err := json.Marshal(prices)
if err != nil {
return res, err
}
vals.Set("title", title)
vals.Set("description", description)
vals.Set("payload", payload)
vals.Set("provider_token", providerToken)
vals.Set("currency", currency)
vals.Set("prices", string(p))
return get[APIResponseBase](a.base, "createInvoiceLink", addValues(vals, opts))
vals.Set("user_id", itoa(userID))
vals.Set("telegram_payment_charge_id", telegramPaymentChargeID)
return res, a.client.get(a.base, "refundStarPayment", vals, &res)
}

View File

@@ -70,10 +70,6 @@ func scan(i any, v url.Values) url.Values {
return v
}
func querify(i any) string {
return scan(i, url.Values{}).Encode()
}
func urlValues(i any) url.Values {
if i == nil {
return nil

View File

@@ -20,7 +20,6 @@ package echotron
import (
"encoding/json"
"fmt"
"net/url"
)
@@ -50,8 +49,6 @@ type StickerSet struct {
Name string `json:"name"`
StickerType StickerSetType `json:"sticker_type"`
Stickers []Sticker `json:"stickers"`
IsAnimated bool `json:"is_animated"`
IsVideo bool `json:"is_video"`
}
// StickerSetType represents the type of a sticker or of the entire set
@@ -100,16 +97,17 @@ type NewStickerSetOptions struct {
// InputSticker is a struct which describes a sticker to be added to a sticker set.
type InputSticker struct {
Sticker InputFile `json:"-"`
EmojiList []string `json:"emoji_list"`
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
Keywords *[]string `json:"keywords,omitempty"`
Format StickerFormat `json:"format"`
Sticker InputFile `json:"-"`
EmojiList []string `json:"emoji_list"`
}
// stickerEnvelope is a generic struct for all the various structs under the InputSticker interface.
type stickerEnvelope struct {
InputSticker
Sticker string `json:"sticker"`
InputSticker
}
// SendSticker is used to send static .WEBP or animated .TGS stickers.
@@ -118,7 +116,7 @@ func (a API) SendSticker(stickerID string, chatID int64, opts *StickerOptions) (
vals.Set("sticker", stickerID)
vals.Set("chat_id", itoa(chatID))
return get[APIResponseMessage](a.base, "sendSticker", addValues(vals, opts))
return res, a.client.get(a.base, "sendSticker", addValues(vals, opts), &res)
}
// GetStickerSet is used to get a sticker set.
@@ -126,30 +124,16 @@ func (a API) GetStickerSet(name string) (res APIResponseStickerSet, err error) {
var vals = make(url.Values)
vals.Set("name", name)
return get[APIResponseStickerSet](a.base, "getStickerSet", vals)
return res, a.client.get(a.base, "getStickerSet", vals, &res)
}
// GetCustomEmojiStickers is used to get information about custom emoji stickers by their identifiers.
func (a API) GetCustomEmojiStickers(customEmojiIDs ...string) (res APIResponseStickers, err error) {
var vals = make(url.Values)
jsn, _ := json.Marshal(customEmojiIDs)
var url = fmt.Sprintf(
"%sgetCustomEmojiStickers?custom_emoji_ids=%s",
a.base,
jsn,
)
cnt, err := sendGetRequest(url)
if err != nil {
return
}
if err = json.Unmarshal(cnt, &res); err != nil {
return
}
err = check(res)
return
vals.Set("custom_emoji_ids", string(jsn))
return res, a.client.get(a.base, "getCustomEmojiStickers", vals, &res)
}
// UploadStickerFile is used to upload a .PNG file with a sticker for later use in
@@ -159,18 +143,17 @@ func (a API) UploadStickerFile(userID int64, sticker InputFile, format StickerFo
vals.Set("user_id", itoa(userID))
vals.Set("sticker_format", string(format))
return postFile[APIResponseFile](a.base, "uploadStickerFile", "sticker", sticker, InputFile{}, vals)
return res, a.client.postFile(a.base, "uploadStickerFile", "sticker", sticker, InputFile{}, vals, &res)
}
// CreateNewStickerSet is used to create a new sticker set owned by a user.
func (a API) CreateNewStickerSet(userID int64, name, title string, stickers []InputSticker, format StickerFormat, opts *NewStickerSetOptions) (res APIResponseBool, err error) {
func (a API) CreateNewStickerSet(userID int64, name, title string, stickers []InputSticker, opts *NewStickerSetOptions) (res APIResponseBool, err error) {
var vals = make(url.Values)
vals.Set("user_id", itoa(userID))
vals.Set("name", name)
vals.Set("title", title)
vals.Set("sticker_format", string(format))
return postStickers[APIResponseBool](a.base, "createNewStickerSet", addValues(vals, opts), stickers...)
return res, a.client.postStickers(a.base, "createNewStickerSet", addValues(vals, opts), &res, stickers...)
}
// AddStickerToSet is used to add a new sticker to a set created by the bot.
@@ -179,7 +162,7 @@ func (a API) AddStickerToSet(userID int64, name string, sticker InputSticker) (r
vals.Set("user_id", itoa(userID))
vals.Set("name", name)
return postStickers[APIResponseBool](a.base, "addStickerToSet", vals, sticker)
return res, a.client.postStickers(a.base, "addStickerToSet", vals, &res, sticker)
}
// SetStickerPositionInSet is used to move a sticker in a set created by the bot to a specific position.
@@ -188,7 +171,7 @@ func (a API) SetStickerPositionInSet(sticker string, position int) (res APIRespo
vals.Set("sticker", sticker)
vals.Set("position", itoa(int64(position)))
return get[APIResponseBase](a.base, "setStickerPositionInSet", vals)
return res, a.client.get(a.base, "setStickerPositionInSet", vals, &res)
}
// DeleteStickerFromSet is used to delete a sticker from a set created by the bot.
@@ -196,7 +179,18 @@ func (a API) DeleteStickerFromSet(sticker string) (res APIResponseBase, err erro
var vals = make(url.Values)
vals.Set("sticker", sticker)
return get[APIResponseBase](a.base, "deleteStickerFromSet", vals)
return res, a.client.get(a.base, "deleteStickerFromSet", vals, &res)
}
// ReplaceStickerInSet is used to replace an existing sticker in a sticker set with a new one.
// The method is equivalent to calling DeleteStickerFromSet, then AddStickerToSet, then SetStickerPositionInSet.
func (a API) ReplaceStickerInSet(userID int64, name string, old_sticker string, sticker InputSticker) (res APIResponseBool, err error) {
var vals = make(url.Values)
vals.Set("user_id", itoa(userID))
vals.Set("name", name)
vals.Set("old_sticker", old_sticker)
return res, a.client.postStickers(a.base, "replaceStickerInSet", vals, &res, sticker)
}
// SetStickerEmojiList is used to change the list of emoji assigned to a regular or custom emoji sticker.
@@ -208,7 +202,7 @@ func (a API) SetStickerEmojiList(sticker string, emojis []string) (res APIRespon
vals.Set("sticker", sticker)
vals.Set("emoji_list", string(jsn))
return get[APIResponseBool](a.base, "setStickerEmojiList", vals)
return res, a.client.get(a.base, "setStickerEmojiList", vals, &res)
}
// SetStickerKeywords is used to change search keywords assigned to a regular or custom emoji sticker.
@@ -220,7 +214,7 @@ func (a API) SetStickerKeywords(sticker string, keywords []string) (res APIRespo
vals.Set("sticker", sticker)
vals.Set("keywords", string(jsn))
return get[APIResponseBool](a.base, "setStickerKeywords", vals)
return res, a.client.get(a.base, "setStickerKeywords", vals, &res)
}
// SetStickerMaskPosition is used to change the mask position of a mask sticker.
@@ -232,7 +226,7 @@ func (a API) SetStickerMaskPosition(sticker string, mask MaskPosition) (res APIR
vals.Set("sticker", sticker)
vals.Set("mask_position", string(jsn))
return get[APIResponseBool](a.base, "setStickerMaskPosition", vals)
return res, a.client.get(a.base, "setStickerMaskPosition", vals, &res)
}
// SetStickerSetTitle is used to set the title of a created sticker set.
@@ -241,16 +235,17 @@ func (a API) SetStickerSetTitle(name, title string) (res APIResponseBool, err er
vals.Set("name", name)
vals.Set("title", title)
return get[APIResponseBool](a.base, "setStickerSetTitle", vals)
return res, a.client.get(a.base, "setStickerSetTitle", vals, &res)
}
// SetStickerSetThumbnail is used to set the thumbnail of a sticker set.
func (a API) SetStickerSetThumbnail(name string, userID int64, thumbnail InputFile) (res APIResponseBase, err error) {
func (a API) SetStickerSetThumbnail(name string, userID int64, thumbnail InputFile, format StickerFormat) (res APIResponseBase, err error) {
var vals = make(url.Values)
vals.Set("name", name)
vals.Set("user_id", itoa(userID))
return postFile[APIResponseBase](a.base, "setStickerSetThumbnail", "thumbnail", thumbnail, InputFile{}, vals)
vals.Set("format", string(format))
return res, a.client.postFile(a.base, "setStickerSetThumbnail", "thumbnail", thumbnail, InputFile{}, vals, &res)
}
// SetCustomEmojiStickerSetThumbnail is used to set the thumbnail of a custom emoji sticker set.
@@ -259,7 +254,7 @@ func (a API) SetCustomEmojiStickerSetThumbnail(name, emojiID string) (res APIRes
vals.Set("name", name)
vals.Set("custom_emoji_id", emojiID)
return get[APIResponseBool](a.base, "setCustomEmojiStickerSetThumbnail", vals)
return res, a.client.get(a.base, "setCustomEmojiStickerSetThumbnail", vals, &res)
}
// DeleteStickerSet is used to delete a sticker set that was created by the bot.
@@ -267,10 +262,10 @@ func (a API) DeleteStickerSet(name string) (res APIResponseBool, err error) {
var vals = make(url.Values)
vals.Set("name", name)
return get[APIResponseBool](a.base, "DeleteStickerSet", vals)
return res, a.client.get(a.base, "DeleteStickerSet", vals, &res)
}
// GetForumTopicIconStickers is used to get custom emoji stickers, which can be used as a forum topic icon by any user.
func (a API) GetForumTopicIconStickers() (res APIResponseStickers, err error) {
return get[APIResponseStickers](a.base, "getForumTopicIconStickers", nil)
return res, a.client.get(a.base, "getForumTopicIconStickers", nil, &res)
}

View File

@@ -23,28 +23,40 @@ import "encoding/json"
// Update represents an incoming update.
// At most one of the optional parameters can be present in any given update.
type Update struct {
ChatJoinRequest *ChatJoinRequest `json:"chat_join_request,omitempty"`
ChatBoost *ChatBoostUpdated `json:"chat_boost,omitempty"`
RemovedChatBoost *ChatBoostRemoved `json:"removed_chat_boost,omitempty"`
Message *Message `json:"message,omitempty"`
EditedMessage *Message `json:"edited_message,omitempty"`
ChannelPost *Message `json:"channel_post,omitempty"`
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"`
MessageReactionCount *MessageReactionCountUpdated `json:"message_reaction_count,omitempty"`
InlineQuery *InlineQuery `json:"inline_query,omitempty"`
ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result,omitempty"`
CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"`
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
MyChatMember *ChatMemberUpdated `json:"my_chat_member,omitempty"`
ChatMember *ChatMemberUpdated `json:"chat_member,omitempty"`
ID int `json:"update_id"`
ChatJoinRequest *ChatJoinRequest `json:"chat_join_request,omitempty"`
ChatBoost *ChatBoostUpdated `json:"chat_boost,omitempty"`
RemovedChatBoost *ChatBoostRemoved `json:"removed_chat_boost,omitempty"`
Message *Message `json:"message,omitempty"`
EditedMessage *Message `json:"edited_message,omitempty"`
ChannelPost *Message `json:"channel_post,omitempty"`
EditedChannelPost *Message `json:"edited_channel_post,omitempty"`
BusinessConnection *BusinessConnection `json:"business_connection,omitempty"`
BusinessMessage *Message `json:"business_message,omitempty"`
EditedBusinessMessage *Message `json:"edited_business_message,omitempty"`
DeletedBusinessMessages *BusinessMessagesDeleted `json:"deleted_business_messages,omitempty"`
MessageReaction *MessageReactionUpdated `json:"message_reaction,omitempty"`
MessageReactionCount *MessageReactionCountUpdated `json:"message_reaction_count,omitempty"`
InlineQuery *InlineQuery `json:"inline_query,omitempty"`
ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result,omitempty"`
CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"`
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
Poll *Poll `json:"poll,omitempty"`
PollAnswer *PollAnswer `json:"poll_answer,omitempty"`
MyChatMember *ChatMemberUpdated `json:"my_chat_member,omitempty"`
ChatMember *ChatMemberUpdated `json:"chat_member,omitempty"`
ID int `json:"update_id"`
}
// ChatID returns the ID of the chat the update is coming from.
func (u Update) ChatID() int64 {
switch {
case u.ChatJoinRequest != nil:
return u.ChatJoinRequest.Chat.ID
case u.ChatBoost != nil:
return u.ChatBoost.Chat.ID
case u.RemovedChatBoost != nil:
return u.RemovedChatBoost.Chat.ID
case u.Message != nil:
return u.Message.Chat.ID
case u.EditedMessage != nil:
@@ -53,6 +65,18 @@ func (u Update) ChatID() int64 {
return u.ChannelPost.Chat.ID
case u.EditedChannelPost != nil:
return u.EditedChannelPost.Chat.ID
case u.BusinessConnection != nil:
return u.BusinessConnection.User.ID
case u.BusinessMessage != nil:
return u.BusinessMessage.Chat.ID
case u.EditedBusinessMessage != nil:
return u.EditedBusinessMessage.Chat.ID
case u.DeletedBusinessMessages != nil:
return u.DeletedBusinessMessages.Chat.ID
case u.MessageReaction != nil:
return u.MessageReaction.Chat.ID
case u.MessageReactionCount != nil:
return u.MessageReactionCount.Chat.ID
case u.InlineQuery != nil:
return u.InlineQuery.From.ID
case u.ChosenInlineResult != nil:
@@ -63,12 +87,12 @@ func (u Update) ChatID() int64 {
return u.ShippingQuery.From.ID
case u.PreCheckoutQuery != nil:
return u.PreCheckoutQuery.From.ID
case u.PollAnswer != nil:
return u.PollAnswer.User.ID
case u.MyChatMember != nil:
return u.MyChatMember.Chat.ID
case u.ChatMember != nil:
return u.ChatMember.Chat.ID
case u.ChatJoinRequest != nil:
return u.ChatJoinRequest.Chat.ID
default:
return 0
}
@@ -215,9 +239,9 @@ func (a APIResponseString) Base() APIResponseBase {
}
// APIResponseChat represents the incoming response from Telegram servers.
// Used by all methods that return a Chat object on success.
// Used by all methods that return a ChatFullInfo object on success.
type APIResponseChat struct {
Result *Chat `json:"result,omitempty"`
Result *ChatFullInfo `json:"result,omitempty"`
APIResponseBase
}
@@ -443,7 +467,7 @@ func (a APIResponseBotName) Base() APIResponseBase {
}
// APIResponseUserChatBoosts represents the incoming response from Telegram servers.
// Used by all methods that return a BotName object on success.
// Used by all methods that return a UserChatBoosts object on success.
type APIResponseUserChatBoosts struct {
Result *UserChatBoosts `json:"result,omitempty"`
APIResponseBase
@@ -454,6 +478,30 @@ func (a APIResponseUserChatBoosts) Base() APIResponseBase {
return a.APIResponseBase
}
// APIResponseBusinessConnection represents the incoming response from Telegram servers.
// Used by all methods that return a BusinessConnection object on success.
type APIResponseBusinessConnection struct {
Result *BusinessConnection `json:"result,omitempty"`
APIResponseBase
}
// Base returns the contained object of type APIResponseBase.
func (a APIResponseBusinessConnection) Base() APIResponseBase {
return a.APIResponseBase
}
// APIResponseStarTransactions represents the incoming response from Telegram servers.
// Used by all methods that return a StarTransactions object on success.
type APIResponseStarTransactions struct {
Result *StarTransactions `json:"result,omitempty"`
APIResponseBase
}
// Base returns the contained object of type APIResponseBase.
func (a APIResponseStarTransactions) Base() APIResponseBase {
return a.APIResponseBase
}
// User represents a Telegram user or bot.
type User struct {
FirstName string `json:"first_name"`
@@ -465,49 +513,67 @@ type User struct {
CanJoinGroups bool `json:"can_join_groups,omitempty"`
CanReadAllGroupMessages bool `json:"can_read_all_group_messages,omitempty"`
SupportsInlineQueries bool `json:"supports_inline_queries,omitempty"`
CanConnectToBusiness bool `json:"can_connect_to_business,omitempty"`
IsPremium bool `json:"is_premium,omitempty"`
AddedToAttachmentMenu bool `json:"added_to_attachment_menu,omitempty"`
}
// Chat represents a chat.
type Chat struct {
Permissions *ChatPermissions `json:"permissions,omitempty"`
Location *ChatLocation `json:"location,omitempty"`
PinnedMessage *Message `json:"pinned_message,omitempty"`
Photo *ChatPhoto `json:"photo,omitempty"`
ActiveUsernames *[]string `json:"active_usernames,omitempty"`
AvailableReactions *[]ReactionType `json:"available_reactions,omitempty"`
BackgroundCustomEmojiID string `json:"background_custom_emoji_id,omitempty"`
ProfileBackgroundCustomEmojiID string `json:"profile_background_custom_emoji_id,omitempty"`
Bio string `json:"bio,omitempty"`
Username string `json:"username,omitempty"`
Title string `json:"title,omitempty"`
StickerSetName string `json:"sticker_set_name,omitempty"`
Description string `json:"description,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
InviteLink string `json:"invite_link,omitempty"`
EmojiStatusCustomEmojiID string `json:"emoji_status_custom_emoji_id,omitempty"`
Type string `json:"type"`
CustomEmojiStickerSetName string `json:"custom_emoji_sticker_set_name,omitempty"`
AccentColorID int `json:"accent_color_id,omitempty"`
ProfileAccentColorID int `json:"profile_accent_color_id,omitempty"`
EmojiStatusExpirationDate int `json:"emoji_status_expiration_date,omitempty"`
MessageAutoDeleteTime int `json:"message_auto_delete_time,omitempty"`
SlowModeDelay int `json:"slow_mode_delay,omitempty"`
UnrestrictBoostCount int `json:"unrestrict_boost_count,omitempty"`
LinkedChatID int64 `json:"linked_chat_id,omitempty"`
ID int64 `json:"id"`
IsForum bool `json:"is_forum,omitempty"`
HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled,omitempty"`
HasHiddenMembers bool `json:"has_hidden_members,omitempty"`
HasProtectedContent bool `json:"has_protected_content,omitempty"`
HasVisibleHistory bool `json:"has_visible_history,omitempty"`
HasPrivateForwards bool `json:"has_private_forwards,omitempty"`
CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"`
JoinToSendMessages bool `json:"join_to_send_messages,omitempty"`
JoinByRequest bool `json:"join_by_request,omitempty"`
HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages,omitempty"`
Type string `json:"type"`
Title string `json:"title,omitempty"`
Username string `json:"username,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
ID int64 `json:"id"`
IsForum bool `json:"is_forum,omitempty"`
}
// ChatFullInfo contains full information about a chat.
type ChatFullInfo struct {
Permissions *ChatPermissions `json:"permissions,omitempty"`
Location *ChatLocation `json:"location,omitempty"`
PinnedMessage *Message `json:"pinned_message,omitempty"`
Photo *ChatPhoto `json:"photo,omitempty"`
ActiveUsernames *[]string `json:"active_usernames,omitempty"`
AvailableReactions *[]ReactionType `json:"available_reactions,omitempty"`
BusinessIntro *BusinessIntro `json:"business_intro,omitempty"`
BusinessLocation *BusinessLocation `json:"business_location,omitempty"`
BusinessOpeningHours *BusinessOpeningHours `json:"business_opening_hours,omitempty"`
PersonalChat *Chat `json:"personal_chat,omitempty"`
Birthdate *Birthdate `json:"birthdate,omitempty"`
BackgroundCustomEmojiID string `json:"background_custom_emoji_id,omitempty"`
ProfileBackgroundCustomEmojiID string `json:"profile_background_custom_emoji_id,omitempty"`
Bio string `json:"bio,omitempty"`
Username string `json:"username,omitempty"`
Title string `json:"title,omitempty"`
StickerSetName string `json:"sticker_set_name,omitempty"`
Description string `json:"description,omitempty"`
FirstName string `json:"first_name,omitempty"`
LastName string `json:"last_name,omitempty"`
InviteLink string `json:"invite_link,omitempty"`
EmojiStatusCustomEmojiID string `json:"emoji_status_custom_emoji_id,omitempty"`
Type string `json:"type"`
CustomEmojiStickerSetName string `json:"custom_emoji_sticker_set_name,omitempty"`
AccentColorID int `json:"accent_color_id,omitempty"`
MaxReactionCount int `json:"max_reaction_count,omitempty"`
ProfileAccentColorID int `json:"profile_accent_color_id,omitempty"`
EmojiStatusExpirationDate int `json:"emoji_status_expiration_date,omitempty"`
MessageAutoDeleteTime int `json:"message_auto_delete_time,omitempty"`
SlowModeDelay int `json:"slow_mode_delay,omitempty"`
UnrestrictBoostCount int `json:"unrestrict_boost_count,omitempty"`
LinkedChatID int64 `json:"linked_chat_id,omitempty"`
ID int64 `json:"id"`
IsForum bool `json:"is_forum,omitempty"`
HasAggressiveAntiSpamEnabled bool `json:"has_aggressive_anti_spam_enabled,omitempty"`
HasHiddenMembers bool `json:"has_hidden_members,omitempty"`
HasProtectedContent bool `json:"has_protected_content,omitempty"`
HasVisibleHistory bool `json:"has_visible_history,omitempty"`
HasPrivateForwards bool `json:"has_private_forwards,omitempty"`
CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"`
JoinToSendMessages bool `json:"join_to_send_messages,omitempty"`
JoinByRequest bool `json:"join_by_request,omitempty"`
HasRestrictedVoiceAndVideoMessages bool `json:"has_restricted_voice_and_video_messages,omitempty"`
}
// Message represents a message.
@@ -561,12 +627,16 @@ type Message struct {
LinkPreviewOptions *LinkPreviewOptions `json:"link_preview_options,omitempty"`
ForwardOrigin *MessageOrigin `json:"forward_origin,omitempty"`
BoostAdded *ChatBoostAdded `json:"boost_added,omitempty"`
ChatBackgroundSet *ChatBackground `json:"chat_background_set,omitempty"`
SenderBusinessBot *User `json:"sender_business_bot,omitempty"`
MediaGroupID string `json:"media_group_id,omitempty"`
ConnectedWebsite string `json:"connected_website,omitempty"`
NewChatTitle string `json:"new_chat_title,omitempty"`
AuthorSignature string `json:"author_signature,omitempty"`
Caption string `json:"caption,omitempty"`
Text string `json:"text,omitempty"`
BusinessConnectionID string `json:"business_connection_id,omitempty"`
EffectID string `json:"effect_id,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
NewChatPhoto []*PhotoSize `json:"new_chat_photo,omitempty"`
NewChatMembers []*User `json:"new_chat_members,omitempty"`
@@ -588,6 +658,8 @@ type Message struct {
ChannelChatCreated bool `json:"channel_chat_created,omitempty"`
HasProtectedContent bool `json:"has_protected_content,omitempty"`
HasMediaSpoiler bool `json:"has_media_spoiler,omitempty"`
IsFromOffline bool `json:"is_from_offline,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// MessageID represents a unique message identifier.
@@ -701,8 +773,16 @@ type Dice struct {
// PollOption contains information about one answer option in a poll.
type PollOption struct {
Text string `json:"text"`
VoterCount int `json:"voter_count"`
Text string `json:"text"`
TextEntities []*MessageEntity `json:"text_entities,omitempty"`
VoterCount int `json:"voter_count"`
}
// InputPollOption contains information about one answer option in a poll to send.
type InputPollOption struct {
Text string `json:"text"`
TextParseMode ParseMode `json:"text_parse_mode,omitempty"`
TextEntities []*MessageEntity `json:"text_entities,omitempty"`
}
// PollAnswer represents an answer of a user in a non-anonymous poll.
@@ -720,6 +800,7 @@ type Poll struct {
Explanation string `json:"explanation,omitempty"`
ID string `json:"id"`
ExplanationEntities []*MessageEntity `json:"explanation_entities,omitempty"`
QuestionEntities []*MessageEntity `json:"question_entities,omitempty"`
Options []*PollOption `json:"options"`
OpenPeriod int `json:"open_period,omitempty"`
TotalVoterCount int `json:"total_voter_count"`
@@ -885,12 +966,13 @@ type ChatMember struct {
// ChatMemberUpdated represents changes in the status of a chat member.
type ChatMemberUpdated struct {
InviteLink *ChatInviteLink `json:"invite_link,omitempty"`
Chat Chat `json:"chat"`
From User `json:"from"`
OldChatMember ChatMember `json:"old_chat_member"`
NewChatMember ChatMember `json:"new_chat_member"`
Chat Chat `json:"chat"`
ViaChatFolderInviteLink bool `json:"via_chat_folder_invite_link,omitempty"`
Date int `json:"date"`
ViaChatFolderInviteLink bool `json:"via_chat_folder_invite_link,omitempty"`
ViaJoinRequest bool `json:"via_join_request,omitempty"`
}
// ChatPermissions describes actions that a non-administrator user is allowed to take in a chat.
@@ -911,6 +993,38 @@ type ChatPermissions struct {
CanManageTopics bool `json:"can_manage_topics,omitempty"`
}
// Birthdate
type Birthdate struct {
Day int `json:"day"`
Month int `json:"month"`
Year int `json:"year"`
}
// BusinessIntro
type BusinessIntro struct {
Sticker *Sticker `json:"sticker,omitempty"`
Title string `json:"title,omitempty"`
Message string `json:"message,omitempty"`
}
// BusinessLocation
type BusinessLocation struct {
Location *Location `json:"location,omitempty"`
Address string `json:"address"`
}
// BusinessOpeningHoursInterval
type BusinessOpeningHoursInterval struct {
OpeningMinute int `json:"opening_minute"`
ClosingMinute int `json:"closing_minute"`
}
// BusinessOpeningHours
type BusinessOpeningHours struct {
TimeZoneName string `json:"time_zone_name"`
OpeningHours []BusinessOpeningHoursInterval `json:"opening_hours"`
}
// ChatLocation represents a location to which a chat is connected.
type ChatLocation struct {
Location *Location `json:"location"`
@@ -1025,12 +1139,13 @@ func (i mediaEnvelope) MarshalJSON() (cnt []byte, err error) {
// InputMediaPhoto represents a photo to be sent.
// Type MUST BE "photo".
type InputMediaPhoto struct {
Type InputMediaType `json:"type"`
Media InputFile `json:"-"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
Type InputMediaType `json:"type"`
Media InputFile `json:"-"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// media is a method which allows to obtain the Media (type InputFile) field from the InputMedia* struct.
@@ -1045,17 +1160,18 @@ func (i InputMediaPhoto) groupable() {}
// InputMediaVideo represents a video to be sent.
// Type MUST BE "video".
type InputMediaVideo struct {
Type InputMediaType `json:"type"`
Media InputFile `json:"-"`
Thumbnail InputFile `json:"-"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
SupportsStreaming bool `json:"supports_streaming,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
Type InputMediaType `json:"type"`
Media InputFile `json:"-"`
Thumbnail InputFile `json:"-"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
SupportsStreaming bool `json:"supports_streaming,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// media is a method which allows to obtain the Media (type InputFile) field from the InputMedia* struct.
@@ -1070,16 +1186,17 @@ func (i InputMediaVideo) groupable() {}
// InputMediaAnimation represents an animation file (GIF or H.264/MPEG-4 AVC video without sound) to be sent.
// Type MUST BE "animation".
type InputMediaAnimation struct {
Type InputMediaType `json:"type"`
Media InputFile `json:"-"`
Thumbnail InputFile `json:"-"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
Type InputMediaType `json:"type"`
Media InputFile `json:"-"`
Thumbnail InputFile `json:"-"`
Caption string `json:"caption,omitempty"`
ParseMode ParseMode `json:"parse_mode,omitempty"`
CaptionEntities []*MessageEntity `json:"caption_entities,omitempty"`
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
Duration int `json:"duration,omitempty"`
HasSpoiler bool `json:"has_spoiler,omitempty"`
ShowCaptionAboveMedia bool `json:"show_caption_above_media,omitempty"`
}
// media is a method which allows to obtain the Media (type InputFile) field from the InputMedia* struct.
@@ -1172,8 +1289,8 @@ type BotName struct {
type ChatJoinRequest struct {
InviteLink *ChatInviteLink `json:"invite_link,omitempty"`
Bio string `json:"bio,omitempty"`
From User `json:"user"`
Chat Chat `json:"chat"`
From User `json:"user"`
Date int `json:"date"`
UserChatID int64 `json:"user_chat_id"`
}
@@ -1183,6 +1300,90 @@ type ChatBoostAdded struct {
BoostCount int `json:"boost_count"`
}
// BackgroundFill describes the way a background is filled based on the selected colors.
type BackgroundFill interface {
ImplementsBackgroundFill()
}
// BackgroundFillSolid is a background filled using the selected color.
// Type MUST be "solid".
type BackgroundFillSolid struct {
Type string `json:"type"`
Color int `json:"color"`
}
func (b BackgroundFillSolid) ImplementsBackgroundFill() {}
// BackgroundFillGradient is a background with a gradient fill.
// Type MUST be "gradient".
type BackgroundFillGradient struct {
Type string `json:"type"`
TopColor int `json:"top_color"`
BottomColor int `json:"bottom_color"`
RotationAngle int `json:"rotation_angle"`
}
func (b BackgroundFillGradient) ImplementsBackgroundFill() {}
// BackgroundFillFreeformGradient is a background with a freeform gradient that rotates after every message in the chat.
// Type MUST be "freeform_gradient".
type BackgroundFillFreeformGradient struct {
Type string `json:"type"`
Colors []int `json:"colors"`
}
func (b BackgroundFillFreeformGradient) ImplementsBackgroundFill() {}
// BackgroundType describes the type of a background.
type BackgroundType interface {
ImplementsBackgroundType()
}
// BackgroundTypeFill is a background which is automatically filled based on the selected colors.
// Type MUST be "fill".
type BackgroundTypeFill struct {
Fill BackgroundFill `json:"fill"`
Type string `json:"type"`
DarkThemeDimming int `json:"dark_theme_dimming"`
}
func (b BackgroundTypeFill) ImplementsBackgroundType() {}
// BackgroundTypeWallpaper is a background which is a wallpaper in the JPEG format.
// Type MUST be "wallpaper".
type BackgroundTypeWallpaper struct {
Type string `json:"type"`
Document Document `json:"document"`
DarkThemeDimming int `json:"dark_theme_dimming"`
IsBlurred bool `json:"is_blurred,omitempty"`
IsMoving bool `json:"is_moving,omitempty"`
}
func (b BackgroundTypeWallpaper) ImplementsBackgroundType() {}
// BackgroundTypePattern is a PNG or TGV (gzipped subset of SVG with MIME type “application/x-tgwallpattern”) pattern
// to be combined with the background fill chosen by the user.
// Type MUST be "pattern".
type BackgroundTypePattern struct {
Fill BackgroundFill `json:"fill"`
Type string `json:"type"`
Document Document `json:"document"`
Intensity int `json:"intensity"`
IsInverted bool `json:"is_inverted,omitempty"`
IsMoving bool `json:"is_moving,omitempty"`
}
func (b BackgroundTypePattern) ImplementsBackgroundType() {}
// BackgroundTypeChatTheme is taken directly from a built-in chat theme.
// Type MUST be "chat_theme".
type BackgroundTypeChatTheme struct {
Type string `json:"type"`
ThemeName string `json:"theme_name"`
}
func (b BackgroundTypeChatTheme) ImplementsBackgroundType() {}
// ForumTopicCreated represents a service message about a new forum topic created in the chat.
type ForumTopicCreated struct {
Name string `json:"name"`
@@ -1190,6 +1391,11 @@ type ForumTopicCreated struct {
IconColor int `json:"icon_color"`
}
// ChatBackground represents a chat background.
type ChatBackground struct {
Type BackgroundType `json:"type"`
}
// ForumTopicClosed represents a service message about a forum topic closed in the chat.
type ForumTopicClosed struct{}
@@ -1210,8 +1416,8 @@ type GeneralForumTopicUnhidden struct{}
// WriteAccessAllowed represents a service message about a user allowing a bot added to the attachment menu to write messages.
type WriteAccessAllowed struct {
FromRequest bool `json:"from_request,omitempty"`
WebAppName string `json:"web_app_name,omitempty"`
FromRequest bool `json:"from_request,omitempty"`
FromAttachmentMenu bool `json:"from_attachment_menu,omitempty"`
}
@@ -1244,8 +1450,11 @@ type UserShared struct {
// ChatShared contains information about the chat whose identifier was shared with the bot using a KeyboardButtonRequestChat button.
type ChatShared struct {
RequestID int `json:"request_id"`
ChatID int64 `json:"chat_id"`
Photo *[]PhotoSize `json:"photo,omitempty"`
Title string `json:"title,omitempty"`
Username string `json:"username,omitempty"`
RequestID int `json:"request_id"`
ChatID int64 `json:"chat_id"`
}
// Story represents a story.
@@ -1254,28 +1463,12 @@ type Story struct {
ID int64 `json:"id"`
}
type ReactionType interface {
ImplementsReactionType()
}
// ReactionTypeEmoji is based on an emoji.
// Type is always "emoji".
type ReactionTypeEmoji struct {
Type string `json:"type"`
Emoji string `json:"emoji"`
}
func (i ReactionTypeEmoji) ImplementsReactionType() {}
// ReactionTypeCustomEmoji is based on a custom emoji.
// Type is always "custom_emoji".
type ReactionTypeCustomEmoji struct {
type ReactionType struct {
Type string `json:"type"`
Emoji string `json:"emoji"`
CustomEmoji string `json:"custom_emoji"`
}
func (i ReactionTypeCustomEmoji) ImplementsReactionType() {}
// ReactionCount represents a reaction added to a message along with the number of times it was added.
type ReactionCount struct {
Type ReactionType `json:"type"`
@@ -1285,71 +1478,71 @@ type ReactionCount struct {
// MessageReactionUpdated represents a change of a reaction on a message performed by a user.
type MessageReactionUpdated struct {
Chat Chat `json:"chat"`
MessageID int `json:"message_id"`
User User `json:"user,omitempty"`
ActorChat Chat `json:"actor_chat,omitempty"`
Date int `json:"date"`
OldReaction []ReactionType `json:"old_reaction"`
NewReaction []ReactionType `json:"new_reaction"`
User User `json:"user,omitempty"`
MessageID int `json:"message_id"`
Date int `json:"date"`
}
// MessageReactionCountUpdated represents reaction changes on a message with anonymous reactions.
type MessageReactionCountUpdated struct {
Reactions []ReactionCount `json:"reactions"`
Chat Chat `json:"chat"`
MessageID int `json:"message_id"`
Date int `json:"date"`
Reactions []ReactionCount `json:"reactions"`
}
// TextQuote contains information about the quoted part of a message that is replied to by the given message.
type TextQuote struct {
Entities *[]MessageEntity `json:"entities,omitempty"`
Text string `json:"text"`
Position int `json:"position"`
IsManual bool `json:"is_manual,omitempty"`
Text string `json:"text"`
Entities *[]MessageEntity `json:"entities,omitempty"`
}
// ExternalReplyInfo contains information about a message that is being replied to, which may come from another chat or forum topic.
type ExternalReplyInfo struct {
Origin MessageOrigin `json:"origin"`
Chat Chat `json:"chat,omitempty"`
MessageID int `json:"message_id,omitempty"`
LinkPreviewOptions LinkPreviewOptions `json:"link_preview_options,omitempty"`
Animation Animation `json:"animation,omitempty"`
Audio Audio `json:"audio,omitempty"`
Document Document `json:"document,omitempty"`
Photo []PhotoSize `json:"photo,omitempty"`
Sticker Sticker `json:"sticker,omitempty"`
Story Story `json:"story,omitempty"`
Video Video `json:"video,omitempty"`
VideoNote VideoNote `json:"video_note,omitempty"`
Voice Voice `json:"voice,omitempty"`
HasMediaSpoiler bool `json:"has_media_spoiler,omitempty"`
Contact Contact `json:"contact,omitempty"`
Dice Dice `json:"dice,omitempty"`
Game Game `json:"game,omitempty"`
Giveaway Giveaway `json:"giveaway,omitempty"`
GiveawayWinners GiveawayWinners `json:"giveaway_winners,omitempty"`
Invoice Invoice `json:"invoice,omitempty"`
Location Location `json:"location,omitempty"`
Poll Poll `json:"poll,omitempty"`
Venue Venue `json:"venue,omitempty"`
Chat Chat `json:"chat,omitempty"`
Document Document `json:"document,omitempty"`
Origin MessageOrigin `json:"origin"`
Contact Contact `json:"contact,omitempty"`
Invoice Invoice `json:"invoice,omitempty"`
Dice Dice `json:"dice,omitempty"`
LinkPreviewOptions LinkPreviewOptions `json:"link_preview_options,omitempty"`
Photo []PhotoSize `json:"photo,omitempty"`
Audio Audio `json:"audio,omitempty"`
Story Story `json:"story,omitempty"`
Voice Voice `json:"voice,omitempty"`
VideoNote VideoNote `json:"video_note,omitempty"`
Game Game `json:"game,omitempty"`
Video Video `json:"video,omitempty"`
Animation Animation `json:"animation,omitempty"`
Sticker Sticker `json:"sticker,omitempty"`
Giveaway Giveaway `json:"giveaway,omitempty"`
Poll Poll `json:"poll,omitempty"`
GiveawayWinners GiveawayWinners `json:"giveaway_winners,omitempty"`
Location Location `json:"location,omitempty"`
MessageID int `json:"message_id,omitempty"`
HasMediaSpoiler bool `json:"has_media_spoiler,omitempty"`
}
// MessageOrigin describes the origin of a message.
type MessageOrigin struct {
Date int `json:"date"`
SenderChat *Chat `json:"sender_chat,omitempty"`
SenderUser *User `json:"sender_user,omitempty"`
Type string `json:"type"`
SenderUserName string `json:"sender_user_name,omitempty"` // Only for MessageOriginHiddenUser
AuthorSignature string `json:"author_signature,omitempty"` // Only for MessageOriginChannel
SenderChat *Chat `json:"sender_chat,omitempty"` // Only for MessageOriginChat
SenderUser *User `json:"sender_user,omitempty"` // Only for MessageOriginUser
SenderUserName string `json:"sender_user_name,omitempty"`
AuthorSignature string `json:"author_signature,omitempty"`
Date int `json:"date"`
}
// LinkPreviewOptions describes the options used for link preview generation.
type LinkPreviewOptions struct {
IsDisabled bool `json:"is_disabled,omitempty"`
URL string `json:"url,omitempty"`
IsDisabled bool `json:"is_disabled,omitempty"`
PreferSmallMedia bool `json:"prefer_small_media,omitempty"`
PreferLargeMedia bool `json:"prefer_large_media,omitempty"`
ShowAboveText bool `json:"show_above_text,omitempty"`
@@ -1357,27 +1550,36 @@ type LinkPreviewOptions struct {
// ReplyParameters describes reply parameters for the message that is being sent.
type ReplyParameters struct {
MessageID int `json:"message_id"`
ChatID int64 `json:"chat_id,omitempty"`
AllowSendingWithoutReply bool `json:"allow_sending_without_reply,omitempty"`
Quote string `json:"quote,omitempty"`
QuoteParseMode string `json:"quote_parse_mode,omitempty"`
QuoteEntities []MessageEntity `json:"quote_entitites,omitempty"`
MessageID int `json:"message_id"`
ChatID int64 `json:"chat_id,omitempty"`
QuotePosition int `json:"quote_position,omitempty"`
AllowSendingWithoutReply bool `json:"allow_sending_without_reply,omitempty"`
}
// SharedUser contains information about a user that was shared with the bot using a KeyboardButtonRequestUser button.
type SharedUser struct {
Photo *[]PhotoSize `json:"photo,omitempty"`
FirstName string `json:"firstname,omitempty"`
LastName string `json:"lastname,omitempty"`
Username string `json:"username,omitempty"`
UserID int64 `json:"user_id"`
}
// UsersShared contains information about the users whose identifiers were shared with the bot using a KeyboardButtonRequestUsers button.
type UsersShared struct {
RequestID int `json:"request_id"`
UserIDs []int64 `json:"user_ids"`
Users []SharedUser `json:"users"`
RequestID int `json:"request_id"`
}
// ChatBoost contains information about a chat boost.
type ChatBoost struct {
BoostID string `json:"boost_id"`
Source ChatBoostSource `json:"source"`
AddDate int `json:"add_date"`
ExpirationDate int `json:"expiration_date"`
Source ChatBoostSource `json:"source"`
}
// ChatBoostSourceType is a custom type for the various chat boost sources.
@@ -1392,8 +1594,8 @@ const (
// ChatBoostSource describes the source of a chat boost.
type ChatBoostSource struct {
Source ChatBoostSourceType `json:"source"`
User *User `json:"user,omitempty"`
Source ChatBoostSourceType `json:"source"`
GiveawayMessageID int `json:"giveaway_message_id,omitempty"`
IsUnclaimed bool `json:"is_unclaimed,omitempty"`
}
@@ -1406,10 +1608,10 @@ type ChatBoostUpdated struct {
// ChatBoostRemoved represents a boost removed from a chat.
type ChatBoostRemoved struct {
Chat Chat `json:"chat"`
BoostID string `json:"boost_id"`
RemoveDate int `json:"remove_date"`
Chat Chat `json:"chat"`
Source ChatBoostSource `json:"source"`
RemoveDate int `json:"remove_date"`
}
// UserChatBoosts represents a list of boosts added to a chat by a user.
@@ -1417,39 +1619,57 @@ type UserChatBoosts struct {
Boosts []ChatBoost `json:"boosts"`
}
// BusinessConnection describes the connection of the bot with a business account.
type BusinessConnection struct {
ID string `json:"id"`
User User `json:"user"`
UserChatID int64 `json:"user_chat_id"`
Date int64 `json:"date"`
CanReply bool `json:"can_reply"`
IsEnabled bool `json:"is_enabled"`
}
// BusinessMessagesDeleted is received when messages are deleted from a connected business account.
type BusinessMessagesDeleted struct {
BusinessConnectionID string `json:"business_connection_id"`
MessageIDs []int `json:"message_ids"`
Chat Chat `json:"chat"`
}
// Giveaway represents a message about a scheduled giveaway.
type Giveaway struct {
CountryCodes *[]string `json:"country_codes,omitempty"`
PrizeDescription string `json:"prize_description,omitempty"`
Chats []Chat `json:"chats"`
WinnersSelectionDate int `json:"winners_selection_date"`
WinnerCount int `json:"winner_count"`
PremiumSubscriptionMonthCount int `json:"premium_subscription_month_count,omitempty"`
OnlyNewMembers bool `json:"only_new_members,omitempty"`
HasPublicWinners bool `json:"has_public_winners,omitempty"`
PrizeDescription string `json:"prize_description,omitempty"`
CountryCodes *[]string `json:"country_codes,omitempty"`
PremiumSubscriptionMonthCount int `json:"premium_subscription_month_count,omitempty"`
}
// GiveawayCreated represents a service message about the creation of a scheduled giveaway. Currently holds no information.
// GiveawayCreated represents a service message about the creation of a scheduled giveaway.
// Currently holds no information.
type GiveawayCreated struct{}
// GiveawayWinners represents a message about the completion of a giveaway with public winners.
type GiveawayWinners struct {
PrizeDescription string `json:"prize_description,omitempty"`
Chats []Chat `json:"chats"`
Winners []User `json:"winners"`
GiveawayMessageID int `json:"giveaway_message_id"`
WinnersSelectionDate int `json:"winners_selection_date"`
WinnerCount int `json:"winner_count"`
Winners []User `json:"winners"`
AdditionalChatCount int `json:"additional_chat_count,omitempty"`
PremiumSubscriptionMonthCount int `json:"premium_subscription_month_count,omitempty"`
UnclaimedPrizeCount int `json:"unclaimed_prize_count,omitempty"`
OnlyNewMembers bool `json:"only_new_members,omitempty"`
WasRefunded bool `json:"was_refunded,omitempty"`
PrizeDescription string `json:"prize_description,omitempty"`
}
// GiveawayCompleted represents a service message about the completion of a giveaway without public winners.
type GiveawayCompleted struct {
GiveawayMessage *Message `json:"giveaway_message,omitempty"`
WinnerCount int `json:"winner_count"`
UnclaimedPrizeCount int `json:"unclaimed_prize_count,omitempty"`
GiveawayMessage *Message `json:"giveaway_message,omitempty"`
}

View File

@@ -53,5 +53,5 @@ func (a API) AnswerWebAppQuery(webAppQueryID string, result InlineQueryResult) (
vals.Set("web_app_query_id", webAppQueryID)
vals.Set("result", string(resultJson))
return get[APIResponseSentWebAppMessage](a.base, "answerWebAppQuery", vals)
return res, a.client.get(a.base, "answerWebAppQuery", vals, &res)
}