🔀 Merge branch 'develop'
This commit is contained in:
commit
9fbfbd4c9a
|
@ -1,6 +0,0 @@
|
|||
# [Patrons!](https://www.patreon.com/bePatron?c=243288)
|
||||
**These people have sponsored the current version of the project:**
|
||||
- Daniil Tlenov
|
||||
- Aurielb
|
||||
- Yami Odymel
|
||||
- MoD21k
|
|
@ -10,10 +10,6 @@ type AnswerCallbackQueryParameters struct {
|
|||
// user, 0-200 characters
|
||||
Text string `json:"text,omitempty"`
|
||||
|
||||
// If true, an alert will be shown by the client instead of a notification at
|
||||
// the top of the chat screen. Defaults to false.
|
||||
ShowAlert bool `json:"show_alert,omitempty"`
|
||||
|
||||
// URL that will be opened by the user's client. If you have created a Game
|
||||
// and accepted the conditions via @Botfather, specify the URL that opens
|
||||
// your game – note that this will only work if the query comes from a
|
||||
|
@ -23,6 +19,10 @@ type AnswerCallbackQueryParameters struct {
|
|||
// bot with a parameter.
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// If true, an alert will be shown by the client instead of a notification at
|
||||
// the top of the chat screen. Defaults to false.
|
||||
ShowAlert bool `json:"show_alert,omitempty"`
|
||||
|
||||
// The maximum amount of time in seconds that the result of the callback
|
||||
// query may be cached client-side. Telegram apps will support caching
|
||||
// starting in version 3.14. Defaults to 0.
|
||||
|
@ -47,7 +47,7 @@ func (bot *Bot) AnswerCallbackQuery(params *AnswerCallbackQueryParameters) (bool
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "answerCallbackQuery")
|
||||
resp, err := bot.request(dst, MethodAnswerCallbackQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -6,18 +6,6 @@ type AnswerInlineQueryParameters struct {
|
|||
// Unique identifier for the answered query
|
||||
InlineQueryID string `json:"inline_query_id"`
|
||||
|
||||
// A JSON-serialized array of results for the inline query
|
||||
Results []interface{} `json:"results"`
|
||||
|
||||
// The maximum amount of time in seconds that the result of the inline query
|
||||
// may be cached on the server. Defaults to 300.
|
||||
CacheTime int `json:"cache_time,omitempty"`
|
||||
|
||||
// Pass True, if results may be cached on the server side only for the user
|
||||
// that sent the query. By default, results may be returned to any user who
|
||||
// sends the same query
|
||||
IsPersonal bool `json:"is_personal,omitempty"`
|
||||
|
||||
// Pass the offset that a client should send in the next query with the same
|
||||
// text to receive more results. Pass an empty string if there are no more
|
||||
// results or if you don‘t support pagination. Offset length can’t exceed 64
|
||||
|
@ -33,6 +21,18 @@ type AnswerInlineQueryParameters struct {
|
|||
// presses the switch button. 1-64 characters, only A-Z, a-z, 0-9, _ and -
|
||||
// are allowed.
|
||||
SwitchPrivateMessageParameter string `json:"switch_pm_parameter,omitempty"`
|
||||
|
||||
// A JSON-serialized array of results for the inline query
|
||||
Results []interface{} `json:"results"`
|
||||
|
||||
// The maximum amount of time in seconds that the result of the inline query
|
||||
// may be cached on the server. Defaults to 300.
|
||||
CacheTime int `json:"cache_time,omitempty"`
|
||||
|
||||
// Pass True, if results may be cached on the server side only for the user
|
||||
// that sent the query. By default, results may be returned to any user who
|
||||
// sends the same query
|
||||
IsPersonal bool `json:"is_personal,omitempty"`
|
||||
}
|
||||
|
||||
func NewAnswerInlineQuery(inlineQueryID string, results ...interface{}) *AnswerInlineQueryParameters {
|
||||
|
@ -51,7 +51,7 @@ func (bot *Bot) AnswerInlineQuery(params *AnswerInlineQueryParameters) (bool, er
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "answerInlineQuery")
|
||||
resp, err := bot.request(dst, MethodAnswerInlineQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -6,17 +6,17 @@ type AnswerPreCheckoutQueryParameters struct {
|
|||
// Unique identifier for the query to be answered
|
||||
PreCheckoutQueryID string `json:"pre_checkout_query_id"`
|
||||
|
||||
// Specify True if everything is alright (goods are available, etc.) and the
|
||||
// bot is ready to proceed with the order. Use False if there are any
|
||||
// problems.
|
||||
Ok bool `json:"ok"`
|
||||
|
||||
// Required if ok is False. Error message in human readable form that
|
||||
// explains the reason for failure to proceed with the checkout (e.g. "Sorry,
|
||||
// somebody just bought the last of our amazing black T-shirts while you were
|
||||
// busy filling out your payment details. Please choose a different color or
|
||||
// garment!"). Telegram will display this message to the user.
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
|
||||
// Specify True if everything is alright (goods are available, etc.) and the
|
||||
// bot is ready to proceed with the order. Use False if there are any
|
||||
// problems.
|
||||
Ok bool `json:"ok"`
|
||||
}
|
||||
|
||||
func NewAnswerPreCheckoutQuery(preCheckoutQueryID string, ok bool) *AnswerPreCheckoutQueryParameters {
|
||||
|
@ -41,7 +41,7 @@ func (bot *Bot) AnswerPreCheckoutQuery(params *AnswerShippingQueryParameters) (b
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "answerPreCheckoutQuery")
|
||||
resp, err := bot.request(dst, MethodAnswerPreCheckoutQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -6,6 +6,12 @@ type AnswerShippingQueryParameters struct {
|
|||
// Unique identifier for the query to be answered
|
||||
ShippingQueryID string `json:"shipping_query_id"`
|
||||
|
||||
// Required if ok is False. Error message in human readable form that
|
||||
// explains why it is impossible to complete the order (e.g. "Sorry, delivery
|
||||
// to your desired address is unavailable'). Telegram will display this
|
||||
// message to the user.
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
|
||||
// Specify True if delivery to the specified address is possible and False
|
||||
// if there are any problems (for example, if delivery to the specified
|
||||
// address is not possible)
|
||||
|
@ -14,12 +20,6 @@ type AnswerShippingQueryParameters struct {
|
|||
// Required if ok is True. A JSON-serialized array of available shipping
|
||||
// options.
|
||||
ShippingOptions []ShippingOption `json:"shipping_options,omitempty"`
|
||||
|
||||
// Required if ok is False. Error message in human readable form that
|
||||
// explains why it is impossible to complete the order (e.g. "Sorry, delivery
|
||||
// to your desired address is unavailable'). Telegram will display this
|
||||
// message to the user.
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
}
|
||||
|
||||
func NewAnswerShippingQuery(shippingQueryID string, ok bool) *AnswerShippingQueryParameters {
|
||||
|
@ -40,7 +40,7 @@ func (bot *Bot) AnswerShippingQuery(params *AnswerShippingQueryParameters) (bool
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "answerShippingQuery")
|
||||
resp, err := bot.request(dst, MethodAnswerShippingQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,151 @@
|
|||
package telegram
|
||||
|
||||
const (
|
||||
ActionFindLocation = "find_location"
|
||||
ActionRecordAudio = "record_audio"
|
||||
ActionRecordVideo = "record_video"
|
||||
ActionRecordVideoNote = "record_video_note"
|
||||
ActionTyping = "typing"
|
||||
ActionUploadAudio = "upload_audio"
|
||||
ActionUploadDocument = "upload_document"
|
||||
ActionUploadPhoto = "upload_photo"
|
||||
ActionUploadVideo = "upload_video"
|
||||
ActionUploadVideoNote = "upload_video_note"
|
||||
)
|
||||
|
||||
const (
|
||||
ChatChannel = "channel"
|
||||
ChatGroup = "group"
|
||||
ChatPrivate = "private"
|
||||
ChatSuperGroup = "supergroup"
|
||||
)
|
||||
|
||||
const (
|
||||
EntityBold = "bold"
|
||||
EntityBotCommand = "bot_command"
|
||||
EntityCode = "code"
|
||||
EntityEmail = "email"
|
||||
EntityHashtag = "hashtag"
|
||||
EntityItalic = "italic"
|
||||
EntityMention = "mention"
|
||||
EntityPre = "pre"
|
||||
EntityTextLink = "text_link"
|
||||
EntityTextMention = "text_mention"
|
||||
EntityURL = "url"
|
||||
)
|
||||
|
||||
const (
|
||||
MethodAddStickerToSet = "addStickerToSet"
|
||||
MethodAnswerCallbackQuery = "answerCallbackQuery"
|
||||
MethodAnswerInlineQuery = "answerInlineQuery"
|
||||
MethodAnswerPreCheckoutQuery = "answerPreCheckoutQuery"
|
||||
MethodAnswerShippingQuery = "answerShippingQuery"
|
||||
MethodCreateNewStickerSet = "createNewStickerSet"
|
||||
MethodDeleteChatPhoto = "deleteChatPhoto"
|
||||
MethodDeleteChatStickerSet = "deleteChatStickerSet"
|
||||
MethodDeleteMessage = "deleteMessage"
|
||||
MethodDeleteStickerFromSet = "deleteStickerFromSet"
|
||||
MethodDeleteWebhook = "deleteWebhook"
|
||||
MethodEditMessageCaption = "editMessageCaption"
|
||||
MethodEditMessageLiveLocation = "editMessageLiveLocation"
|
||||
MethodEditMessageReplyMarkup = "editMessageReplyMarkup"
|
||||
MethodEditMessageText = "editMessageText"
|
||||
MethodExportChatInviteLink = "exportChatInviteLink"
|
||||
MethodForwardMessage = "forwardMessage"
|
||||
MethodGetChat = "getChat"
|
||||
MethodGetChatAdministrators = "getChatAdministrators"
|
||||
MethodGetChatMember = "getChatMember"
|
||||
MethodGetChatMembersCount = "getChatMembersCount"
|
||||
MethodGetFile = "getFile"
|
||||
MethodGetGameHighScores = "getGameHighScores"
|
||||
MethodGetMe = "getMe"
|
||||
MethodGetStickerSet = "getStickerSet"
|
||||
MethodGetUpdates = "getUpdates"
|
||||
MethodGetUserProfilePhotos = "getUserProfilePhotos"
|
||||
MethodGetWebhookInfo = "getWebhookInfo"
|
||||
MethodKickChatMember = "kickChatMember"
|
||||
MethodLeaveChat = "leaveChat"
|
||||
MethodPinChatMessage = "pinChatMessage"
|
||||
MethodPromoteChatMember = "promoteChatMember"
|
||||
MethodRestrictChatMember = "restrictChatMember"
|
||||
MethodSendAudio = "sendAudio"
|
||||
MethodSendChatAction = "sendChatAction"
|
||||
MethodSendContact = "sendContact"
|
||||
MethodSendDocument = "sendDocument"
|
||||
MethodSendGame = "sendGame"
|
||||
MethodSendInvoice = "sendInvoice"
|
||||
MethodSendLocation = "sendLocation"
|
||||
MethodSendMediaGroup = "sendMediaGroup"
|
||||
MethodSendMessage = "sendMessage"
|
||||
MethodSendPhoto = "sendPhoto"
|
||||
MethodSendSticker = "sendSticker"
|
||||
MethodSendVenue = "sendVenue"
|
||||
MethodSendVideo = "sendVideo"
|
||||
MethodSendVideoNote = "sendVideoNote"
|
||||
MethodSendVoice = "sendVoice"
|
||||
MethodSetChatDescription = "setChatDescription"
|
||||
MethodSetChatPhoto = "setChatPhoto"
|
||||
MethodSetChatStickerSet = "setChatStickerSet"
|
||||
MethodSetChatTitle = "setChatTitle"
|
||||
MethodSetGameScore = "setGameScore"
|
||||
MethodSetStickerPositionInSet = "setStickerPositionInSet"
|
||||
MethodSetWebhook = "setWebhook"
|
||||
MethodStopMessageLiveLocation = "stopMessageLiveLocation"
|
||||
MethodUnbanChatMember = "unbanChatMember"
|
||||
MethodUnpinChatMessage = "unpinChatMessage"
|
||||
MethodUploadStickerFile = "uploadStickerFile"
|
||||
)
|
||||
|
||||
const (
|
||||
ModeHTML = "html"
|
||||
ModeMarkdown = "markdown"
|
||||
)
|
||||
|
||||
const (
|
||||
MimeHTML = "text/html"
|
||||
MimeMP4 = "video/mp4"
|
||||
MimePDF = "application/pdf"
|
||||
MimeZIP = "application/zip"
|
||||
)
|
||||
|
||||
const (
|
||||
SchemeAttach = "attach"
|
||||
SchemeTelegram = "tg"
|
||||
)
|
||||
|
||||
const (
|
||||
StatusAdministrator = "administrator"
|
||||
StatusCreator = "creator"
|
||||
StatusKicked = "kicked"
|
||||
StatusLeft = "left"
|
||||
StatusMember = "member"
|
||||
StatusRestricted = "restricted"
|
||||
)
|
||||
|
||||
const (
|
||||
TypeArticle = "article"
|
||||
TypeAudio = "audio"
|
||||
TypeContact = "contact"
|
||||
TypeDocument = "document"
|
||||
TypeGame = "game"
|
||||
TypeGIF = "gif"
|
||||
TypeLocation = "location"
|
||||
TypeMpeg4Gif = "mpeg4_gif"
|
||||
TypePhoto = "photo"
|
||||
TypeSticker = "sticker"
|
||||
TypeVenue = "venue"
|
||||
TypeVideo = "video"
|
||||
TypeVoice = "voice"
|
||||
)
|
||||
|
||||
const (
|
||||
UpdateCallbackQuery = "callback_query"
|
||||
UpdateChannelPost = "channel_post"
|
||||
UpdateChosenInlineResult = "chosen_inline_result"
|
||||
UpdateEditedChannelPost = "edited_channel_post"
|
||||
UpdateEditedMessage = "edited_message"
|
||||
UpdateInlineQuery = "inline_query"
|
||||
UpdateMessage = "message"
|
||||
UpdatePreCheckoutQuery = "pre_checkout_query"
|
||||
UpdateShippingQuery = "shipping_query"
|
||||
)
|
|
@ -19,7 +19,7 @@ func (bot *Bot) DeleteChatPhoto(chatID int64) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "deleteChatPhoto")
|
||||
resp, err := bot.request(dst, MethodDeleteChatPhoto)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func (bot *Bot) DeleteChatStickerSet(chatID int64) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "deleteChatStickerSet")
|
||||
resp, err := bot.request(dst, MethodDeleteChatStickerSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ func (bot *Bot) DeleteMessage(chatID int64, messageID int) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "deleteMessage")
|
||||
resp, err := bot.request(dst, MethodDeleteMessage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func (bot *Bot) DeleteStickerFromSet(sticker string) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "deleteStickerFromSet")
|
||||
resp, err := bot.request(dst, MethodDeleteStickerFromSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import json "github.com/pquerna/ffjson/ffjson"
|
|||
// DeleteWebhook remove webhook integration if you decide to switch back to
|
||||
// getUpdates. Returns True on success. Requires no parameters.
|
||||
func (bot *Bot) DeleteWebhook() (bool, error) {
|
||||
resp, err := bot.request(nil, "deleteWebhook")
|
||||
resp, err := bot.request(nil, MethodDeleteWebhook)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
## Our Pledge
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project owner at git@toby3d.ru. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
|
@ -0,0 +1,9 @@
|
|||
# [Support me on Patreon!](https://www.patreon.com/bePatron?c=243288)
|
||||
I develop this project in my spare time, and I do it and I will do it free of charge. However, you can make a donation or become a sponsor to make sure that I have enough coffee and pizza for night coding.
|
||||
|
||||
**These people sponsored current version of the project:**
|
||||
- Aurielb
|
||||
- Daniil Tlenov
|
||||
- @kirillDanshin
|
||||
- MoD21k
|
||||
- @YamiOdymel
|
|
@ -36,7 +36,7 @@ func (bot *Bot) EditMessageCaption(params *EditMessageCaptionParameters) (*Messa
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "editMessageCaption")
|
||||
resp, err := bot.request(dst, MethodEditMessageCaption)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func (bot *Bot) EditMessageLiveLocation(params *EditMessageLiveLocationParameter
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "editMessageLiveLocation")
|
||||
resp, err := bot.request(dst, MethodEditMessageLiveLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ func (bot *Bot) EditMessageReplyMarkup(params *EditMessageReplyMarkupParameters)
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "editMessageReplyMarkup")
|
||||
resp, err := bot.request(dst, MethodEditMessageReplyMarkup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ func (bot *Bot) EditMessageText(params *EditMessageTextParameters) (*Message, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "editMessageText")
|
||||
resp, err := bot.request(dst, MethodEditMessageText)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func (bot *Bot) ExportChatInviteLink(chatID int64) (string, error) {
|
|||
return "", err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "exportChatInviteLink")
|
||||
resp, err := bot.request(dst, MethodExportChatInviteLink)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func (bot *Bot) ForwardMessage(params *ForwardMessageParameters) (*Message, erro
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "forwardMessage")
|
||||
resp, err := bot.request(dst, MethodForwardMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func (bot *Bot) GetChat(chatID int64) (*Chat, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getChat")
|
||||
resp, err := bot.request(dst, MethodGetChat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ func (bot *Bot) GetChatAdministrators(chatID int64) ([]ChatMember, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getChatAdministrators")
|
||||
resp, err := bot.request(dst, MethodGetChatAdministrators)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ func (bot *Bot) GetChatMember(chatID int64, userID int) (*ChatMember, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getChatMember")
|
||||
resp, err := bot.request(dst, MethodGetChatMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func (bot *Bot) GetChatMembersCount(chatID int64) (int, error) {
|
|||
return 0, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getChatMembersCount")
|
||||
resp, err := bot.request(dst, MethodGetChatMembersCount)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ func (bot *Bot) GetFile(fileID string) (*File, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getFile")
|
||||
resp, err := bot.request(dst, MethodGetFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -6,14 +6,14 @@ type GetGameHighScoresParameters struct {
|
|||
// Target user id
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Required if inline_message_id is not specified. Unique identifier for the
|
||||
// target chat
|
||||
ChatID int64 `json:"chat_id,omitempty"`
|
||||
|
||||
// Required if inline_message_id is not specified. Identifier of the sent
|
||||
// message
|
||||
MessageID int `json:"message_id,omitempty"`
|
||||
|
||||
// Required if inline_message_id is not specified. Unique identifier for the
|
||||
// target chat
|
||||
ChatID int64 `json:"chat_id,omitempty"`
|
||||
|
||||
// Required if chat_id and message_id are not specified. Identifier of the
|
||||
// inline message
|
||||
InlineMessageID string `json:"inline_message_id,omitempty"`
|
||||
|
@ -34,7 +34,7 @@ func (bot *Bot) GetGameHighScores(params *GetGameHighScoresParameters) ([]GameHi
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getGameHighScores")
|
||||
resp, err := bot.request(dst, MethodGetGameHighScores)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import json "github.com/pquerna/ffjson/ffjson"
|
|||
// GetMe testing your bot's auth token. Requires no parameters. Returns basic
|
||||
// information about the bot in form of a User object.
|
||||
func (bot *Bot) GetMe() (*User, error) {
|
||||
resp, err := bot.request(nil, "getMe")
|
||||
resp, err := bot.request(nil, MethodGetMe)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ func (bot *Bot) GetStickerSet(name string) (*StickerSet, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getStickerSet")
|
||||
resp, err := bot.request(dst, MethodGetStickerSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ func (bot *Bot) GetUpdates(params *GetUpdatesParameters) ([]Update, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getUpdates")
|
||||
resp, err := bot.request(dst, MethodGetUpdates)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ func (bot *Bot) GetUserProfilePhotos(params *GetUserProfilePhotosParameters) (*U
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "getUserProfilePhotos")
|
||||
resp, err := bot.request(dst, MethodGetUserProfilePhotos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import json "github.com/pquerna/ffjson/ffjson"
|
|||
// returns a WebhookInfo object. If the bot is using getUpdates, will return an
|
||||
// object with the url field empty.
|
||||
func (bot *Bot) GetWebhookInfo() (*WebhookInfo, error) {
|
||||
resp, err := bot.request(nil, "getWebhookInfo")
|
||||
resp, err := bot.request(nil, MethodGetWebhookInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
26
helpers.go
26
helpers.go
|
@ -1,26 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NewForceReply(selective bool) *ForceReply {
|
||||
return &ForceReply{
|
||||
ForceReply: true,
|
||||
Selective: selective,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInlineMentionURL(id int) *url.URL {
|
||||
link := &url.URL{
|
||||
Scheme: "tg",
|
||||
Path: "user",
|
||||
}
|
||||
|
||||
q := link.Query()
|
||||
q.Add("id", strconv.Itoa(id))
|
||||
link.RawQuery = q.Encode()
|
||||
|
||||
return link
|
||||
}
|
|
@ -6,8 +6,8 @@ type KickChatMemberParameters struct {
|
|||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
UserID int `json:"user_id"`
|
||||
UntilDate int64 `json:"until_date"`
|
||||
UserID int `json:"user_id"`
|
||||
}
|
||||
|
||||
// KickChatMember kick a user from a group, a supergroup or a channel. In the case of supergroups and
|
||||
|
@ -24,7 +24,7 @@ func (bot *Bot) KickChatMember(params *KickChatMemberParameters) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "kickChatMember")
|
||||
resp, err := bot.request(dst, MethodKickChatMember)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ func (bot *Bot) LeaveChat(chatID int64) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "leaveChat")
|
||||
resp, err := bot.request(dst, MethodLeaveChat)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -4,34 +4,40 @@ import (
|
|||
"crypto/hmac"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"errors"
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var ErrUserNotDefined = errors.New("user is not defined")
|
||||
|
||||
// CheckAuthorization verify the authentication and the integrity of the data
|
||||
// received by comparing the received hash parameter with the hexadecimal
|
||||
// representation of the HMAC-SHA-256 signature of the data-check-string with the
|
||||
// SHA256 hash of the bot's token used as a secret key.
|
||||
func (user *User) CheckAuthorization(botToken string) (bool, error) {
|
||||
dataCheckString := fmt.Sprint(
|
||||
"auth_date=", user.AuthDate.Unix(),
|
||||
"\n", "first_name=", user.FirstName,
|
||||
// Eliminate 'hash' to avoid recursion and incorrect data validation.
|
||||
"\n", "id=", user.ID,
|
||||
)
|
||||
func (app *App) CheckAuthorization(user *User) (bool, error) {
|
||||
if user == nil {
|
||||
return false, ErrUserNotDefined
|
||||
}
|
||||
|
||||
dataCheck := make(url.Values)
|
||||
dataCheck.Add(KeyAuthDate, string(user.AuthDate))
|
||||
dataCheck.Add(KeyFirstName, user.FirstName)
|
||||
dataCheck.Add(KeyID, strconv.Itoa(user.ID))
|
||||
|
||||
// Add optional values if exist
|
||||
if user.LastName != "" {
|
||||
dataCheckString += fmt.Sprint("\n", "last_name=", user.LastName)
|
||||
dataCheck.Add(KeyLastName, user.LastName)
|
||||
}
|
||||
if user.PhotoURL != "" {
|
||||
dataCheckString += fmt.Sprint("\n", "photo_url=", user.PhotoURL)
|
||||
dataCheck.Add(KeyPhotoURL, user.PhotoURL)
|
||||
}
|
||||
if user.Username != "" {
|
||||
dataCheckString += fmt.Sprint("\n", "username=", user.Username)
|
||||
dataCheck.Add(KeyUsername, user.Username)
|
||||
}
|
||||
|
||||
secretKey := sha256.Sum256([]byte(botToken))
|
||||
secretKey := sha256.Sum256([]byte(app.SecretKey))
|
||||
hash := hmac.New(sha256.New, secretKey[0:])
|
||||
_, err := hash.Write([]byte(dataCheckString))
|
||||
_, err := hash.Write([]byte(dataCheck.Encode()))
|
||||
return hex.EncodeToString(hash.Sum(nil)) == user.Hash, err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
package login
|
||||
|
||||
const (
|
||||
KeyAuthDate = "auth_date"
|
||||
KeyFirstName = "first_name"
|
||||
KeyHash = "hash"
|
||||
KeyID = "id"
|
||||
KeyLastName = "last_name"
|
||||
KeyPhotoURL = "photo_url"
|
||||
KeyUsername = "username"
|
||||
)
|
42
login/new.go
42
login/new.go
|
@ -1,41 +1,11 @@
|
|||
package login
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// User contains data about authenticated user.
|
||||
type User struct {
|
||||
AuthDate time.Time `json:"auth_date"`
|
||||
FirstName string `json:"first_name"`
|
||||
Hash string `json:"hash"`
|
||||
ID int `json:"id"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
PhotoURL string `json:"photo_url,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
// App represents a widget which get and validate users authorizations.
|
||||
type App struct {
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
// New create User structure from input url.Values.
|
||||
func New(src url.Values) (*User, error) {
|
||||
authDate, err := strconv.Atoi(src.Get("auth_date"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(src.Get("id"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &User{
|
||||
AuthDate: time.Unix(int64(authDate), 0),
|
||||
FirstName: src.Get("first_name"),
|
||||
Hash: src.Get("hash"),
|
||||
ID: id,
|
||||
LastName: src.Get("last_name"),
|
||||
PhotoURL: src.Get("photo_url"),
|
||||
Username: src.Get("username"),
|
||||
}, nil
|
||||
// New create new app widget for validate authorizations with bot token as secret key.
|
||||
func New(botToken string) *App {
|
||||
return &App{SecretKey: botToken}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package login
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// User contains data about authenticated user.
|
||||
type User struct {
|
||||
AuthDate int64 `json:"auth_date"`
|
||||
FirstName string `json:"first_name"`
|
||||
Hash string `json:"hash"`
|
||||
ID int `json:"id"`
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
PhotoURL string `json:"photo_url,omitempty"`
|
||||
Username string `json:"username,omitempty"`
|
||||
}
|
||||
|
||||
// ParseUser create User structure from input url.Values.
|
||||
func ParseUser(src url.Values) (*User, error) {
|
||||
authDate, err := strconv.Atoi(src.Get(KeyAuthDate))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
id, err := strconv.Atoi(src.Get(KeyID))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &User{
|
||||
AuthDate: int64(authDate),
|
||||
FirstName: src.Get(KeyFirstName),
|
||||
Hash: src.Get(KeyHash),
|
||||
ID: id,
|
||||
LastName: src.Get(KeyLastName),
|
||||
PhotoURL: src.Get(KeyPhotoURL),
|
||||
Username: src.Get(KeyUsername),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package login
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FullName return user first name only or full name if last name is present.
|
||||
func (user *User) FullName() string {
|
||||
if user == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if user.LastName != "" {
|
||||
return fmt.Sprintln(user.FirstName, user.LastName)
|
||||
}
|
||||
|
||||
return user.FirstName
|
||||
}
|
||||
|
||||
// AuthTime convert AuthDate field into time.Time.
|
||||
func (user *User) AuthTime() time.Time {
|
||||
if user == nil {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
return time.Unix(user.AuthDate, 0)
|
||||
}
|
503
models.go
503
models.go
|
@ -2,77 +2,6 @@ package telegram
|
|||
|
||||
import "encoding/json"
|
||||
|
||||
const (
|
||||
ActionFindLocation = "find_location"
|
||||
ActionRecordAudio = "record_audio"
|
||||
ActionRecordVideo = "record_video"
|
||||
ActionRecordVideoNote = "record_video_note"
|
||||
ActionTyping = "typing"
|
||||
ActionUploadAudio = "upload_audio"
|
||||
ActionUploadDocument = "upload_document"
|
||||
ActionUploadPhoto = "upload_photo"
|
||||
ActionUploadVideo = "upload_video"
|
||||
ActionUploadVideoNote = "upload_video_note"
|
||||
|
||||
ChatChannel = "channel"
|
||||
ChatGroup = "group"
|
||||
ChatPrivate = "private"
|
||||
ChatSuperGroup = "supergroup"
|
||||
|
||||
EntityBold = "bold"
|
||||
EntityBotCommand = "bot_command"
|
||||
EntityCode = "code"
|
||||
EntityEmail = "email"
|
||||
EntityHashtag = "hashtag"
|
||||
EntityItalic = "italic"
|
||||
EntityMention = "mention"
|
||||
EntityPre = "pre"
|
||||
EntityTextLink = "text_link"
|
||||
EntityTextMention = "text_mention"
|
||||
EntityURL = "url"
|
||||
|
||||
ModeHTML = "html"
|
||||
ModeMarkdown = "markdown"
|
||||
|
||||
MimeHTML = "text/html"
|
||||
MimeMP4 = "video/mp4"
|
||||
MimePDF = "application/pdf"
|
||||
MimeZIP = "application/zip"
|
||||
|
||||
PrefixAttach = "attach://"
|
||||
|
||||
StatusAdministrator = "administrator"
|
||||
StatusCreator = "creator"
|
||||
StatusKicked = "kicked"
|
||||
StatusLeft = "left"
|
||||
StatusMember = "member"
|
||||
StatusRestricted = "restricted"
|
||||
|
||||
TypeArticle = "article"
|
||||
TypeAudio = "audio"
|
||||
TypeContact = "contact"
|
||||
TypeDocument = "document"
|
||||
TypeGame = "game"
|
||||
TypeGIF = "gif"
|
||||
TypeLocation = "location"
|
||||
TypeMpeg4Gif = "mpeg4_gif"
|
||||
TypePhoto = "photo"
|
||||
TypeSticker = "sticker"
|
||||
TypeVenue = "venue"
|
||||
TypeVideo = "video"
|
||||
TypeVoice = "voice"
|
||||
|
||||
UpdateCallbackQuery = "callback_query"
|
||||
UpdateChannelPost = "channel_post"
|
||||
UpdateChosenInlineResult = "chosen_inline_result"
|
||||
UpdateEditedChannelPost = "edited_channel_post"
|
||||
UpdateEditedMessage = "edited_message"
|
||||
UpdateInlineQuery = "inline_query"
|
||||
UpdateMessage = "message"
|
||||
UpdatePreCheckoutQuery = "pre_checkout_query"
|
||||
UpdateShippingQuery = "shipping_query"
|
||||
)
|
||||
|
||||
type (
|
||||
// Response represents a response from the Telegram API with the result
|
||||
// stored raw. If ok equals true, the request was successful, and the result
|
||||
|
@ -132,6 +61,10 @@ type (
|
|||
// Webhook URL, may be empty if webhook is not set up
|
||||
URL string `json:"url"`
|
||||
|
||||
// Error message in human-readable format for the most recent error that
|
||||
// happened when trying to deliver an update via webhook
|
||||
LastErrorMessage string `json:"last_error_message,omitempty"`
|
||||
|
||||
// True, if a custom certificate was provided for webhook certificate
|
||||
// checks
|
||||
HasCustomCertificate bool `json:"has_custom_certificate"`
|
||||
|
@ -139,18 +72,14 @@ type (
|
|||
// Number of updates awaiting delivery
|
||||
PendingUpdateCount int `json:"pending_update_count"`
|
||||
|
||||
// Unix time for the most recent error that happened when trying to
|
||||
// deliver an update via webhook
|
||||
LastErrorDate int64 `json:"last_error_date,omitempty"`
|
||||
|
||||
// Error message in human-readable format for the most recent error that
|
||||
// happened when trying to deliver an update via webhook
|
||||
LastErrorMessage string `json:"last_error_message,omitempty"`
|
||||
|
||||
// Maximum allowed number of simultaneous HTTPS connections to the
|
||||
// webhook for update delivery
|
||||
MaxConnections int `json:"max_connections,omitempty"`
|
||||
|
||||
// Unix time for the most recent error that happened when trying to
|
||||
// deliver an update via webhook
|
||||
LastErrorDate int64 `json:"last_error_date,omitempty"`
|
||||
|
||||
// A list of update types the bot is subscribed to. Defaults to all
|
||||
// update types
|
||||
AllowedUpdates []string `json:"allowed_updates,omitempty"`
|
||||
|
@ -198,12 +127,6 @@ type (
|
|||
// Last name of the other party in a private chat
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
|
||||
// True if a group has ‘All Members Are Admins’ enabled.
|
||||
AllMembersAreAdministrators bool `json:"all_members_are_administrators,omitempty"`
|
||||
|
||||
// Chat photo. Returned only in getChat.
|
||||
Photo *ChatPhoto `json:"photo,omitempty"`
|
||||
|
||||
// Description, for supergroups and channel chats. Returned only in
|
||||
// getChat.
|
||||
Description string `json:"description,omitempty"`
|
||||
|
@ -212,15 +135,21 @@ type (
|
|||
// getChat.
|
||||
InviteLink string `json:"invite_link,omitempty"`
|
||||
|
||||
// Pinned message, for supergroups. Returned only in getChat.
|
||||
PinnedMessage *Message `json:"pinned_message,omitempty"`
|
||||
|
||||
// For supergroups, name of Group sticker set. Returned only in getChat.
|
||||
StickerSetName string `json:"sticker_set_name,omitempty"`
|
||||
|
||||
// True if a group has ‘All Members Are Admins’ enabled.
|
||||
AllMembersAreAdministrators bool `json:"all_members_are_administrators,omitempty"`
|
||||
|
||||
// True, if the bot can change group the sticker set. Returned only in
|
||||
// getChat.
|
||||
CanSetStickerSet bool `json:"can_set_sticker_set,omitempty"`
|
||||
|
||||
// Chat photo. Returned only in getChat.
|
||||
Photo *ChatPhoto `json:"photo,omitempty"`
|
||||
|
||||
// Pinned message, for supergroups. Returned only in getChat.
|
||||
PinnedMessage *Message `json:"pinned_message,omitempty"`
|
||||
}
|
||||
|
||||
// Message represents a message.
|
||||
|
@ -228,42 +157,49 @@ type (
|
|||
// Unique message identifier inside this chat
|
||||
ID int `json:"message_id"`
|
||||
|
||||
// Sender, empty for messages sent to channels
|
||||
From *User `json:"from,omitempty"`
|
||||
|
||||
// Date the message was sent in Unix time
|
||||
Date int64 `json:"date"`
|
||||
|
||||
// Conversation the message belongs to
|
||||
Chat *Chat `json:"chat"`
|
||||
|
||||
// For forwarded messages, sender of the original message
|
||||
ForwardFrom *User `json:"forward_from,omitempty"`
|
||||
|
||||
// For messages forwarded from channels, information about the original
|
||||
// channel
|
||||
ForwardFromChat *Chat `json:"forward_from_chat,omitempty"`
|
||||
|
||||
// For messages forwarded from channels, identifier of the original
|
||||
// message in the channel
|
||||
ForwardFromMessageID int `json:"forward_from_message_id,omitempty"`
|
||||
|
||||
// For messages forwarded from channels, signature of the post author if
|
||||
// present
|
||||
ForwardSignature string `json:"forward_signature,omitempty"`
|
||||
// Sender, empty for messages sent to channels
|
||||
From *User `json:"from,omitempty"`
|
||||
|
||||
// For forwarded messages, sender of the original message
|
||||
ForwardFrom *User `json:"forward_from,omitempty"`
|
||||
|
||||
// A member was removed from the group, information about them (this
|
||||
// member may be the bot itself)
|
||||
LeftChatMember *User `json:"left_chat_member,omitempty"`
|
||||
|
||||
// Date the message was sent in Unix time
|
||||
Date int64 `json:"date"`
|
||||
|
||||
// For forwarded messages, date the original message was sent in Unix
|
||||
// time
|
||||
ForwardDate int64 `json:"forward_date,omitempty"`
|
||||
|
||||
// For replies, the original message. Note that the Message object in
|
||||
// this field will not contain further reply_to_message fields even if it
|
||||
// itself is a reply.
|
||||
ReplyToMessage *Message `json:"reply_to_message,omitempty"`
|
||||
|
||||
// Date the message was last edited in Unix time
|
||||
EditDate int64 `json:"edit_date,omitempty"`
|
||||
|
||||
// The group has been migrated to a supergroup with the specified
|
||||
// identifier.
|
||||
MigrateToChatID int64 `json:"migrate_to_chat_id,omitempty"`
|
||||
|
||||
// The supergroup has been migrated from a group with the specified
|
||||
// identifier.
|
||||
MigrateFromChatID int64 `json:"migrate_from_chat_id,omitempty"`
|
||||
|
||||
// Conversation the message belongs to
|
||||
Chat *Chat `json:"chat"`
|
||||
|
||||
// For messages forwarded from channels, information about the original
|
||||
// channel
|
||||
ForwardFromChat *Chat `json:"forward_from_chat,omitempty"`
|
||||
|
||||
// For messages forwarded from channels, signature of the post author if
|
||||
// present
|
||||
ForwardSignature string `json:"forward_signature,omitempty"`
|
||||
|
||||
// The unique identifier of a media message group this message belongs to
|
||||
MediaGroupID string `json:"media_group_id,omitempty"`
|
||||
|
||||
|
@ -274,6 +210,25 @@ type (
|
|||
// characters.
|
||||
Text string `json:"text,omitempty"`
|
||||
|
||||
// Caption for the document, photo or video, 0-200 characters
|
||||
Caption string `json:"caption,omitempty"`
|
||||
|
||||
// A chat title was changed to this value
|
||||
NewChatTitle string `json:"new_chat_title,omitempty"`
|
||||
|
||||
// The domain name of the website on which the user has logged in.
|
||||
ConnectedWebsite string `json:"connected_website,omitempty"`
|
||||
|
||||
// For replies, the original message. Note that the Message object in
|
||||
// this field will not contain further reply_to_message fields even if it
|
||||
// itself is a reply.
|
||||
ReplyToMessage *Message `json:"reply_to_message,omitempty"`
|
||||
|
||||
// Specified message was pinned. Note that the Message object in this
|
||||
// field will not contain further reply_to_message fields even if it is
|
||||
// itself a reply.
|
||||
PinnedMessage *Message `json:"pinned_message,omitempty"`
|
||||
|
||||
// For text messages, special entities like usernames, URLs, bot
|
||||
// commands, etc. that appear in the text
|
||||
Entities []MessageEntity `json:"entities,omitempty"`
|
||||
|
@ -294,6 +249,9 @@ type (
|
|||
// Message is a photo, available sizes of the photo
|
||||
Photo []PhotoSize `json:"photo,omitempty"`
|
||||
|
||||
// A chat photo was change to this value
|
||||
NewChatPhoto []PhotoSize `json:"new_chat_photo,omitempty"`
|
||||
|
||||
// Message is a sticker, information about the sticker
|
||||
Sticker *Sticker `json:"sticker,omitempty"`
|
||||
|
||||
|
@ -306,9 +264,6 @@ type (
|
|||
// Message is a video note, information about the video message
|
||||
VideoNote *VideoNote `json:"video_note,omitempty"`
|
||||
|
||||
// Caption for the document, photo or video, 0-200 characters
|
||||
Caption string `json:"caption,omitempty"`
|
||||
|
||||
// Message is a shared contact, information about the contact
|
||||
Contact *Contact `json:"contact,omitempty"`
|
||||
|
||||
|
@ -322,16 +277,6 @@ type (
|
|||
// about them (the bot itself may be one of these members)
|
||||
NewChatMembers []User `json:"new_chat_members,omitempty"`
|
||||
|
||||
// A member was removed from the group, information about them (this
|
||||
// member may be the bot itself)
|
||||
LeftChatMember *User `json:"left_chat_member,omitempty"`
|
||||
|
||||
// A chat title was changed to this value
|
||||
NewChatTitle string `json:"new_chat_title,omitempty"`
|
||||
|
||||
// A chat photo was change to this value
|
||||
NewChatPhoto []PhotoSize `json:"new_chat_photo,omitempty"`
|
||||
|
||||
// Service message: the chat photo was deleted
|
||||
DeleteChatPhoto bool `json:"delete_chat_photo,omitempty"`
|
||||
|
||||
|
@ -352,28 +297,12 @@ type (
|
|||
// channel.
|
||||
ChannelChatCreated bool `json:"channel_chat_created,omitempty"`
|
||||
|
||||
// The group has been migrated to a supergroup with the specified
|
||||
// identifier.
|
||||
MigrateToChatID int64 `json:"migrate_to_chat_id,omitempty"`
|
||||
|
||||
// The supergroup has been migrated from a group with the specified
|
||||
// identifier.
|
||||
MigrateFromChatID int64 `json:"migrate_from_chat_id,omitempty"`
|
||||
|
||||
// Specified message was pinned. Note that the Message object in this
|
||||
// field will not contain further reply_to_message fields even if it is
|
||||
// itself a reply.
|
||||
PinnedMessage *Message `json:"pinned_message,omitempty"`
|
||||
|
||||
// Message is an invoice for a payment, information about the invoice.
|
||||
Invoice *Invoice `json:"invoice,omitempty"`
|
||||
|
||||
// Message is a service message about a successful payment, information
|
||||
// about the payment.
|
||||
SuccessfulPayment *SuccessfulPayment `json:"successful_payment,omitempty"`
|
||||
|
||||
// The domain name of the website on which the user has logged in.
|
||||
ConnectedWebsite string `json:"connected_website,omitempty"`
|
||||
}
|
||||
|
||||
// MessageEntity represents one special entity in a text message. For
|
||||
|
@ -385,16 +314,16 @@ type (
|
|||
// text_mention (for users without usernames)
|
||||
Type string `json:"type"`
|
||||
|
||||
// For "text_link" only, url that will be opened after user taps on the
|
||||
// text
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Offset in UTF-16 code units to the start of the entity
|
||||
Offset int `json:"offset"`
|
||||
|
||||
// Length of the entity in UTF-16 code units
|
||||
Length int `json:"length"`
|
||||
|
||||
// For "text_link" only, url that will be opened after user taps on the
|
||||
// text
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// For "text_mention" only, the mentioned user
|
||||
User *User `json:"user,omitempty"`
|
||||
}
|
||||
|
@ -420,9 +349,6 @@ type (
|
|||
// Unique identifier for this file
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Duration of the audio in seconds as defined by sender
|
||||
Duration int `json:"duration"`
|
||||
|
||||
// Performer of the audio as defined by sender or by audio tags
|
||||
Performer string `json:"performer,omitempty"`
|
||||
|
||||
|
@ -432,6 +358,9 @@ type (
|
|||
// MIME type of the file as defined by sender
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
|
||||
// Duration of the audio in seconds as defined by sender
|
||||
Duration int `json:"duration"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
}
|
||||
|
@ -442,15 +371,15 @@ type (
|
|||
// Unique file identifier
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Document thumbnail as defined by sender
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// Original filename as defined by sender
|
||||
FileName string `json:"file_name,omitempty"`
|
||||
|
||||
// MIME type of the file as defined by sender
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
|
||||
// Document thumbnail as defined by sender
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
}
|
||||
|
@ -460,6 +389,9 @@ type (
|
|||
// Unique identifier for this file
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Mime type of a file as defined by sender
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
|
||||
// Video width as defined by sender
|
||||
Width int `json:"width"`
|
||||
|
||||
|
@ -469,14 +401,11 @@ type (
|
|||
// Duration of the video in seconds as defined by sender
|
||||
Duration int `json:"duration"`
|
||||
|
||||
// Video thumbnail
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// Mime type of a file as defined by sender
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
|
||||
// Video thumbnail
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
}
|
||||
|
||||
// Voice represents a voice note.
|
||||
|
@ -484,12 +413,12 @@ type (
|
|||
// Unique identifier for this file
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Duration of the audio in seconds as defined by sender
|
||||
Duration int `json:"duration"`
|
||||
|
||||
// MIME type of the file as defined by sender
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
|
||||
// Duration of the audio in seconds as defined by sender
|
||||
Duration int `json:"duration"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
}
|
||||
|
@ -506,11 +435,11 @@ type (
|
|||
// Duration of the video in seconds as defined by sender
|
||||
Duration int `json:"duration"`
|
||||
|
||||
// Video thumbnail
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
|
||||
// Video thumbnail
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
}
|
||||
|
||||
// Contact represents a phone contact.
|
||||
|
@ -571,12 +500,12 @@ type (
|
|||
// Unique identifier for this file
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// File size, if known
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
|
||||
// File path. Use https://api.telegram.org/file/bot<token>/<file_path> to
|
||||
// get the file.
|
||||
FilePath string `json:"file_path,omitempty"`
|
||||
|
||||
// File size, if known
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
}
|
||||
|
||||
// ReplyKeyboardMarkup represents a custom keyboard with reply options (see
|
||||
|
@ -720,14 +649,6 @@ type (
|
|||
// Unique identifier for this query
|
||||
ID string `json:"id"`
|
||||
|
||||
// Sender
|
||||
From *User `json:"from"`
|
||||
|
||||
// Message with the callback button that originated the query. Note that
|
||||
// message content and message date will not be available if the message
|
||||
// is too old
|
||||
Message *Message `json:"message,omitempty"`
|
||||
|
||||
// Identifier of the message sent via the bot in inline mode, that
|
||||
// originated the query.
|
||||
InlineMessageID string `json:"inline_message_id,omitempty"`
|
||||
|
@ -744,6 +665,14 @@ type (
|
|||
// Short name of a Game to be returned, serves as the unique identifier
|
||||
// for the game
|
||||
GameShortName string `json:"game_short_name,omitempty"`
|
||||
|
||||
// Sender
|
||||
From *User `json:"from"`
|
||||
|
||||
// Message with the callback button that originated the query. Note that
|
||||
// message content and message date will not be available if the message
|
||||
// is too old
|
||||
Message *Message `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
// ForceReply display a reply interface to the user (act as if the user has
|
||||
|
@ -922,26 +851,26 @@ type (
|
|||
// Unique identifier for this file
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Sticker width
|
||||
Width int `json:"width"`
|
||||
|
||||
// Sticker height
|
||||
Height int `json:"height"`
|
||||
|
||||
// Sticker thumbnail in the .webp or .jpg format
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// Emoji associated with the sticker
|
||||
Emoji string `json:"emoji,omitempty"`
|
||||
|
||||
// Name of the sticker set to which the sticker belongs
|
||||
SetName string `json:"set_name,omitempty"`
|
||||
|
||||
// For mask stickers, the position where the mask should be placed
|
||||
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
|
||||
// Sticker width
|
||||
Width int `json:"width"`
|
||||
|
||||
// Sticker height
|
||||
Height int `json:"height"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
|
||||
// Sticker thumbnail in the .webp or .jpg format
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// For mask stickers, the position where the mask should be placed
|
||||
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
|
||||
}
|
||||
|
||||
// StickerSet represents a sticker set.
|
||||
|
@ -986,17 +915,17 @@ type (
|
|||
// Unique identifier for this query
|
||||
ID string `json:"id"`
|
||||
|
||||
// Sender
|
||||
From *User `json:"from"`
|
||||
|
||||
// Sender location, only for bots that request user location
|
||||
Location *Location `json:"location,omitempty"`
|
||||
|
||||
// Text of the query (up to 512 characters)
|
||||
Query string `json:"query"`
|
||||
|
||||
// Offset of the results to be returned, can be controlled by the bot
|
||||
Offset string `json:"offset"`
|
||||
|
||||
// Sender
|
||||
From *User `json:"from"`
|
||||
|
||||
// Sender location, only for bots that request user location
|
||||
Location *Location `json:"location,omitempty"`
|
||||
}
|
||||
|
||||
// InlineQueryResult represents one result of an inline query.
|
||||
|
@ -1034,24 +963,24 @@ type (
|
|||
//Title of the result
|
||||
Title string `json:"title"`
|
||||
|
||||
// Content of the message to be sent
|
||||
InputMessageContent interface{} `json:"input_message_content"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
// URL of the result
|
||||
URL string `json:"url,omitempty"`
|
||||
|
||||
// Pass True, if you don't want the URL to be shown in the message
|
||||
HideURL bool `json:"hide_url,omitempty"`
|
||||
|
||||
// Short description of the result
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Content of the message to be sent
|
||||
InputMessageContent interface{} `json:"input_message_content"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
// Pass True, if you don't want the URL to be shown in the message
|
||||
HideURL bool `json:"hide_url,omitempty"`
|
||||
|
||||
// Thumbnail width
|
||||
ThumbWidth int `json:"thumb_width,omitempty"`
|
||||
|
||||
|
@ -1077,12 +1006,6 @@ type (
|
|||
// URL of the thumbnail for the photo
|
||||
ThumbURL string `json:"thumb_url"`
|
||||
|
||||
// Width of the photo
|
||||
PhotoWidth int `json:"photo_width,omitempty"`
|
||||
|
||||
// Height of the photo
|
||||
PhotoHeight int `json:"photo_height,omitempty"`
|
||||
|
||||
// Title for the result
|
||||
Title string `json:"title,omitempty"`
|
||||
|
||||
|
@ -1096,6 +1019,12 @@ type (
|
|||
// fixed-width text or inline URLs in the media caption.
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
|
||||
// Width of the photo
|
||||
PhotoWidth int `json:"photo_width,omitempty"`
|
||||
|
||||
// Height of the photo
|
||||
PhotoHeight int `json:"photo_height,omitempty"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
|
@ -1117,15 +1046,6 @@ type (
|
|||
// A valid URL for the GIF file. File size must not exceed 1MB
|
||||
GifURL string `json:"gif_url"`
|
||||
|
||||
// Width of the GIF
|
||||
GifWidth int `json:"gif_width,omitempty"`
|
||||
|
||||
// Height of the GIF
|
||||
GifHeight int `json:"gif_height,omitempty"`
|
||||
|
||||
// Duration of the GIF
|
||||
GifDuration int `json:"gif_duration,omitempty"`
|
||||
|
||||
// URL of the static thumbnail for the result (jpeg or gif)
|
||||
ThumbURL string `json:"thumb_url"`
|
||||
|
||||
|
@ -1139,6 +1059,15 @@ type (
|
|||
// fixed-width text or inline URLs in the media caption.
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
|
||||
// Width of the GIF
|
||||
GifWidth int `json:"gif_width,omitempty"`
|
||||
|
||||
// Height of the GIF
|
||||
GifHeight int `json:"gif_height,omitempty"`
|
||||
|
||||
// Duration of the GIF
|
||||
GifDuration int `json:"gif_duration,omitempty"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
|
@ -1161,15 +1090,6 @@ type (
|
|||
// A valid URL for the MP4 file. File size must not exceed 1MB
|
||||
Mpeg4URL string `json:"mpeg4_url"`
|
||||
|
||||
// Video width
|
||||
Mpeg4Width int `json:"mpeg4_width,omitempty"`
|
||||
|
||||
// Video height
|
||||
Mpeg4Height int `json:"mpeg4_height,omitempty"`
|
||||
|
||||
// Video duration
|
||||
Mpeg4Duration int `json:"mpeg4_duration,omitempty"`
|
||||
|
||||
// URL of the static thumbnail (jpeg or gif) for the result
|
||||
ThumbURL string `json:"thumb_url"`
|
||||
|
||||
|
@ -1179,6 +1099,15 @@ type (
|
|||
// Caption of the MPEG-4 file to be sent, 0-200 characters
|
||||
Caption string `json:"caption,omitempty"`
|
||||
|
||||
// Video width
|
||||
Mpeg4Width int `json:"mpeg4_width,omitempty"`
|
||||
|
||||
// Video height
|
||||
Mpeg4Height int `json:"mpeg4_height,omitempty"`
|
||||
|
||||
// Video duration
|
||||
Mpeg4Duration int `json:"mpeg4_duration,omitempty"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
|
@ -1220,6 +1149,9 @@ type (
|
|||
// fixed-width text or inline URLs in the media caption.
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
|
||||
// Short description of the result
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Video width
|
||||
VideoWidth int `json:"video_width,omitempty"`
|
||||
|
||||
|
@ -1229,9 +1161,6 @@ type (
|
|||
// Video duration in seconds
|
||||
VideoDuration int `json:"video_duration,omitempty"`
|
||||
|
||||
// Short description of the result
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
|
@ -1344,15 +1273,15 @@ type (
|
|||
// Short description of the result
|
||||
Description string `json:"description,omitempty"`
|
||||
|
||||
// URL of the thumbnail (jpeg only) for the file
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
// Content of the message to be sent instead of the file
|
||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
||||
|
||||
// URL of the thumbnail (jpeg only) for the file
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Thumbnail width
|
||||
ThumbWidth int `json:"thumb_width,omitempty"`
|
||||
|
||||
|
@ -1371,24 +1300,24 @@ type (
|
|||
// Unique identifier for this result, 1-64 Bytes
|
||||
ID string `json:"id"`
|
||||
|
||||
// Location title
|
||||
Title string `json:"title"`
|
||||
|
||||
//Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Location latitude in degrees
|
||||
Latitude float32 `json:"latitude"`
|
||||
|
||||
// Location longitude in degrees
|
||||
Longitude float32 `json:"longitude"`
|
||||
|
||||
// Location title
|
||||
Title string `json:"title"`
|
||||
|
||||
//Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
//Content of the message to be sent instead of the location
|
||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
||||
|
||||
//Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
//Thumbnail width
|
||||
ThumbWidth int `json:"thumb_width,omitempty"`
|
||||
|
||||
|
@ -1406,12 +1335,6 @@ type (
|
|||
// Unique identifier for this result, 1-64 Bytes
|
||||
ID string `json:"id"`
|
||||
|
||||
// Latitude of the venue location in degrees
|
||||
Latitude float32 `json:"latitude"`
|
||||
|
||||
// Longitude of the venue location in degrees
|
||||
Longitude float32 `json:"longitude"`
|
||||
|
||||
// Title of the venue
|
||||
Title string `json:"title"`
|
||||
|
||||
|
@ -1421,15 +1344,21 @@ type (
|
|||
// Foursquare identifier of the venue if known
|
||||
FoursquareID string `json:"foursquare_id,omitempty"`
|
||||
|
||||
// Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Latitude of the venue location in degrees
|
||||
Latitude float32 `json:"latitude"`
|
||||
|
||||
// Longitude of the venue location in degrees
|
||||
Longitude float32 `json:"longitude"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
// Content of the message to be sent instead of the venue
|
||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
||||
|
||||
// Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Thumbnail width
|
||||
ThumbWidth int `json:"thumb_width,omitempty"`
|
||||
|
||||
|
@ -1457,15 +1386,15 @@ type (
|
|||
// Contact's last name
|
||||
LastName string `json:"last_name,omitempty"`
|
||||
|
||||
// Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Inline keyboard attached to the message
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
|
||||
// Content of the message to be sent instead of the contact
|
||||
InputMessageContent interface{} `json:"input_message_content,omitempty"`
|
||||
|
||||
// Url of the thumbnail for the result
|
||||
ThumbURL string `json:"thumb_url,omitempty"`
|
||||
|
||||
// Thumbnail width
|
||||
ThumbWidth int `json:"thumb_width,omitempty"`
|
||||
|
||||
|
@ -1806,12 +1735,6 @@ type (
|
|||
// The unique identifier for the result that was chosen
|
||||
ResultID string `json:"result_id"`
|
||||
|
||||
// The user that chose the result
|
||||
From *User `json:"from"`
|
||||
|
||||
// Sender location, only for bots that require user location
|
||||
Location *Location `json:"location,omitempty"`
|
||||
|
||||
// Identifier of the sent inline message. Available only if there is an
|
||||
// inline keyboard attached to the message. Will be also received in
|
||||
// callback queries and can be used to edit the message.
|
||||
|
@ -1819,6 +1742,12 @@ type (
|
|||
|
||||
// The query that was used to obtain the result
|
||||
Query string `json:"query"`
|
||||
|
||||
// The user that chose the result
|
||||
From *User `json:"from"`
|
||||
|
||||
// Sender location, only for bots that require user location
|
||||
Location *Location `json:"location,omitempty"`
|
||||
}
|
||||
|
||||
// LabeledPrice represents a portion of the price for goods or services.
|
||||
|
@ -1910,6 +1839,18 @@ type (
|
|||
// Three-letter ISO 4217 currency code
|
||||
Currency string `json:"currency"`
|
||||
|
||||
// Bot specified invoice payload
|
||||
InvoicePayload string `json:"invoice_payload"`
|
||||
|
||||
// Identifier of the shipping option chosen by the user
|
||||
ShippingOptionID string `json:"shipping_option_id,omitempty"`
|
||||
|
||||
// Telegram payment identifier
|
||||
TelegramPaymentChargeID string `json:"telegram_payment_charge_id"`
|
||||
|
||||
// Provider payment identifier
|
||||
ProviderPaymentChargeID string `json:"provider_payment_charge_id"`
|
||||
|
||||
// Total price in the smallest units of the currency (integer, not
|
||||
// float/double). For example, for a price of US$ 1.45 pass amount = 145.
|
||||
// See the exp parameter in currencies.json, it shows the number of
|
||||
|
@ -1917,20 +1858,8 @@ type (
|
|||
// of currencies).
|
||||
TotalAmount int `json:"total_amount"`
|
||||
|
||||
// Bot specified invoice payload
|
||||
InvoicePayload string `json:"invoice_payload"`
|
||||
|
||||
// Identifier of the shipping option chosen by the user
|
||||
ShippingOptionID string `json:"shipping_option_id,omitempty"`
|
||||
|
||||
// Order info provided by the user
|
||||
OrderInfo *OrderInfo `json:"order_info,omitempty"`
|
||||
|
||||
// Telegram payment identifier
|
||||
TelegramPaymentChargeID string `json:"telegram_payment_charge_id"`
|
||||
|
||||
// Provider payment identifier
|
||||
ProviderPaymentChargeID string `json:"provider_payment_charge_id"`
|
||||
}
|
||||
|
||||
// ShippingQuery contains information about an incoming shipping query.
|
||||
|
@ -1938,12 +1867,12 @@ type (
|
|||
// Unique query identifier
|
||||
ID string `json:"id"`
|
||||
|
||||
// User who sent the query
|
||||
From *User `json:"from"`
|
||||
|
||||
// Bot specified invoice payload
|
||||
InvoicePayload string `json:"invoice_payload"`
|
||||
|
||||
// User who sent the query
|
||||
From *User `json:"from"`
|
||||
|
||||
// User specified shipping address
|
||||
ShippingAddress *ShippingAddress `json:"shipping_address"`
|
||||
}
|
||||
|
@ -1953,12 +1882,18 @@ type (
|
|||
// Unique query identifier
|
||||
ID string `json:"id"`
|
||||
|
||||
// User who sent the query
|
||||
From *User `json:"from"`
|
||||
|
||||
// Three-letter ISO 4217 currency code
|
||||
Currency string `json:"currency"`
|
||||
|
||||
// Bot specified invoice payload
|
||||
InvoicePayload string `json:"invoice_payload"`
|
||||
|
||||
// Identifier of the shipping option chosen by the user
|
||||
ShippingOptionID string `json:"shipping_option_id,omitempty"`
|
||||
|
||||
// User who sent the query
|
||||
From *User `json:"from"`
|
||||
|
||||
// Total price in the smallest units of the currency (integer, not
|
||||
// float/double). For example, for a price of US$ 1.45 pass amount = 145.
|
||||
// See the exp parameter in currencies.json, it shows the number of
|
||||
|
@ -1966,12 +1901,6 @@ type (
|
|||
// currencies).
|
||||
TotalAmount int `json:"total_amount"`
|
||||
|
||||
// Bot specified invoice payload
|
||||
InvoicePayload string `json:"invoice_payload"`
|
||||
|
||||
// Identifier of the shipping option chosen by the user
|
||||
ShippingOptionID string `json:"shipping_option_id,omitempty"`
|
||||
|
||||
// Order info provided by the user
|
||||
OrderInfo *OrderInfo `json:"order_info,omitempty"`
|
||||
}
|
||||
|
@ -1985,15 +1914,15 @@ type (
|
|||
// Description of the game
|
||||
Description string `json:"description"`
|
||||
|
||||
// Photo that will be displayed in the game message in chats.
|
||||
Photo []PhotoSize `json:"photo"`
|
||||
|
||||
// Brief description of the game or high scores included in the game
|
||||
// message. Can be automatically edited to include current high scores
|
||||
// for the game when the bot calls setGameScore, or manually edited
|
||||
// using editMessageText. 0-4096 characters.
|
||||
Text string `json:"text,omitempty"`
|
||||
|
||||
// Photo that will be displayed in the game message in chats.
|
||||
Photo []PhotoSize `json:"photo"`
|
||||
|
||||
// Special entities that appear in text, such as usernames, URLs, bot
|
||||
// commands, etc.
|
||||
TextEntities []MessageEntity `json:"text_entities,omitempty"`
|
||||
|
@ -2010,15 +1939,15 @@ type (
|
|||
// Unique file identifier
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Animation thumbnail as defined by sender
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// Original animation filename as defined by sender
|
||||
FileName string `json:"file_name,omitempty"`
|
||||
|
||||
// MIME type of the file as defined by sender
|
||||
MimeType string `json:"mime_type,omitempty"`
|
||||
|
||||
// Animation thumbnail as defined by sender
|
||||
Thumb *PhotoSize `json:"thumb,omitempty"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
}
|
||||
|
@ -2032,11 +1961,11 @@ type (
|
|||
// Position in high score table for the game
|
||||
Position int `json:"position"`
|
||||
|
||||
// User
|
||||
User *User `json:"user"`
|
||||
|
||||
// Score
|
||||
Score int `json:"score"`
|
||||
|
||||
// User
|
||||
User *User `json:"user"`
|
||||
}
|
||||
|
||||
// ReplyMarkup is a JSON-serialized object for an inline keyboard, custom
|
||||
|
|
14
new_bot.go
14
new_bot.go
|
@ -1,14 +0,0 @@
|
|||
package telegram
|
||||
|
||||
type Bot struct {
|
||||
AccessToken string
|
||||
Self *User
|
||||
}
|
||||
|
||||
func NewBot(accessToken string) (*Bot, error) {
|
||||
var err error
|
||||
bot := &Bot{AccessToken: accessToken}
|
||||
|
||||
bot.Self, err = bot.GetMe()
|
||||
return bot, err
|
||||
}
|
|
@ -19,7 +19,7 @@ func (bot *Bot) PinChatMessage(params *PinChatMessageParameters) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "pinChatMessage")
|
||||
resp, err := bot.request(dst, MethodPinChatMessage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func (bot *Bot) SendChatAction(chatID int64, action string) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendChatAction")
|
||||
resp, err := bot.request(dst, MethodSendChatAction)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ func (bot *Bot) SendContact(params *SendContactParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendContact")
|
||||
resp, err := bot.request(dst, MethodSendContact)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ func (bot *Bot) SendDocument(params *SendDocumentParameters) (*Message, error) {
|
|||
|
||||
args.Add("disable_notification", strconv.FormatBool(params.DisableNotification))
|
||||
|
||||
resp, err := bot.upload(params.Document, "document", "", "sendDocument", args)
|
||||
resp, err := bot.Upload(MethodSendDocument, "document", "", params.Document, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func (bot *Bot) SendGame(params *SendGameParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendGame")
|
||||
resp, err := bot.request(dst, MethodSendGame)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -26,10 +26,6 @@ type SendInvoiceParameters struct {
|
|||
// Three-letter ISO 4217 currency code, see more on currencies
|
||||
Currency string `json:"currency"`
|
||||
|
||||
// Price breakdown, a list of components (e.g. product price, tax, discount,
|
||||
// delivery cost, delivery tax, bonus, etc.)
|
||||
Prices []LabeledPrice `json:"prices"`
|
||||
|
||||
// JSON-encoded data about the invoice, which will be shared with the payment
|
||||
// provider. A detailed description of required fields should be provided by
|
||||
// the payment provider.
|
||||
|
@ -40,6 +36,10 @@ type SendInvoiceParameters struct {
|
|||
// they are paying for.
|
||||
PhotoURL string `json:"photo_url,omitempty"`
|
||||
|
||||
// Price breakdown, a list of components (e.g. product price, tax, discount,
|
||||
// delivery cost, delivery tax, bonus, etc.)
|
||||
Prices []LabeledPrice `json:"prices"`
|
||||
|
||||
// Photo size
|
||||
PhotoSize int `json:"photo_size,omitempty"`
|
||||
|
||||
|
@ -49,6 +49,9 @@ type SendInvoiceParameters struct {
|
|||
// Photo height
|
||||
PhotoHeight int `json:"photo_height,omitempty"`
|
||||
|
||||
// If the message is a reply, ID of the original message
|
||||
ReplyToMessageID int `json:"reply_to_message_id,omitempty"`
|
||||
|
||||
// Pass True, if you require the user's full name to complete the order
|
||||
NeedName bool `json:"need_name,omitempty"`
|
||||
|
||||
|
@ -69,9 +72,6 @@ type SendInvoiceParameters struct {
|
|||
// sound.
|
||||
DisableNotification bool `json:"disable_notification,omitempty"`
|
||||
|
||||
// If the message is a reply, ID of the original message
|
||||
ReplyToMessageID int `json:"reply_to_message_id,omitempty"`
|
||||
|
||||
// A JSON-serialized object for an inline keyboard. If empty, one 'Pay total
|
||||
// price' button will be shown. If not empty, the first button must be a Pay
|
||||
// button.
|
||||
|
@ -98,7 +98,7 @@ func (bot *Bot) SendInvoice(params *SendInvoiceParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendInvoice")
|
||||
resp, err := bot.request(dst, MethodSendInvoice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -16,13 +16,13 @@ type SendLocationParameters struct {
|
|||
// Locations), should be between 60 and 86400.
|
||||
LivePeriod int `json:"live_period,omitempty"`
|
||||
|
||||
// If the message is a reply, ID of the original message
|
||||
ReplyToMessageID int `json:"reply_to_message_id,omitempty"`
|
||||
|
||||
// Sends the message silently. Users will receive a notification with no
|
||||
// sound.
|
||||
DisableNotification bool `json:"disable_notification,omitempty"`
|
||||
|
||||
// If the message is a reply, ID of the original message
|
||||
ReplyToMessageID int `json:"reply_to_message_id,omitempty"`
|
||||
|
||||
// A JSON-serialized object for an inline keyboard. If empty, one 'Pay total
|
||||
// price' button will be shown. If not empty, the first button must be a Pay
|
||||
// button.
|
||||
|
@ -44,7 +44,7 @@ func (bot *Bot) SendLocation(params *SendLocationParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendLocation")
|
||||
resp, err := bot.request(dst, MethodSendLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ func (bot *Bot) SendMediaGroup(params *SendMediaGroupParameters) ([]Message, err
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendMediaGroup")
|
||||
resp, err := bot.request(dst, MethodSendMediaGroup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ func (bot *Bot) SendMessage(params *SendMessageParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendMessage")
|
||||
resp, err := bot.request(dst, MethodSendMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ func (bot *Bot) SendPhoto(params *SendPhotoParameters) (*Message, error) {
|
|||
|
||||
args.Add("disable_notification", strconv.FormatBool(params.DisableNotification))
|
||||
|
||||
resp, err := bot.upload(params.Photo, "photo", "", "sendPhoto", args)
|
||||
resp, err := bot.Upload(MethodSendPhoto, "photo", "", params.Photo, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ func (bot *Bot) SendVenue(params *SendVenueParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "sendVenue")
|
||||
resp, err := bot.request(dst, MethodSendVenue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ func (bot *Bot) SetChatDescription(chatID int64, description string) (bool, erro
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "setChatDescription")
|
||||
resp, err := bot.request(dst, MethodSetChatDescription)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ func (bot *Bot) SetChatPhoto(chatID int64, chatPhoto interface{}) (bool, error)
|
|||
defer http.ReleaseArgs(args)
|
||||
args.Add("chat_id", strconv.FormatInt(chatID, 10))
|
||||
|
||||
resp, err := bot.upload(chatPhoto, TypePhoto, "chat_photo", "setChatPhoto", args)
|
||||
resp, err := bot.Upload(MethodSetChatPhoto, TypePhoto, "chat_photo", chatPhoto, args)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ func (bot *Bot) SetChatStickerSet(chatID int64, stickerSetName string) (bool, er
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "setChatStickerSet")
|
||||
resp, err := bot.request(dst, MethodSetChatStickerSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ func (bot *Bot) SetChatTitle(chatID int64, title string) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "setChatTitle")
|
||||
resp, err := bot.request(dst, MethodSetChatTitle)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -9,6 +9,10 @@ type SetGameScoreParameters struct {
|
|||
// New score, must be non-negative
|
||||
Score int `json:"score"`
|
||||
|
||||
// Required if inline_message_id is not specified. Identifier of the sent
|
||||
// message
|
||||
MessageID int `json:"message_id,omitempty"`
|
||||
|
||||
// Pass True, if the high score is allowed to decrease. This can be useful
|
||||
// when fixing mistakes or banning cheaters
|
||||
Force bool `json:"force,omitempty"`
|
||||
|
@ -21,10 +25,6 @@ type SetGameScoreParameters struct {
|
|||
// target chat
|
||||
ChatID int64 `json:"chat_id,omitempty"`
|
||||
|
||||
// Required if inline_message_id is not specified. Identifier of the sent
|
||||
// message
|
||||
MessageID int `json:"message_id,omitempty"`
|
||||
|
||||
// Required if chat_id and message_id are not specified. Identifier of the
|
||||
// inline message
|
||||
InlineMessageID string `json:"inline_message_id,omitempty"`
|
||||
|
@ -47,7 +47,7 @@ func (bot *Bot) SetGameScore(params *SetGameScoreParameters) (*Message, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "setGameScore")
|
||||
resp, err := bot.request(dst, MethodSetGameScore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ func (bot *Bot) SetStickerPositionInSet(sticker string, position int) (bool, err
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "setStickerPositionInSet")
|
||||
resp, err := bot.request(dst, MethodSetStickerPositionInSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import (
|
|||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
const setWebhook = "setWebhook"
|
||||
|
||||
type SetWebhookParameters struct {
|
||||
// HTTPS url to send updates to. Use an empty string to remove webhook
|
||||
// integration
|
||||
|
@ -72,16 +70,15 @@ func (bot *Bot) SetWebhook(params *SetWebhookParameters) (bool, error) {
|
|||
resp *Response
|
||||
)
|
||||
if params.Certificate != nil {
|
||||
resp, err = bot.upload(
|
||||
params.Certificate, "certificate", "cert.pem", setWebhook, args,
|
||||
)
|
||||
resp, err = bot.Upload(MethodSetWebhook, "certificate", "cert.pem", params.Certificate, args)
|
||||
} else {
|
||||
dst, err := json.Marshal(params)
|
||||
var dst []byte
|
||||
dst, err = json.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err = bot.request(dst, setWebhook)
|
||||
resp, err = bot.request(dst, MethodSetWebhook)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
|
|
|
@ -8,12 +8,12 @@ import (
|
|||
|
||||
func TestGetMe(t *testing.T) {
|
||||
var err error
|
||||
bot.Self, err = bot.GetMe()
|
||||
bot.User, err = bot.GetMe()
|
||||
if err != nil {
|
||||
t.Error(err.Error())
|
||||
t.FailNow()
|
||||
}
|
||||
if bot.Self == nil {
|
||||
if bot.User == nil {
|
||||
t.Error("unexpected result: bot user is nil")
|
||||
t.FailNow()
|
||||
}
|
||||
|
|
|
@ -8,13 +8,13 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
photoFileID = "AgADAgADw6cxG4zHKAkr42N7RwEN3IFShCoABHQwXEtVks4EH2wBAAEC"
|
||||
documentFileID = "BQADAgADOQADjMcoCcioX1GrDvp3Ag"
|
||||
audioFileID = "BQADAgADRgADjMcoCdXg3lSIN49lAg"
|
||||
voiceFileID = "AwADAgADWQADjMcoCeul6r_q52IyAg"
|
||||
videoFileID = "BAADAgADZgADjMcoCav432kYe0FRAg"
|
||||
videoNoteFileID = "DQADAgADdQAD70cQSUK41dLsRMqfAg"
|
||||
stickerFileID = "BQADAgADcwADjMcoCbdl-6eB--YPAg"
|
||||
photoFileID = "AgADAgADw6cxG4zHKAkr42N7RwEN3IFShCoABHQwXEtVks4EH2wBAAEC"
|
||||
documentFileID = "BQADAgADOQADjMcoCcioX1GrDvp3Ag"
|
||||
// audioFileID = "BQADAgADRgADjMcoCdXg3lSIN49lAg"
|
||||
// voiceFileID = "AwADAgADWQADjMcoCeul6r_q52IyAg"
|
||||
// videoFileID = "BAADAgADZgADjMcoCav432kYe0FRAg"
|
||||
// videoNoteFileID = "DQADAgADdQAD70cQSUK41dLsRMqfAg"
|
||||
// stickerFileID = "BQADAgADcwADjMcoCbdl-6eB--YPAg"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
@ -22,7 +22,7 @@ func (bot *Bot) UnbanChatMember(chatID int64, userID int) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "unbanChatMember")
|
||||
resp, err := bot.request(dst, MethodUnbanChatMember)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ func (bot *Bot) UnpinChatMessage(chatID int64) (bool, error) {
|
|||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, "unpinChatMessage")
|
||||
resp, err := bot.request(dst, MethodUnpinChatMessage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
|
98
upload.go
98
upload.go
|
@ -17,7 +17,7 @@ import (
|
|||
var ErrBadFileType = errors.New("bad file type")
|
||||
|
||||
/*
|
||||
upload is a helper method which provide are three ways to send files (photos, stickers, audio,
|
||||
Upload is a helper method which provide are three ways to send files (photos, stickers, audio,
|
||||
media, etc.):
|
||||
|
||||
1. If the file is already stored somewhere on the Telegram servers, you don't need to reupload it:
|
||||
|
@ -45,7 +45,7 @@ sendAudio, etc.).
|
|||
voice notes will be sent as files.
|
||||
- Other configurations may work but we can't guarantee that they will.
|
||||
*/
|
||||
func (bot *Bot) upload(file InputFile, fieldName, fileName, method string, args *http.Args) (*Response, error) {
|
||||
func (bot *Bot) Upload(method, key, name string, file InputFile, args fmt.Stringer) (*Response, error) {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
multi := multipart.NewWriter(buffer)
|
||||
|
||||
|
@ -66,49 +66,21 @@ func (bot *Bot) upload(file InputFile, fieldName, fileName, method string, args
|
|||
}
|
||||
}
|
||||
|
||||
switch f := file.(type) {
|
||||
switch src := file.(type) {
|
||||
case string:
|
||||
if _, err = os.Stat(f); os.IsNotExist(err) {
|
||||
// Send by 'file_id'
|
||||
if err = multi.WriteField(fieldName, f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Upload new
|
||||
src, err := os.Open(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer src.Close()
|
||||
|
||||
formFile, err := multi.CreateFormFile(fieldName, src.Name())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = io.Copy(formFile, src); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
case []byte: // Upload new
|
||||
formFile, err := multi.CreateFormFile(fieldName, fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = io.Copy(formFile, bytes.NewReader(f)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = uploadByString(multi, key, src)
|
||||
case *url.URL: // Send by URL
|
||||
if err = multi.WriteField(fieldName, f.String()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = uploadFromURL(multi, key, src)
|
||||
case []byte: // Upload new
|
||||
err = uploadFromMemory(multi, key, name, bytes.NewReader(src))
|
||||
case io.Reader: // Upload new
|
||||
if _, err = multi.CreateFormFile(fieldName, fileName); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = uploadFromMemory(multi, key, name, src)
|
||||
default:
|
||||
return nil, ErrBadFileType
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err = multi.Close(); err != nil {
|
||||
return nil, err
|
||||
|
@ -149,3 +121,51 @@ func (bot *Bot) upload(file InputFile, fieldName, fileName, method string, args
|
|||
|
||||
return &data, nil
|
||||
}
|
||||
|
||||
func uploadByString(w *multipart.Writer, key, src string) error {
|
||||
_, err := os.Stat(src)
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
err = uploadFromFileID(w, key, src)
|
||||
case os.IsExist(err):
|
||||
err = uploadFromDisk(w, key, src)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func uploadFromFileID(w *multipart.Writer, key, src string) error {
|
||||
return w.WriteField(key, src)
|
||||
}
|
||||
|
||||
func uploadFromDisk(w *multipart.Writer, key, src string) error {
|
||||
file, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
_ = file.Close()
|
||||
}()
|
||||
|
||||
var formFile io.Writer
|
||||
formFile, err = w.CreateFormFile(key, file.Name())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(formFile, file)
|
||||
return err
|
||||
}
|
||||
|
||||
func uploadFromURL(w *multipart.Writer, key string, src *url.URL) error {
|
||||
return w.WriteField(key, src.String())
|
||||
}
|
||||
|
||||
func uploadFromMemory(w *multipart.Writer, key, value string, src io.Reader) error {
|
||||
field, err := w.CreateFormFile(key, value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = io.Copy(field, src)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func NewForceReply() *ForceReply {
|
||||
return &ForceReply{ForceReply: true}
|
||||
}
|
||||
|
||||
func NewInlineMentionURL(userID int) *url.URL {
|
||||
link := &url.URL{
|
||||
Scheme: SchemeTelegram,
|
||||
Path: "user",
|
||||
}
|
||||
|
||||
q := link.Query()
|
||||
q.Add("id", strconv.Itoa(userID))
|
||||
link.RawQuery = q.Encode()
|
||||
|
||||
return link
|
||||
}
|
|
@ -6,16 +6,29 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
type Bot struct {
|
||||
AccessToken string
|
||||
*User
|
||||
}
|
||||
|
||||
func New(accessToken string) (*Bot, error) {
|
||||
var err error
|
||||
bot := &Bot{AccessToken: accessToken}
|
||||
|
||||
bot.User, err = bot.GetMe()
|
||||
return bot, err
|
||||
}
|
||||
|
||||
func (bot *Bot) IsMessageFromMe(msg *Message) bool {
|
||||
if msg == nil || bot == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if msg.From == nil || bot.Self == nil {
|
||||
if msg.From == nil || bot.User == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return msg.From.ID == bot.Self.ID
|
||||
return msg.From.ID == bot.ID
|
||||
}
|
||||
|
||||
func (bot *Bot) IsForwardFromMe(msg *Message) bool {
|
||||
|
@ -27,11 +40,11 @@ func (bot *Bot) IsForwardFromMe(msg *Message) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if bot.Self == nil {
|
||||
if bot.User == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return msg.ForwardFrom.ID == bot.Self.ID
|
||||
return msg.ForwardFrom.ID == bot.ID
|
||||
}
|
||||
|
||||
func (bot *Bot) IsReplyToMe(msg *Message) bool {
|
||||
|
@ -60,7 +73,7 @@ func (bot *Bot) IsCommandToMe(msg *Message) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
return strings.ToLower(parts[1]) == strings.ToLower(bot.Self.Username)
|
||||
return strings.ToLower(parts[1]) == strings.ToLower(bot.User.Username)
|
||||
}
|
||||
|
||||
func (bot *Bot) IsMessageMentionsMe(msg *Message) bool {
|
||||
|
@ -68,7 +81,7 @@ func (bot *Bot) IsMessageMentionsMe(msg *Message) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
if bot.Self == nil {
|
||||
if bot.User == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -86,7 +99,7 @@ func (bot *Bot) IsMessageMentionsMe(msg *Message) bool {
|
|||
|
||||
for _, entity := range entities {
|
||||
if entity.IsMention() {
|
||||
if bot.Self.ID == entity.User.ID {
|
||||
if bot.ID == entity.User.ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
@ -143,18 +156,18 @@ func (bot *Bot) NewRedirectURL(group bool, param string) *url.URL {
|
|||
return nil
|
||||
}
|
||||
|
||||
if bot.Self == nil {
|
||||
if bot.User == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if bot.Self.Username == "" {
|
||||
if bot.User.Username == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
link := &url.URL{
|
||||
Scheme: "https",
|
||||
Host: "t.me",
|
||||
Path: bot.Self.Username,
|
||||
Path: bot.User.Username,
|
||||
}
|
||||
|
||||
q := link.Query()
|
|
@ -1,5 +1,7 @@
|
|||
package telegram
|
||||
|
||||
import "fmt"
|
||||
|
||||
func (chat *Chat) IsPrivate() bool {
|
||||
if chat == nil {
|
||||
return false
|
||||
|
@ -39,3 +41,40 @@ func (chat *Chat) HasPinnedMessage() bool {
|
|||
|
||||
return chat.PinnedMessage != nil
|
||||
}
|
||||
|
||||
func (chat *Chat) HasStickerSet() bool {
|
||||
if chat == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return chat.StickerSetName != ""
|
||||
}
|
||||
|
||||
func (chat *Chat) StickerSet(bot *Bot) *StickerSet {
|
||||
if !chat.HasStickerSet() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if bot == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
set, err := bot.GetStickerSet(chat.StickerSetName)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (chat *Chat) FullName() string {
|
||||
if chat == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
if chat.LastName != "" {
|
||||
return fmt.Sprintln(chat.FirstName, chat.LastName)
|
||||
}
|
||||
|
||||
return chat.FirstName
|
||||
}
|
|
@ -10,28 +10,24 @@ func (entity *MessageEntity) ParseURL(messageText string) *url.URL {
|
|||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
link := new(url.URL)
|
||||
switch {
|
||||
case entity.IsTextLink():
|
||||
link, err = url.Parse(entity.URL)
|
||||
case entity.IsURL():
|
||||
if messageText == "" {
|
||||
return nil
|
||||
}
|
||||
if !entity.IsURL() {
|
||||
return nil
|
||||
}
|
||||
|
||||
rawMessageText := []rune(messageText)
|
||||
if len(rawMessageText) < (entity.Offset + entity.Length) {
|
||||
return nil
|
||||
}
|
||||
if messageText == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
from := entity.Offset
|
||||
to := from + entity.Length
|
||||
rawURL := string([]rune(messageText)[from:to])
|
||||
link, err = url.Parse(rawURL)
|
||||
if err == nil && link.Scheme == "" {
|
||||
link, err = url.Parse(fmt.Sprint("http://", link))
|
||||
}
|
||||
from := entity.Offset
|
||||
to := from + entity.Length
|
||||
text := []rune(messageText)
|
||||
if len(text) < to {
|
||||
return nil
|
||||
}
|
||||
|
||||
link, err := url.Parse(string(text[from:to]))
|
||||
if err == nil && link.Scheme == "" {
|
||||
link, err = url.Parse(fmt.Sprint("http://", link))
|
||||
}
|
||||
if err != nil {
|
||||
return nil
|
||||
|
@ -127,3 +123,16 @@ func (entity *MessageEntity) IsURL() bool {
|
|||
|
||||
return entity.Type == EntityURL
|
||||
}
|
||||
|
||||
func (entity *MessageEntity) TextLink() *url.URL {
|
||||
if entity == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
link, err := url.Parse(entity.URL)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return link
|
||||
}
|
|
@ -15,7 +15,6 @@ func (msg *Message) IsCommand(command string) bool {
|
|||
}
|
||||
|
||||
entity := msg.Entities[0]
|
||||
|
||||
isBotCommand := entity.IsBotCommand() && entity.Offset == 0
|
||||
if command != "" {
|
||||
return isBotCommand && strings.EqualFold(msg.Command(), command)
|
||||
|
@ -94,18 +93,23 @@ func (msg *Message) ForwardTime() time.Time {
|
|||
}
|
||||
|
||||
func (msg *Message) EditTime() time.Time {
|
||||
var t time.Time
|
||||
if msg == nil {
|
||||
return time.Time{}
|
||||
return t
|
||||
}
|
||||
|
||||
if !msg.HasBeenEdited() {
|
||||
return time.Time{}
|
||||
return t
|
||||
}
|
||||
|
||||
return time.Unix(msg.EditDate, 0)
|
||||
}
|
||||
|
||||
func (msg *Message) HasBeenEdited() bool {
|
||||
if msg == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return msg.EditDate > 0
|
||||
}
|
||||
|
||||
|
@ -140,6 +144,7 @@ func (msg *Message) IsSticker() bool {
|
|||
func (msg *Message) IsVideo() bool {
|
||||
return !msg.IsText() && msg.Video != nil
|
||||
}
|
||||
|
||||
func (msg *Message) IsVoice() bool {
|
||||
return !msg.IsText() && msg.Voice != nil
|
||||
}
|
|
@ -25,7 +25,7 @@ func (user *User) FullName() string {
|
|||
}
|
||||
|
||||
if user.LastName != "" {
|
||||
return fmt.Sprint(user.FirstName, " ", user.LastName)
|
||||
return fmt.Sprintln(user.FirstName, user.LastName)
|
||||
}
|
||||
|
||||
return user.FirstName
|
Loading…
Reference in New Issue