♻️ Refactoring code
This commit is contained in:
parent
7659fbb9f5
commit
82e84ed718
56
add.go
56
add.go
|
@ -1,56 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type AddStickerToSetParameters struct {
|
||||
// User identifier of sticker set owner
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Sticker set name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
|
||||
PNGSticker interface{} `json:"png_sticker"`
|
||||
|
||||
// One or more emoji corresponding to the sticker
|
||||
Emojis string `json:"emojis"`
|
||||
|
||||
// A JSON-serialized object for position where the mask should be placed on faces
|
||||
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
|
||||
}
|
||||
|
||||
// AddStickerToSet add a new sticker to a set created by the bot. Returns True
|
||||
// on success.
|
||||
func (b *Bot) AddStickerToSet(params *AddStickerToSetParameters) (bool, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.SetUint("user_id", params.UserID)
|
||||
|
||||
if !strings.HasSuffix(strings.ToLower(params.Name), strings.ToLower("_by_"+b.Username)) {
|
||||
params.Name = params.Name + "_by_" + b.Username
|
||||
}
|
||||
|
||||
args.Set("emojis", params.Emojis)
|
||||
|
||||
if params.MaskPosition != nil {
|
||||
mp, err := parser.Marshal(params.MaskPosition)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
args.SetBytesV("mask_position", mp)
|
||||
}
|
||||
|
||||
resp, err := b.Upload(MethodAddStickerToSet, TypeSticker, "sticker", params.PNGSticker, args)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
227
answer.go
227
answer.go
|
@ -1,227 +0,0 @@
|
|||
package telegram
|
||||
|
||||
type (
|
||||
// AnswerCallbackQueryParameters represents data for AnswerCallbackQuery method.
|
||||
AnswerCallbackQueryParameters struct {
|
||||
// Unique identifier for the query to be answered
|
||||
CallbackQueryID string `json:"callback_query_id"`
|
||||
|
||||
// Text of the notification. If not specified, nothing will be shown to the
|
||||
// user, 0-200 characters
|
||||
Text string `json:"text,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
|
||||
// callback_game button.
|
||||
//
|
||||
// Otherwise, you may use links like t.me/your_bot?start=XXXX that open your
|
||||
// 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.
|
||||
CacheTime int `json:"cache_time,omitempty"`
|
||||
}
|
||||
|
||||
// AnswerPreCheckoutQueryParameters represents data for AnswerPreCheckoutQuery
|
||||
// method.
|
||||
AnswerPreCheckoutQueryParameters struct {
|
||||
// Unique identifier for the query to be answered
|
||||
PreCheckoutQueryID string `json:"pre_checkout_query_id"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// AnswerShippingQueryParameters represents data for AnswerShippingQuery method.
|
||||
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)
|
||||
Ok bool `json:"ok"`
|
||||
|
||||
// Required if ok is True. A JSON-serialized array of available shipping
|
||||
// options.
|
||||
ShippingOptions []ShippingOption `json:"shipping_options,omitempty"`
|
||||
}
|
||||
|
||||
// AnswerInlineQueryParameters represents data for AnswerInlineQuery method.
|
||||
AnswerInlineQueryParameters struct {
|
||||
// Unique identifier for the answered query
|
||||
InlineQueryID string `json:"inline_query_id"`
|
||||
|
||||
// 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
|
||||
// bytes.
|
||||
NextOffset string `json:"next_offset,omitempty"`
|
||||
|
||||
// If passed, clients will display a button with specified text that switches
|
||||
// the user to a private chat with the bot and sends the bot a start message
|
||||
// with the parameter switch_pm_parameter
|
||||
SwitchPrivateMessageText string `json:"switch_pm_text,omitempty"`
|
||||
|
||||
// Deep-linking parameter for the /start message sent to the bot when user
|
||||
// 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"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewAnswerCallbackQuery creates AnswerCallbackQueryParameters only with
|
||||
// required parameters.
|
||||
func NewAnswerCallbackQuery(callbackQueryID string) *AnswerCallbackQueryParameters {
|
||||
return &AnswerCallbackQueryParameters{CallbackQueryID: callbackQueryID}
|
||||
}
|
||||
|
||||
// NewAnswerPreCheckoutQuery creates AnswerPreCheckoutQueryParameters only with
|
||||
// required parameters.
|
||||
func NewAnswerPreCheckoutQuery(preCheckoutQueryID string, ok bool) *AnswerPreCheckoutQueryParameters {
|
||||
return &AnswerPreCheckoutQueryParameters{
|
||||
PreCheckoutQueryID: preCheckoutQueryID,
|
||||
Ok: ok,
|
||||
}
|
||||
}
|
||||
|
||||
// NewAnswerShippingQuery creates AnswerShippingQueryParameters only with
|
||||
// required parameters.
|
||||
func NewAnswerShippingQuery(shippingQueryID string, ok bool) *AnswerShippingQueryParameters {
|
||||
return &AnswerShippingQueryParameters{
|
||||
ShippingQueryID: shippingQueryID,
|
||||
Ok: ok,
|
||||
}
|
||||
}
|
||||
|
||||
// NewAnswerInlineQuery creates AnswerInlineQueryParameters only with required
|
||||
// parameters.
|
||||
func NewAnswerInlineQuery(inlineQueryID string, results ...interface{}) *AnswerInlineQueryParameters {
|
||||
return &AnswerInlineQueryParameters{
|
||||
InlineQueryID: inlineQueryID,
|
||||
Results: results,
|
||||
}
|
||||
}
|
||||
|
||||
// AnswerCallbackQuery send answers to callback queries sent from inline
|
||||
// keyboards. The answer will be displayed to the user as a notification at the
|
||||
// top of the chat screen or as an alert. On success, True is returned.
|
||||
//
|
||||
// Alternatively, the user can be redirected to the specified Game URL. For this
|
||||
// option to work, you must first create a game for your bot via @Botfather and
|
||||
// accept the terms. Otherwise, you may use links like t.me/your_bot?start=XXXX
|
||||
// that open your bot with a parameter.
|
||||
func (bot *Bot) AnswerCallbackQuery(params *AnswerCallbackQueryParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodAnswerCallbackQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// AnswerPreCheckoutQuery respond to such pre-checkout queries.
|
||||
//
|
||||
// Once the user has confirmed their payment and shipping details, the Bot API
|
||||
// sends the final confirmation in the form of an Update with the field
|
||||
// pre_checkout_query. Use this method to respond to such pre-checkout queries.
|
||||
// On success, True is returned.
|
||||
//
|
||||
// Note: The Bot API must receive an answer within 10 seconds after the
|
||||
// pre-checkout query was sent.
|
||||
func (bot *Bot) AnswerPreCheckoutQuery(params *AnswerShippingQueryParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodAnswerPreCheckoutQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// AnswerShippingQuery reply to shipping queries.
|
||||
//
|
||||
// If you sent an invoice requesting a shipping address and the parameter
|
||||
// is_flexible was specified, the Bot API will send an Update with a
|
||||
// shipping_query field to the bot. On success, True is returned.
|
||||
func (bot *Bot) AnswerShippingQuery(params *AnswerShippingQueryParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodAnswerShippingQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// AnswerInlineQuery send answers to an inline query. On success, True is returned.
|
||||
//
|
||||
// No more than 50 results per query are allowed.
|
||||
func (bot *Bot) AnswerInlineQuery(params *AnswerInlineQueryParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodAnswerInlineQuery)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
20
const.go
20
const.go
|
@ -1,7 +1,9 @@
|
|||
package telegram
|
||||
|
||||
import "github.com/Masterminds/semver"
|
||||
|
||||
// Version represents current version of Telegram API supported by this package
|
||||
const Version string = "4.4"
|
||||
var Version = semver.MustParse("4.5.0")
|
||||
|
||||
// Action represents available and supported status actions of bot
|
||||
const (
|
||||
|
@ -25,14 +27,14 @@ const (
|
|||
ChatSuperGroup string = "supergroup"
|
||||
)
|
||||
|
||||
// Command represents global commands which should be supported by any bot.
|
||||
// Command represents global commands which should be supported by any b.
|
||||
// You can user IsCommandEqual method of Message for checking.
|
||||
//
|
||||
// See: https://core.telegram.org/bots#global-commands
|
||||
const (
|
||||
CommandStart string = "start"
|
||||
CommandHelp string = "help"
|
||||
CommandSettings string = "settings"
|
||||
CommandStart string = "start"
|
||||
)
|
||||
|
||||
// Entity represents available and supported entity types
|
||||
|
@ -131,6 +133,13 @@ const (
|
|||
ParseModeMarkdownV2 string = "MarkdownV2"
|
||||
)
|
||||
|
||||
const (
|
||||
PointForehead string = "forehead"
|
||||
PointEyes string = "eyes"
|
||||
PointMouth string = "mouth"
|
||||
PointChin string = "chin"
|
||||
)
|
||||
|
||||
// Mime represents available and supported MIME types of data
|
||||
const (
|
||||
MimeHTML string = "text/html"
|
||||
|
@ -198,3 +207,8 @@ const (
|
|||
UpdatePreCheckoutQuery string = "pre_checkout_query"
|
||||
UpdateShippingQuery string = "shipping_query"
|
||||
)
|
||||
|
||||
const (
|
||||
DefaultAudioSeparator = " – "
|
||||
DefaultAudioTitle = "[untitled]"
|
||||
)
|
||||
|
|
76
create.go
76
create.go
|
@ -1,76 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type CreateNewStickerSetParameters struct {
|
||||
// User identifier of created sticker set owner
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Short name of sticker set, to be used in t.me/addstickers/ URLs
|
||||
// (e.g., animals). Can contain only english letters, digits and
|
||||
// underscores. Must begin with a letter, can't contain consecutive
|
||||
// underscores and must end in “_by_<bot username>”. <bot_username>
|
||||
// is case insensitive. 1-64 characters.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Sticker set title, 1-64 characters
|
||||
Title string `json:"title"`
|
||||
|
||||
// Png image with the sticker, must be up to 512 kilobytes in size,
|
||||
// dimensions must not exceed 512px, and either width or height must
|
||||
// be exactly 512px. Pass a file_id as a String to send a file that
|
||||
// already exists on the Telegram servers, pass an HTTP URL as a
|
||||
// String for Telegram to get a file from the Internet, or upload
|
||||
// a new one using multipart/form-data.
|
||||
PNGSticker interface{} `json:"png_sticker"`
|
||||
|
||||
// One or more emoji corresponding to the sticker
|
||||
Emojis string `json:"emojis"`
|
||||
|
||||
// Pass True, if a set of mask stickers should be created
|
||||
ContainsMasks bool `json:"contains_masks,omitempty"`
|
||||
|
||||
// A JSON-serialized object for position where the mask should be
|
||||
// placed on faces
|
||||
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
|
||||
}
|
||||
|
||||
// CreateNewStickerSet create new sticker set owned by a user. The bot will be
|
||||
// able to edit the created sticker set. Returns True on success.
|
||||
func (b *Bot) CreateNewStickerSet(params *CreateNewStickerSetParameters) (bool, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.SetUint("user_id", params.UserID)
|
||||
|
||||
if !strings.HasSuffix(strings.ToLower(params.Name), strings.ToLower("_by_"+b.Username)) {
|
||||
params.Name = params.Name + "_by_" + b.Username
|
||||
}
|
||||
|
||||
args.Set("name", params.Name)
|
||||
args.Set("title", params.Title)
|
||||
args.Set("emojis", params.Emojis)
|
||||
args.Set("contains_masks", strconv.FormatBool(params.ContainsMasks))
|
||||
|
||||
if params.MaskPosition != nil {
|
||||
mp, err := parser.Marshal(params.MaskPosition)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
args.SetBytesV("mask_position", mp)
|
||||
}
|
||||
|
||||
resp, err := b.Upload(MethodCreateNewStickerSet, TypeSticker, "sticker", params.PNGSticker, args)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
129
delete.go
129
delete.go
|
@ -1,129 +0,0 @@
|
|||
package telegram
|
||||
|
||||
type (
|
||||
// DeleteChatPhotoParameters represents data for DeleteChatPhoto method.
|
||||
DeleteChatPhotoParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// DeleteChatStickerSetParameters represents data for DeleteChatStickerSet method.
|
||||
DeleteChatStickerSetParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// DeleteMessageParameters represents data for DeleteMessage method.
|
||||
DeleteMessageParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Identifier of the message to delete
|
||||
MessageID int `json:"message_id"`
|
||||
}
|
||||
|
||||
// DeleteStickerFromSetParameters represents data for DeleteStickerFromSet method.
|
||||
DeleteStickerFromSetParameters struct {
|
||||
// File identifier of the sticker
|
||||
Sticker string `json:"sticker"`
|
||||
}
|
||||
)
|
||||
|
||||
// DeleteChatPhoto delete a chat photo. Photos can't be changed for private
|
||||
// chats. The bot must be an administrator in the chat for this to work and must
|
||||
// have the appropriate admin rights. Returns True on success.
|
||||
//
|
||||
// Note: In regular groups (non-supergroups), this method will only work if the
|
||||
// 'All Members Are Admins' setting is off in the target group.
|
||||
func (bot *Bot) DeleteChatPhoto(chatID int64) (bool, error) {
|
||||
dst, err := parser.Marshal(&DeleteChatPhotoParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodDeleteChatPhoto)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// DeleteChatStickerSet delete a group sticker set from a supergroup. The bot must be an administrator
|
||||
// in the chat for this to work and must have the appropriate admin rights. Use the field
|
||||
// can_set_sticker_set optionally returned in getChat requests to check if the bot can use this
|
||||
// method. Returns True on success.
|
||||
func (bot *Bot) DeleteChatStickerSet(chatID int64) (bool, error) {
|
||||
dst, err := parser.Marshal(&DeleteChatStickerSetParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodDeleteChatStickerSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// 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, MethodDeleteWebhook)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// DeleteMessage delete a message, including service messages, with the following
|
||||
// limitations: A message can only be deleted if it was sent less than 48 hours
|
||||
// ago; Bots can delete outgoing messages in groups and supergroups; Bots granted
|
||||
// can_post_messages permissions can delete outgoing messages in channels; If the
|
||||
// bot is an administrator of a group, it can delete any message there; If the
|
||||
// bot has can_delete_messages permission in a supergroup or a channel, it can
|
||||
// delete any message there. Returns True on success.
|
||||
func (bot *Bot) DeleteMessage(chatID int64, messageID int) (bool, error) {
|
||||
dst, err := parser.Marshal(&DeleteMessageParameters{
|
||||
ChatID: chatID,
|
||||
MessageID: messageID,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodDeleteMessage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// DeleteStickerFromSet delete a sticker from a set created by the bot. Returns
|
||||
// True on success.
|
||||
func (bot *Bot) DeleteStickerFromSet(sticker string) (bool, error) {
|
||||
dst, err := parser.Marshal(&DeleteStickerFromSetParameters{Sticker: sticker})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodDeleteStickerFromSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/xerrors"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Code int `json:"error_code"`
|
||||
Description string `json:"description"`
|
||||
Parameters []*ResponseParameters `json:"parameters,omitempty"`
|
||||
frame xerrors.Frame
|
||||
}
|
||||
|
||||
func (e Error) FormatError(p xerrors.Printer) error {
|
||||
p.Printf("%d %s", e.Code, e.Description)
|
||||
e.frame.Format(p)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e Error) Format(s fmt.State, r rune) {
|
||||
xerrors.FormatError(e, s, r)
|
||||
}
|
||||
|
||||
func (e Error) Error() string {
|
||||
return fmt.Sprint(e)
|
||||
}
|
26
export.go
26
export.go
|
@ -1,26 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// ExportChatInviteLinkParameters represents data for ExportChatInviteLink method.
|
||||
type ExportChatInviteLinkParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// ExportChatInviteLink export an invite link to a supergroup or a channel. The
|
||||
// bot must be an administrator in the chat for this to work and must have the
|
||||
// appropriate admin rights. Returns exported invite link as String on success.
|
||||
func (bot *Bot) ExportChatInviteLink(chatID int64) (string, error) {
|
||||
dst, err := parser.Marshal(&ExportChatInviteLinkParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodExportChatInviteLink)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var inviteLink string
|
||||
err = parser.Unmarshal(resp.Result, &inviteLink)
|
||||
return inviteLink, err
|
||||
}
|
45
forward.go
45
forward.go
|
@ -1,45 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// ForwardMessageParameters represents data for ForwardMessage method.
|
||||
type ForwardMessageParameters struct {
|
||||
// Unique identifier for the target chat or username of the target
|
||||
// channel (in the format @channelusername)
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Unique identifier for the chat where the original message was sent
|
||||
// (or channel username in the format @channelusername)
|
||||
FromChatID int64 `json:"from_chat_id"`
|
||||
|
||||
// Sends the message silently. Users will receive a notification with no
|
||||
// sound.
|
||||
DisableNotification bool `json:"disable_notification,omitempty"`
|
||||
|
||||
// Message identifier in the chat specified in from_chat_id
|
||||
MessageID int `json:"message_id"`
|
||||
}
|
||||
|
||||
// NewForwardMessage creates ForwardMessageParameters only with reqired parameters.
|
||||
func NewForwardMessage(from, to int64, messageID int) *ForwardMessageParameters {
|
||||
return &ForwardMessageParameters{
|
||||
FromChatID: from,
|
||||
ChatID: to,
|
||||
MessageID: messageID,
|
||||
}
|
||||
}
|
||||
|
||||
// ForwardMessage forward messages of any kind. On success, the sent Message is returned.
|
||||
func (bot *Bot) ForwardMessage(params *ForwardMessageParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodForwardMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package telegram
|
||||
|
||||
type (
|
||||
// Game represents a game. Use BotFather to create and edit games, their short names will act as unique
|
||||
// identifiers.
|
||||
Game struct {
|
||||
// Title of the game
|
||||
Title string `json:"title"`
|
||||
|
||||
// Description of the game
|
||||
Description string `json:"description"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Animation that will be displayed in the game message in chats. Upload via BotFather
|
||||
Animation *Animation `json:"animation,omitempty"`
|
||||
}
|
||||
|
||||
// CallbackGame a placeholder, currently holds no information. Use BotFather to set up your game.
|
||||
CallbackGame struct{}
|
||||
|
||||
// GameHighScore represents one row of the high scores table for a game.
|
||||
GameHighScore struct {
|
||||
// Position in high score table for the game
|
||||
Position int `json:"position"`
|
||||
|
||||
// Score
|
||||
Score int `json:"score"`
|
||||
|
||||
// User
|
||||
User *User `json:"user"`
|
||||
}
|
||||
|
||||
// SendGameParameters represents data for SendGame method.
|
||||
SendGame struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Short name of the game, serves as the unique identifier for the game. Set up your games via
|
||||
// Botfather.
|
||||
GameShortName string `json:"game_short_name"`
|
||||
|
||||
// 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 ‘Play game_title’ button will be
|
||||
// shown. If not empty, the first button must launch the game.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SetGameScoreParameters represents data for SetGameScore method.
|
||||
SetGameScore struct {
|
||||
// User identifier
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Pass True, if the game message should not be automatically edited to include the current scoreboard
|
||||
DisableEditMessage bool `json:"disable_edit_message,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"`
|
||||
}
|
||||
|
||||
// GetGameHighScoresParameters represents data for GetGameHighScores method.
|
||||
GetGameHighScores struct {
|
||||
// Target user id
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
)
|
||||
|
||||
// SendGame send a game. On success, the sent Message is returned.
|
||||
func (b *Bot) SendGame(p SendGame) (*Message, error) {
|
||||
src, err := b.Do(MethodSendGame, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SetGameScore set the score of the specified user in a game. On success, if the message was sent by the bot, returns
|
||||
// the edited Message, otherwise returns True. Returns an error, if the new score is not greater than the user's
|
||||
// current score in the chat and force is False.
|
||||
func (b *Bot) SetGameScore(p SetGameScore) (*Message, error) {
|
||||
src, err := b.Do(MethodSetGameScore, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetGameHighScores get data for high score tables. Will return the score of the specified user and several of his
|
||||
// neighbors in a game. On success, returns an Array of GameHighScore objects.
|
||||
func (b *Bot) GetGameHighScores(p GetGameHighScores) ([]*GameHighScore, error) {
|
||||
src, err := b.Do(MethodGetGameHighScores, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*GameHighScore, 0)
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
314
get.go
314
get.go
|
@ -1,314 +0,0 @@
|
|||
package telegram
|
||||
|
||||
type (
|
||||
// GetChatParameters represents data for GetChat method.
|
||||
GetChatParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// GetChatAdministratorsParameters represents data for GetChatAdministrators
|
||||
// method.
|
||||
GetChatAdministratorsParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// GetChatMemberParameters represents data for GetChatMember method.
|
||||
GetChatMemberParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Unique identifier of the target user
|
||||
UserID int `json:"user_id"`
|
||||
}
|
||||
|
||||
// GetChatMembersCountParameters represents data for GetChatMembersCount method.
|
||||
GetChatMembersCountParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// GetFileParameters represents data for GetFile method.
|
||||
GetFileParameters struct {
|
||||
// File identifier to get info about
|
||||
FileID string `json:"file_id"`
|
||||
}
|
||||
|
||||
// GetUpdatesParameters represents data for GetUpdates method.
|
||||
GetUpdatesParameters struct {
|
||||
// Identifier of the first update to be returned. Must be greater by one than the highest among the
|
||||
// identifiers of previously received updates. By default, updates starting with the earliest unconfirmed
|
||||
// update are returned. An update is considered confirmed as soon as getUpdates is called with an offset
|
||||
// higher than its update_id. The negative offset can be specified to retrieve updates starting from -offset
|
||||
// update from the end of the updates queue. All previous updates will forgotten.
|
||||
Offset int `json:"offset,omitempty"`
|
||||
|
||||
// Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100.
|
||||
Limit int `json:"limit,omitempty"`
|
||||
|
||||
// Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Should be positive, short
|
||||
// polling should be used for testing purposes only.
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
|
||||
// List the types of updates you want your bot to receive. For example, specify ["message",
|
||||
// "edited_channel_post", "callback_query"] to only receive updates of these types. See Update for a complete
|
||||
// list of available update types. Specify an empty list to receive all updates regardless of type (default).
|
||||
// If not specified, the previous setting will be used.
|
||||
//
|
||||
// Please note that this parameter doesn't affect updates created before the call to the getUpdates, so
|
||||
// unwanted updates may be received for a short period of time.
|
||||
AllowedUpdates []string `json:"allowed_updates,omitempty"`
|
||||
}
|
||||
|
||||
// GetUserProfilePhotosParameters represents data for GetUserProfilePhotos method.
|
||||
GetUserProfilePhotosParameters struct {
|
||||
// Unique identifier of the target user
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Sequential number of the first photo to be returned. By default, all
|
||||
// photos are returned.
|
||||
Offset int `json:"offset,omitempty"`
|
||||
|
||||
// Limits the number of photos to be retrieved. Values between 1—100 are
|
||||
// accepted. Defaults to 100.
|
||||
Limit int `json:"limit,omitempty"`
|
||||
}
|
||||
|
||||
// GetGameHighScoresParameters represents data for GetGameHighScores method.
|
||||
GetGameHighScoresParameters struct {
|
||||
// Target user id
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// GetStickerSetParameters represents data for GetStickerSet method.
|
||||
GetStickerSetParameters struct {
|
||||
// Name of the sticker set
|
||||
Name string `json:"name"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewGameHighScores creates GetGameHighScoresParameters only with required parameters.
|
||||
func NewGameHighScores(userID int) *GetGameHighScoresParameters {
|
||||
return &GetGameHighScoresParameters{
|
||||
UserID: userID,
|
||||
}
|
||||
}
|
||||
|
||||
// GetChat get up to date information about the chat (current name of the user
|
||||
// for one-on-one conversations, current username of a user, group or channel,
|
||||
// etc.). Returns a Chat object on success.
|
||||
func (bot *Bot) GetChat(chatID int64) (*Chat, error) {
|
||||
dst, err := parser.Marshal(&GetChatParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetChat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var chat Chat
|
||||
err = parser.Unmarshal(resp.Result, &chat)
|
||||
return &chat, err
|
||||
}
|
||||
|
||||
// GetChatAdministrators get a list of administrators in a chat. On success,
|
||||
// returns an Array of ChatMember objects that contains information about all
|
||||
// chat administrators except other bots. If the chat is a group or a supergroup
|
||||
// and no administrators were appointed, only the creator will be returned.
|
||||
func (bot *Bot) GetChatAdministrators(chatID int64) ([]ChatMember, error) {
|
||||
dst, err := parser.Marshal(&GetChatAdministratorsParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetChatAdministrators)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var chatMembers []ChatMember
|
||||
err = parser.Unmarshal(resp.Result, &chatMembers)
|
||||
return chatMembers, err
|
||||
}
|
||||
|
||||
// GetChatMember get information about a member of a chat. Returns a ChatMember
|
||||
// object on success.
|
||||
func (bot *Bot) GetChatMember(chatID int64, userID int) (*ChatMember, error) {
|
||||
dst, err := parser.Marshal(&GetChatMemberParameters{
|
||||
ChatID: chatID,
|
||||
UserID: userID,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetChatMember)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var chatMember ChatMember
|
||||
err = parser.Unmarshal(resp.Result, &chatMember)
|
||||
return &chatMember, err
|
||||
}
|
||||
|
||||
// GetChatMembersCount get the number of members in a chat. Returns Int on
|
||||
// success.
|
||||
func (bot *Bot) GetChatMembersCount(chatID int64) (int, error) {
|
||||
dst, err := parser.Marshal(&GetChatMembersCountParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetChatMembersCount)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
var count int
|
||||
err = parser.Unmarshal(resp.Result, &count)
|
||||
return count, err
|
||||
}
|
||||
|
||||
// GetFile get basic info about a file and prepare it for downloading. For the
|
||||
// moment, bots can download files of up to 20MB in size. On success, a File
|
||||
// object is returned. The file can then be downloaded via the link
|
||||
// https://api.telegram.org/file/bot<token>/<file_path>, where <file_path> is
|
||||
// taken from the response. It is guaranteed that the link will be valid for at
|
||||
// least 1 hour. When the link expires, a new one can be requested by calling
|
||||
// getFile again.
|
||||
//
|
||||
// Note: This function may not preserve the original file name and MIME type. You
|
||||
// should save the file's MIME type and name (if available) when the File object
|
||||
// is received.
|
||||
func (bot *Bot) GetFile(fileID string) (*File, error) {
|
||||
dst, err := parser.Marshal(&GetFileParameters{FileID: fileID})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var file File
|
||||
err = parser.Unmarshal(resp.Result, &file)
|
||||
return &file, err
|
||||
}
|
||||
|
||||
// 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, MethodGetMe)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var me User
|
||||
err = parser.Unmarshal(resp.Result, &me)
|
||||
return &me, err
|
||||
}
|
||||
|
||||
// GetUpdates receive incoming updates using long polling. An Array of Update objects is returned.
|
||||
func (bot *Bot) GetUpdates(params *GetUpdatesParameters) ([]Update, error) {
|
||||
if params == nil {
|
||||
params = &GetUpdatesParameters{Limit: 100}
|
||||
}
|
||||
|
||||
src, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(src, MethodGetUpdates)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
updates := make([]Update, params.Limit)
|
||||
err = parser.Unmarshal(resp.Result, &updates)
|
||||
return updates, err
|
||||
}
|
||||
|
||||
// GetUserProfilePhotos get a list of profile pictures for a user. Returns a UserProfilePhotos object.
|
||||
func (bot *Bot) GetUserProfilePhotos(params *GetUserProfilePhotosParameters) (*UserProfilePhotos, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetUserProfilePhotos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var photos UserProfilePhotos
|
||||
err = parser.Unmarshal(resp.Result, &photos)
|
||||
return &photos, err
|
||||
}
|
||||
|
||||
// GetWebhookInfo get current webhook status. Requires no parameters. On success,
|
||||
// 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, MethodGetWebhookInfo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var info WebhookInfo
|
||||
err = parser.Unmarshal(resp.Result, &info)
|
||||
return &info, err
|
||||
}
|
||||
|
||||
// GetGameHighScores get data for high score tables. Will return the score of the
|
||||
// specified user and several of his neighbors in a game. On success, returns an
|
||||
// Array of GameHighScore objects.
|
||||
func (bot *Bot) GetGameHighScores(params *GetGameHighScoresParameters) ([]GameHighScore, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetGameHighScores)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var scores []GameHighScore
|
||||
err = parser.Unmarshal(resp.Result, &scores)
|
||||
return scores, err
|
||||
}
|
||||
|
||||
// GetStickerSet get a sticker set. On success, a StickerSet object is returned.
|
||||
func (bot *Bot) GetStickerSet(name string) (*StickerSet, error) {
|
||||
dst, err := parser.Marshal(&GetStickerSetParameters{Name: name})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodGetStickerSet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var set StickerSet
|
||||
err = parser.Unmarshal(resp.Result, &set)
|
||||
return &set, err
|
||||
}
|
9
go.mod
9
go.mod
|
@ -3,14 +3,15 @@ module gitlab.com/toby3d/telegram
|
|||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/json-iterator/go v1.1.7
|
||||
github.com/Masterminds/semver v1.5.0
|
||||
github.com/json-iterator/go v1.1.9
|
||||
github.com/kirillDanshin/dlog v0.0.0-20170728000807-97d876b12bf9
|
||||
github.com/kirillDanshin/myutils v0.0.0-20160713214838-182269b1fbcc // indirect
|
||||
github.com/klauspost/compress v1.7.4 // indirect
|
||||
github.com/klauspost/cpuid v1.2.1 // indirect
|
||||
github.com/klauspost/compress v1.9.7 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/valyala/fasthttp v1.4.0
|
||||
github.com/valyala/fasthttp v1.7.1
|
||||
golang.org/x/text v0.3.2
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
|
||||
)
|
||||
|
|
26
go.sum
26
go.sum
|
@ -1,20 +1,19 @@
|
|||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/kirillDanshin/dlog v0.0.0-20170728000807-97d876b12bf9 h1:mA7k8E2Vrmyj5CW/D1XZBFmohVNi7jf757vibGwzRbo=
|
||||
github.com/kirillDanshin/dlog v0.0.0-20170728000807-97d876b12bf9/go.mod h1:l8CN7iyX1k2xlsTYVTpCtwBPcxThf/jLWDGVcF6T/bM=
|
||||
github.com/kirillDanshin/myutils v0.0.0-20160713214838-182269b1fbcc h1:OkOhOn3WBUmfATC1NsA3rBlgHGkjk0KGnR5akl/8uXc=
|
||||
github.com/kirillDanshin/myutils v0.0.0-20160713214838-182269b1fbcc/go.mod h1:Bt95qRxLvpdmASW9s2tTxGdQ5ma4o4n8QFhCvzCew/M=
|
||||
github.com/klauspost/compress v1.4.0 h1:8nsMz3tWa9SWWPL60G1V6CUsf4lLjWLTNEtibhe8gh8=
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.7.4 h1:4UqAIzZ1Ns2epCTyJ1d2xMWvxtX+FNSCYWeOFogK9nc=
|
||||
github.com/klauspost/compress v1.7.4/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e h1:+lIPJOWl+jSiJOc70QXJ07+2eg2Jy2EC7Mi11BWujeM=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.9.7 h1:hYW1gP94JUmAhBtJ+LNz5My+gBobDxPR1iVuKug26aA=
|
||||
github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.1 h1:vJi+O/nMdFt0vqm8NZBI6wzALWdA2X+egi0ogNyrC/w=
|
||||
github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -30,10 +29,15 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
|||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.4.0 h1:PuaTGZIw3mjYhhhbVbCQp8aciRZN9YdoB7MGX9Ko76A=
|
||||
github.com/valyala/fasthttp v1.4.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||
github.com/valyala/fasthttp v1.7.1 h1:UHtt5/7O70RSUZTR/hSu0PNWMAfWx5AtsPp9Jk+g17M=
|
||||
github.com/valyala/fasthttp v1.7.1/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestInlineQueryHasQuery(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
iq := InlineQuery{Query: "sample text"}
|
||||
assert.True(t, iq.HasQuery())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
iq := InlineQuery{}
|
||||
assert.False(t, iq.HasQuery())
|
||||
})
|
||||
}
|
||||
|
||||
func TestInlineQueryHasOffset(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
iq := InlineQuery{Offset: "42"}
|
||||
assert.True(t, iq.HasOffset())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
iq := InlineQuery{}
|
||||
assert.False(t, iq.HasOffset())
|
||||
})
|
||||
}
|
||||
|
||||
func TestInlineQueryHasLocation(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
iq := InlineQuery{Location: &Location{Latitude: 56.085180, Longitude: 60.735150}}
|
||||
assert.True(t, iq.HasLocation())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
iq := InlineQuery{}
|
||||
assert.False(t, iq.HasLocation())
|
||||
})
|
||||
}
|
||||
|
||||
func TestChosenInlineResultInlineQueryHasLocation(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
cir := ChosenInlineResult{Location: &Location{Latitude: 56.085180, Longitude: 60.735150}}
|
||||
assert.True(t, cir.HasLocation())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
cir := ChosenInlineResult{}
|
||||
assert.False(t, cir.HasLocation())
|
||||
})
|
||||
}
|
39
kick.go
39
kick.go
|
@ -1,39 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// KickChatMemberParameters represents data for KickChatMember method.
|
||||
type KickChatMemberParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Unique identifier of the target user
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Date when the user will be unbanned, unix time. If user is banned for
|
||||
// more than 366 days or less than 30 seconds from the current time they
|
||||
// are considered to be banned forever
|
||||
UntilDate int64 `json:"until_date"`
|
||||
}
|
||||
|
||||
// KickChatMember kick a user from a group, a supergroup or a channel. In the case of supergroups and
|
||||
// channels, the user will not be able to return to the group on their own using invite links, etc.,
|
||||
// unless unbanned first. The bot must be an administrator in the chat for this to work and must have
|
||||
// the appropriate admin rights. Returns True on success.
|
||||
//
|
||||
// Note: In regular groups (non-supergroups), this method will only work if the 'All Members Are
|
||||
// Admins' setting is off in the target group. Otherwise members may only be removed by the group's
|
||||
// creator or by the member that added them.
|
||||
func (bot *Bot) KickChatMember(params *KickChatMemberParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodKickChatMember)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
24
leave.go
24
leave.go
|
@ -1,24 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// LeaveChatParameters represents data for LeaveChat method.
|
||||
type LeaveChatParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// LeaveChat leave a group, supergroup or channel. Returns True on success.
|
||||
func (bot *Bot) LeaveChat(chatID int64) (bool, error) {
|
||||
dst, err := parser.Marshal(&LeaveChatParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodLeaveChat)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,347 @@
|
|||
package telegram
|
||||
|
||||
type (
|
||||
// LabeledPrice represents a portion of the price for goods or services.
|
||||
LabeledPrice struct {
|
||||
// Portion label
|
||||
Label string `json:"label"`
|
||||
|
||||
// Price of the product 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
|
||||
// digits past the decimal point for each currency (2 for the majority
|
||||
// of currencies).
|
||||
Amount int `json:"amount"`
|
||||
}
|
||||
|
||||
// Invoice contains basic information about an invoice.
|
||||
Invoice struct {
|
||||
// Product name
|
||||
Title string `json:"title"`
|
||||
|
||||
// Product description
|
||||
Description string `json:"description"`
|
||||
|
||||
// Unique bot deep-linking parameter that can be used to generate this
|
||||
// invoice
|
||||
StartParameter string `json:"start_parameter"`
|
||||
|
||||
// Three-letter ISO 4217 currency code
|
||||
Currency string `json:"currency"`
|
||||
|
||||
// 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
|
||||
// digits past the decimal point for each currency (2 for the majority
|
||||
// of currencies).
|
||||
TotalAmount int `json:"total_amount"`
|
||||
}
|
||||
|
||||
// ShippingAddress represents a shipping address.
|
||||
ShippingAddress struct {
|
||||
// ISO 3166-1 alpha-2 country code
|
||||
CountryCode string `json:"country_code"`
|
||||
|
||||
// State, if applicable
|
||||
State string `json:"state"`
|
||||
|
||||
// City
|
||||
City string `json:"city"`
|
||||
|
||||
// First line for the address
|
||||
StreetLine1 string `json:"street_line1"`
|
||||
|
||||
// Second line for the address
|
||||
StreetLine2 string `json:"street_line2"`
|
||||
|
||||
// Address post code
|
||||
PostCode string `json:"post_code"`
|
||||
}
|
||||
|
||||
// OrderInfo represents information about an order.
|
||||
OrderInfo struct {
|
||||
// User name
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
// User's phone number
|
||||
PhoneNumber string `json:"phone_number,omitempty"`
|
||||
|
||||
// User email
|
||||
Email string `json:"email,omitempty"`
|
||||
|
||||
// User shipping address
|
||||
ShippingAddress *ShippingAddress `json:"shipping_address,omitempty"`
|
||||
}
|
||||
|
||||
// ShippingOption represents one shipping option.
|
||||
ShippingOption struct {
|
||||
// Shipping option identifier
|
||||
ID string `json:"id"`
|
||||
|
||||
// Option title
|
||||
Title string `json:"title"`
|
||||
|
||||
// List of price portions
|
||||
Prices []*LabeledPrice `json:"prices"`
|
||||
}
|
||||
|
||||
// SuccessfulPayment contains basic information about a successful payment.
|
||||
SuccessfulPayment struct {
|
||||
// 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
|
||||
// digits past the decimal point for each currency (2 for the majority
|
||||
// of currencies).
|
||||
TotalAmount int `json:"total_amount"`
|
||||
|
||||
// Order info provided by the user
|
||||
OrderInfo *OrderInfo `json:"order_info,omitempty"`
|
||||
}
|
||||
|
||||
// ShippingQuery contains information about an incoming shipping query.
|
||||
ShippingQuery struct {
|
||||
// Unique query identifier
|
||||
ID string `json:"id"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// PreCheckoutQuery contains information about an incoming pre-checkout query.
|
||||
PreCheckoutQuery struct {
|
||||
// Unique query identifier
|
||||
ID string `json:"id"`
|
||||
|
||||
// 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
|
||||
// digits past the decimal point for each currency (2 for the majority of
|
||||
// currencies).
|
||||
TotalAmount int `json:"total_amount"`
|
||||
|
||||
// Order info provided by the user
|
||||
OrderInfo *OrderInfo `json:"order_info,omitempty"`
|
||||
}
|
||||
|
||||
// SendInvoiceParameters represents data for SendInvoice method.
|
||||
SendInvoice struct {
|
||||
// Unique identifier for the target private chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Product name, 1-32 characters
|
||||
Title string `json:"title"`
|
||||
|
||||
// Product description, 1-255 characters
|
||||
Description string `json:"description"`
|
||||
|
||||
// Bot-defined invoice payload, 1-128 bytes. This will not be displayed to
|
||||
// the user, use for your internal processes.
|
||||
Payload string `json:"payload"`
|
||||
|
||||
// Payments provider token, obtained via Botfather
|
||||
ProviderToken string `json:"provider_token"`
|
||||
|
||||
// Unique deep-linking parameter that can be used to generate this invoice
|
||||
// when used as a start parameter
|
||||
StartParameter string `json:"start_parameter"`
|
||||
|
||||
// Three-letter ISO 4217 currency code, see more on currencies
|
||||
Currency string `json:"currency"`
|
||||
|
||||
// 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.
|
||||
ProviderData string `json:"provider_data,omitempty"`
|
||||
|
||||
// URL of the product photo for the invoice. Can be a photo of the goods or a
|
||||
// marketing image for a service. People like it better when they see what
|
||||
// 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"`
|
||||
|
||||
// Photo width
|
||||
PhotoWidth int `json:"photo_width,omitempty"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Pass True, if you require the user's phone number to complete the order
|
||||
NeedPhoneNumber bool `json:"need_phone_number,omitempty"`
|
||||
|
||||
// Pass True, if you require the user's email to complete the order
|
||||
NeedEmail bool `json:"need_email,omitempty"`
|
||||
|
||||
// Pass True, if you require the user's shipping address to complete the
|
||||
// order
|
||||
NeedShippingAddress bool `json:"need_shipping_address,omitempty"`
|
||||
|
||||
// Pass True, if the final price depends on the shipping method
|
||||
IsFlexible bool `json:"is_flexible,omitempty"`
|
||||
|
||||
// Sends the message silently. Users will receive a notification with no
|
||||
// sound.
|
||||
DisableNotification bool `json:"disable_notification,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.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// AnswerShippingQueryParameters represents data for AnswerShippingQuery method.
|
||||
AnswerShippingQuery 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)
|
||||
Ok bool `json:"ok"`
|
||||
|
||||
// Required if ok is True. A JSON-serialized array of available shipping
|
||||
// options.
|
||||
ShippingOptions []*ShippingOption `json:"shipping_options,omitempty"`
|
||||
}
|
||||
|
||||
// AnswerPreCheckoutQueryParameters represents data for AnswerPreCheckoutQuery
|
||||
// method.
|
||||
AnswerPreCheckoutQuery struct {
|
||||
// Unique identifier for the query to be answered
|
||||
PreCheckoutQueryID string `json:"pre_checkout_query_id"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
)
|
||||
|
||||
// SendInvoice send invoices. On success, the sent Message is returned.
|
||||
func (b *Bot) SendInvoice(p SendInvoice) (*Message, error) {
|
||||
src, err := b.Do(MethodSendInvoice, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AnswerShippingQuery reply to shipping queries.
|
||||
//
|
||||
// If you sent an invoice requesting a shipping address and the parameter
|
||||
// is_flexible was specified, the Bot API will send an Update with a
|
||||
// shipping_query field to the b. On success, True is returned.
|
||||
func (b *Bot) AnswerShippingQuery(p AnswerShippingQuery) (bool, error) {
|
||||
src, err := b.Do(MethodAnswerShippingQuery, p)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AnswerPreCheckoutQuery respond to such pre-checkout queries.
|
||||
//
|
||||
// Once the user has confirmed their payment and shipping details, the Bot API
|
||||
// sends the final confirmation in the form of an Update with the field
|
||||
// pre_checkout_query. Use this method to respond to such pre-checkout queries.
|
||||
// On success, True is returned.
|
||||
//
|
||||
// Note: The Bot API must receive an answer within 10 seconds after the
|
||||
// pre-checkout query was sent.
|
||||
func (b *Bot) AnswerPreCheckoutQuery(p AnswerShippingQuery) (bool, error) {
|
||||
src, err := b.Do(MethodAnswerPreCheckoutQuery, p)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
34
pin.go
34
pin.go
|
@ -1,34 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// PinChatMessageParameters represents data for PinChatMessage method.
|
||||
type PinChatMessageParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Identifier of a message to pin
|
||||
MessageID int `json:"message_id"`
|
||||
|
||||
// Pass true, if it is not necessary to send a notification to all chat
|
||||
// members about the new pinned message. Notifications are always
|
||||
// disabled in channels.
|
||||
DisableNotification bool `json:"disable_notification"`
|
||||
}
|
||||
|
||||
// PinChatMessage pin a message in a supergroup or a channel. The bot must be an administrator in the
|
||||
// chat for this to work and must have the 'can_pin_messages' admin right in the supergroup or
|
||||
// 'can_edit_messages' admin right in the channel. Returns True on success.
|
||||
func (bot *Bot) PinChatMessage(params *PinChatMessageParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodPinChatMessage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
35
restrict.go
35
restrict.go
|
@ -1,35 +0,0 @@
|
|||
package telegram
|
||||
|
||||
type RestrictChatMemberParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Unique identifier of the target user
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// New user permissions
|
||||
Permissions ChatPermissions `json:"permissions"`
|
||||
|
||||
// Date when restrictions will be lifted for the user, unix time. If user is restricted for more than 366 days
|
||||
// or less than 30 seconds from the current time, they are considered to be restricted forever
|
||||
UntilDate int64 `json:"until_date,omitempty"`
|
||||
}
|
||||
|
||||
// restrict a user in a supergroup. The bot must be an administrator in the supergroup for this to work and must have
|
||||
// the appropriate admin rights. Pass True for all permissions to lift restrictions from a user. Returns True on
|
||||
// success.
|
||||
func (b *Bot) RestrictChatMember(params RestrictChatMemberParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(¶ms)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodRestrictChatMember)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
796
send.go
796
send.go
|
@ -1,796 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type (
|
||||
// SendAnimationParameters represents data for SendAnimation method.
|
||||
SendAnimationParameters struct {
|
||||
// Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Animation to send. Pass a file_id as String to send an animation that exists on the Telegram servers (recommended), pass an HTTP URL as a String for Telegram to get an animation from the Internet, or upload a new animation using multipart/form-data. More info on Sending Files »
|
||||
Animation InputFile `json:"animation"`
|
||||
|
||||
// Duration of sent animation in seconds
|
||||
Duration int `json:"duration,omitempty"`
|
||||
|
||||
// Animation width
|
||||
Width int `json:"width,omitempty"`
|
||||
|
||||
// Animation height
|
||||
Height int `json:"height,omitempty"`
|
||||
|
||||
// Thumbnail of the file sent. The thumbnail should be in JPEG format and less than 200 kB in size. A thumbnail‘s width and height should not exceed 90. Ignored if the file is not uploaded using multipart/form-data. Thumbnails can’t be reused and can be only uploaded as a new file, so you can pass “attach://<file_attach_name>” if the thumbnail was uploaded using multipart/form-data under <file_attach_name>. More info on Sending Files »
|
||||
Thumb InputFile `json:"thumb,omitempty"`
|
||||
|
||||
// Animation caption (may also be used when resending animation by file_id), 0-200 characters
|
||||
Caption string `json:"caption,omitempty"`
|
||||
|
||||
// Send Markdown or HTML, if you want Telegram apps to show bold, italic, fixed-width text or inline URLs in the media caption.
|
||||
ParseMode string `json:"parse_mode,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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
||||
ReplyMarkup interface{} `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendChatActionParameters represents data for SendChatAction method.
|
||||
SendChatActionParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Type of action to broadcast
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
// SendContactParameters represents data for SendContact method.
|
||||
SendContactParameters struct {
|
||||
// Unique identifier for the target private chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Contact's phone number
|
||||
PhoneNumber string `json:"phone_number"`
|
||||
|
||||
// Contact's first name
|
||||
FirstName string `json:"first_name"`
|
||||
|
||||
// Contact's last name
|
||||
LastName string `json:"last_name"`
|
||||
|
||||
// Additional data about the contact in the form of a vCard, 0-2048 bytes
|
||||
VCard string `json:"vcard,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.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendDocumentParameters represents data for SendDocument method.
|
||||
SendDocumentParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// File to send. Pass a file_id as String to send a file that exists on the Telegram servers
|
||||
// (recommended), pass an HTTP URL as a String for Telegram to get a file from the Internet, or
|
||||
// upload a new one using multipart/form-data.
|
||||
Document InputFile `json:"document"`
|
||||
|
||||
// Document caption (may also be used when resending documents by file_id), 0-200 characters
|
||||
Caption string `json:"caption,omitempty"`
|
||||
|
||||
// Send Markdown or HTML, if you want Telegram apps to show bold, italic,
|
||||
// fixed-width text or inline URLs in the media caption.
|
||||
ParseMode string `json:"parse_mode,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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an inline keyboard, custom reply
|
||||
// keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
||||
ReplyMarkup interface{} `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendInvoiceParameters represents data for SendInvoice method.
|
||||
SendInvoiceParameters struct {
|
||||
// Unique identifier for the target private chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Product name, 1-32 characters
|
||||
Title string `json:"title"`
|
||||
|
||||
// Product description, 1-255 characters
|
||||
Description string `json:"description"`
|
||||
|
||||
// Bot-defined invoice payload, 1-128 bytes. This will not be displayed to
|
||||
// the user, use for your internal processes.
|
||||
Payload string `json:"payload"`
|
||||
|
||||
// Payments provider token, obtained via Botfather
|
||||
ProviderToken string `json:"provider_token"`
|
||||
|
||||
// Unique deep-linking parameter that can be used to generate this invoice
|
||||
// when used as a start parameter
|
||||
StartParameter string `json:"start_parameter"`
|
||||
|
||||
// Three-letter ISO 4217 currency code, see more on currencies
|
||||
Currency string `json:"currency"`
|
||||
|
||||
// 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.
|
||||
ProviderData string `json:"provider_data,omitempty"`
|
||||
|
||||
// URL of the product photo for the invoice. Can be a photo of the goods or a
|
||||
// marketing image for a service. People like it better when they see what
|
||||
// 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"`
|
||||
|
||||
// Photo width
|
||||
PhotoWidth int `json:"photo_width,omitempty"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Pass True, if you require the user's phone number to complete the order
|
||||
NeedPhoneNumber bool `json:"need_phone_number,omitempty"`
|
||||
|
||||
// Pass True, if you require the user's email to complete the order
|
||||
NeedEmail bool `json:"need_email,omitempty"`
|
||||
|
||||
// Pass True, if you require the user's shipping address to complete the
|
||||
// order
|
||||
NeedShippingAddress bool `json:"need_shipping_address,omitempty"`
|
||||
|
||||
// Pass True, if the final price depends on the shipping method
|
||||
IsFlexible bool `json:"is_flexible,omitempty"`
|
||||
|
||||
// Sends the message silently. Users will receive a notification with no
|
||||
// sound.
|
||||
DisableNotification bool `json:"disable_notification,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.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendLocationParameters represents data for SendLocation method.
|
||||
SendLocationParameters struct {
|
||||
// Unique identifier for the target private chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Latitude of the location
|
||||
Latitude float32 `json:"latitude"`
|
||||
|
||||
// Longitude of the location
|
||||
Longitude float32 `json:"longitude"`
|
||||
|
||||
// Period in seconds for which the location will be updated (see Live
|
||||
// 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"`
|
||||
|
||||
// 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.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendMediaGroupParameters represents data for SendMediaGroup method.
|
||||
SendMediaGroupParameters struct {
|
||||
// Unique identifier for the target chat.
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// A JSON-serialized array describing photos and videos to be sent, must
|
||||
// include 2–10 items
|
||||
Media []interface{} `json:"media"`
|
||||
|
||||
// Sends the messages silently. Users will receive a notification with no
|
||||
// sound.
|
||||
DisableNotification bool `json:"disable_notification,omitempty"`
|
||||
|
||||
// If the messages are a reply, ID of the original message
|
||||
ReplyToMessageID int `json:"reply_to_message_id,omitempty"`
|
||||
}
|
||||
|
||||
// SendMessageParameters represents data for SendMessage method.
|
||||
SendMessageParameters struct {
|
||||
// Unique identifier for the target chat or username of the target channel
|
||||
// (in the format @channelusername)
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Text of the message to be sent
|
||||
Text string `json:"text"`
|
||||
|
||||
// Send Markdown or HTML, if you want Telegram apps to show bold, italic,
|
||||
// fixed-width text or inline URLs in your bot's message.
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
|
||||
// Disables link previews for links in this message
|
||||
DisableWebPagePreview bool `json:"disable_web_page_preview,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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an inline
|
||||
// keyboard, custom reply keyboard, instructions to remove reply keyboard or
|
||||
// to force a reply from the user.
|
||||
ReplyMarkup interface{} `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendPhotoParameters represents data for SendPhoto method.
|
||||
SendPhotoParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Photo to send. Pass a file_id as String to send a photo that exists on the
|
||||
// Telegram servers (recommended), pass an HTTP URL as a String for Telegram
|
||||
// to get a photo from the Internet, or upload a new photo using
|
||||
// multipart/form-data.
|
||||
Photo InputFile `json:"photo"`
|
||||
|
||||
// Photo caption (may also be used when resending photos by file_id), 0-200
|
||||
// characters
|
||||
Caption string `json:"caption,omitempty"`
|
||||
|
||||
// Send Markdown or HTML, if you want Telegram apps to show bold, italic,
|
||||
// fixed-width text or inline URLs in the media caption.
|
||||
ParseMode string `json:"parse_mode,omitempty"`
|
||||
|
||||
// Disables link previews for links in this message
|
||||
DisableWebPagePreview bool `json:"disable_web_page_preview,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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an inline
|
||||
// keyboard, custom reply keyboard, instructions to remove reply keyboard or
|
||||
// to force a reply from the user.
|
||||
ReplyMarkup interface{} `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
SendPollConfig struct {
|
||||
// Unique identifier for the target chat. A native poll can't be sent to a private chat.
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Poll question, 1-255 characters
|
||||
Question string `json:"question"`
|
||||
|
||||
// List of answer options, 2-10 strings 1-100 characters each
|
||||
Options []string `json:"options"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard,
|
||||
// instructions to remove reply keyboard or to force a reply from the user.
|
||||
ReplyMarkup interface{} `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendVenueParameters represents data for SendVenue method.
|
||||
SendVenueParameters struct {
|
||||
// Unique identifier for the target private chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Latitude of the venue
|
||||
Latitude float32 `json:"latitude"`
|
||||
|
||||
// Longitude of the venue
|
||||
Longitude float32 `json:"longitude"`
|
||||
|
||||
// Name of the venue
|
||||
Title string `json:"title"`
|
||||
|
||||
// Address of the venue
|
||||
Address string `json:"address"`
|
||||
|
||||
// Foursquare identifier of the venue
|
||||
FoursquareID string `json:"foursquare_id,omitempty"`
|
||||
|
||||
// Foursquare type of the venue, if known. (For example,
|
||||
// "arts_entertainment/default", "arts_entertainment/aquarium" or
|
||||
// "food/icecream".)
|
||||
FoursquareType string `json:"foursquare_type,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.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendGameParameters represents data for SendGame method.
|
||||
SendGameParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Short name of the game, serves as the unique identifier for the game. Set
|
||||
// up your games via Botfather.
|
||||
GameShortName string `json:"game_short_name"`
|
||||
|
||||
// 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 ‘Play
|
||||
// game_title’ button will be shown. If not empty, the first button must
|
||||
// launch the game.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// SendStickerParameters represents data for SetSticker method.
|
||||
SendStickerParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Sticker to send
|
||||
Sticker interface{} `json:"sticker"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an
|
||||
// inline keyboard, custom reply keyboard, instructions to remove
|
||||
// reply keyboard or to force a reply from the user.
|
||||
ReplyMarkup interface{} `json:"reply_markup,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewAnimation creates SendAnimationParameters only with required parameters.
|
||||
func NewAnimation(chatID int64, animation interface{}) *SendAnimationParameters {
|
||||
return &SendAnimationParameters{
|
||||
ChatID: chatID,
|
||||
Animation: animation,
|
||||
}
|
||||
}
|
||||
|
||||
// NewContact creates SendContactParameters only with required parameters.
|
||||
func NewContact(chatID int64, phoneNumber, firstName string) *SendContactParameters {
|
||||
return &SendContactParameters{
|
||||
ChatID: chatID,
|
||||
PhoneNumber: phoneNumber,
|
||||
FirstName: firstName,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDocument creates SendDocumentParameters only with required parameters.
|
||||
func NewDocument(chatID int64, document interface{}) *SendDocumentParameters {
|
||||
return &SendDocumentParameters{
|
||||
ChatID: chatID,
|
||||
Document: document,
|
||||
}
|
||||
}
|
||||
|
||||
// NewInvoice creates SendInvoiceParameters only with required parameters.
|
||||
func NewInvoice(chatID int64, title, description, payload, providerToken, startParameter, currency string, prices ...LabeledPrice) *SendInvoiceParameters {
|
||||
return &SendInvoiceParameters{
|
||||
ChatID: chatID,
|
||||
Title: title,
|
||||
Description: description,
|
||||
Payload: payload,
|
||||
ProviderToken: providerToken,
|
||||
StartParameter: startParameter,
|
||||
Currency: currency,
|
||||
Prices: prices,
|
||||
}
|
||||
}
|
||||
|
||||
// NewLocation creates SendLocationParameters only with required parameters.
|
||||
func NewLocation(chatID int64, latitude, longitude float32) *SendLocationParameters {
|
||||
return &SendLocationParameters{
|
||||
ChatID: chatID,
|
||||
Latitude: latitude,
|
||||
Longitude: longitude,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMediaGroup creates SendMediaGroupParameters only with required parameters.
|
||||
func NewMediaGroup(chatID int64, media ...interface{}) *SendMediaGroupParameters {
|
||||
return &SendMediaGroupParameters{
|
||||
ChatID: chatID,
|
||||
Media: media,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMessage creates SendMessageParameters only with required parameters.
|
||||
func NewMessage(chatID int64, text string) *SendMessageParameters {
|
||||
return &SendMessageParameters{
|
||||
ChatID: chatID,
|
||||
Text: text,
|
||||
}
|
||||
}
|
||||
|
||||
// NewPhoto creates SendPhotoParameters only with required parameters.
|
||||
func NewPhoto(chatID int64, photo interface{}) *SendPhotoParameters {
|
||||
return &SendPhotoParameters{
|
||||
ChatID: chatID,
|
||||
Photo: photo,
|
||||
}
|
||||
}
|
||||
|
||||
func NewPoll(chatID int64, question string, options ...string) SendPollConfig {
|
||||
return SendPollConfig{
|
||||
ChatID: chatID,
|
||||
Question: question,
|
||||
Options: options,
|
||||
}
|
||||
}
|
||||
|
||||
// NewVenue creates SendVenueParameters only with required parameters.
|
||||
func NewVenue(chatID int64, latitude, longitude float32, title, address string) *SendVenueParameters {
|
||||
return &SendVenueParameters{
|
||||
ChatID: chatID,
|
||||
Latitude: latitude,
|
||||
Longitude: longitude,
|
||||
Title: title,
|
||||
Address: address,
|
||||
}
|
||||
}
|
||||
|
||||
// NewGame creates SendGameParameters only with required parameters.
|
||||
func NewGame(chatID int64, gameShortName string) *SendGameParameters {
|
||||
return &SendGameParameters{
|
||||
ChatID: chatID,
|
||||
GameShortName: gameShortName,
|
||||
}
|
||||
}
|
||||
|
||||
// SendAnimation send animation files (GIF or H.264/MPEG-4 AVC video without
|
||||
// sound). On success, the sent Message is returned. Bots can currently send
|
||||
// animation files of up to 50 MB in size, this limit may be changed in the
|
||||
// future.
|
||||
func (bot *Bot) SendAnimation(params *SendAnimationParameters) (*Message, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Add("chat_id", strconv.FormatInt(params.ChatID, 10))
|
||||
|
||||
if params.Caption != "" {
|
||||
args.Add("caption", params.Caption)
|
||||
}
|
||||
|
||||
if params.ReplyMarkup != nil {
|
||||
dst, err := parser.Marshal(params.ReplyMarkup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args.Add("reply_markup", string(dst))
|
||||
}
|
||||
|
||||
if params.ReplyToMessageID != 0 {
|
||||
args.Add("reply_to_message_id", strconv.Itoa(params.ReplyToMessageID))
|
||||
}
|
||||
|
||||
args.Add("disable_notification", strconv.FormatBool(params.DisableNotification))
|
||||
|
||||
resp, err := bot.Upload(MethodSendAnimation, "animation", "", params.Animation, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result Message
|
||||
err = parser.Unmarshal(resp.Result, &result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
// SendChatAction tell the user that something is happening on the bot's side.
|
||||
// The status is set for 5 seconds or less (when a message arrives from your bot,
|
||||
// Telegram clients clear its typing status). Returns True on success.
|
||||
//
|
||||
// We only recommend using this method when a response from the bot will take a
|
||||
// noticeable amount of time to arrive.
|
||||
func (bot *Bot) SendChatAction(chatID int64, action string) (bool, error) {
|
||||
dst, err := parser.Marshal(&SendChatActionParameters{
|
||||
ChatID: chatID,
|
||||
Action: action,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendChatAction)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SendContact send phone contacts. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendContact(params *SendContactParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(*params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendContact)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendDocument send general files. On success, the sent Message is returned. Bots can currently send
|
||||
// files of any type of up to 50 MB in size, this limit may be changed in the future.
|
||||
func (bot *Bot) SendDocument(params *SendDocumentParameters) (*Message, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Add("chat_id", strconv.FormatInt(params.ChatID, 10))
|
||||
|
||||
if params.Caption != "" {
|
||||
args.Add("caption", params.Caption)
|
||||
}
|
||||
|
||||
if params.ReplyMarkup != nil {
|
||||
dst, err := parser.Marshal(params.ReplyMarkup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args.Add("reply_markup", string(dst))
|
||||
}
|
||||
|
||||
if params.ReplyToMessageID != 0 {
|
||||
args.Add("reply_to_message_id", strconv.Itoa(params.ReplyToMessageID))
|
||||
}
|
||||
|
||||
args.Add("disable_notification", strconv.FormatBool(params.DisableNotification))
|
||||
|
||||
resp, err := bot.Upload(MethodSendDocument, "document", "", params.Document, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result Message
|
||||
err = parser.Unmarshal(resp.Result, &result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
// SendInvoice send invoices. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendInvoice(params *SendInvoiceParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendInvoice)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendLocation send point on the map. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendLocation(params *SendLocationParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendMediaGroup send a group of photos or videos as an album. On success, an array of the sent
|
||||
// Messages is returned.
|
||||
func (bot *Bot) SendMediaGroup(params *SendMediaGroupParameters) ([]Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendMediaGroup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var group []Message
|
||||
err = parser.Unmarshal(resp.Result, &group)
|
||||
return group, err
|
||||
}
|
||||
|
||||
// SendMessage send text messages. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendMessage(params *SendMessageParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendMessage)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendPhoto send photos. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendPhoto(params *SendPhotoParameters) (*Message, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Add("chat_id", strconv.FormatInt(params.ChatID, 10))
|
||||
|
||||
if params.Caption != "" {
|
||||
args.Add("caption", params.Caption)
|
||||
}
|
||||
|
||||
if params.ReplyMarkup != nil {
|
||||
dst, err := parser.Marshal(params.ReplyMarkup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
args.Add("reply_markup", string(dst))
|
||||
}
|
||||
|
||||
if params.ReplyToMessageID != 0 {
|
||||
args.Add("reply_to_message_id", strconv.Itoa(params.ReplyToMessageID))
|
||||
}
|
||||
|
||||
args.Add("disable_notification", strconv.FormatBool(params.DisableNotification))
|
||||
|
||||
resp, err := bot.Upload(MethodSendPhoto, "photo", "", params.Photo, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result Message
|
||||
err = parser.Unmarshal(resp.Result, &result)
|
||||
return &result, err
|
||||
}
|
||||
|
||||
// SendPoll send a native poll. A native poll can't be sent to a private chat. On success, the sent Message is
|
||||
// returned.
|
||||
func (b *Bot) SendPoll(params SendPollConfig) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodSendPoll)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendVenue send information about a venue. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendVenue(params *SendVenueParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendVenue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendGame send a game. On success, the sent Message is returned.
|
||||
func (bot *Bot) SendGame(params *SendGameParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSendGame)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SendSticker send .webp stickers. On success, the sent Message is returned.
|
||||
func (b *Bot) SendSticker(params *SendStickerParameters) (*Message, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Set("chat_id", strconv.FormatInt(params.ChatID, 10))
|
||||
args.Set("disable_notification", strconv.FormatBool(params.DisableNotification))
|
||||
if params.ReplyToMessageID > 0 {
|
||||
args.SetUint("reply_to_message_id", params.ReplyToMessageID)
|
||||
}
|
||||
if params.ReplyMarkup != nil {
|
||||
rm, err := parser.Marshal(params.ReplyMarkup)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
args.SetBytesV("reply_markup", rm)
|
||||
}
|
||||
|
||||
resp, err := b.Upload(MethodSendSticker, TypeSticker, "sticker", params.Sticker, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result Message
|
||||
err = parser.Unmarshal(resp.Result, &result)
|
||||
return &result, err
|
||||
}
|
398
set.go
398
set.go
|
@ -1,398 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type (
|
||||
// SetChatDescriptionParameters represents data for SetChatDescription method.
|
||||
SetChatDescriptionParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// New chat description, 0-255 characters
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
// SetChatPhotoParameters represents data for SetChatPhoto method.
|
||||
SetChatPhotoParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// New chat photo, uploaded using multipart/form-data
|
||||
ChatPhoto interface{} `json:"chat_photo"`
|
||||
}
|
||||
|
||||
// SetChatStickerSetParameters represents data for SetChatStickerSet method.
|
||||
SetChatStickerSetParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Name of the sticker set to be set as the group sticker set
|
||||
StickerSetName string `json:"sticker_set_name"`
|
||||
}
|
||||
|
||||
// SetChatTitleParameters represents data for SetChatTitle method.
|
||||
SetChatTitleParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// New chat title, 1-255 characters
|
||||
Title string `json:"title"`
|
||||
}
|
||||
|
||||
SetPassportDataErrorsParameters struct {
|
||||
// User identifier
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// A JSON-serialized array describing the errors
|
||||
Errors []PassportElementError `json:"errors"`
|
||||
}
|
||||
|
||||
// SetWebhookParameters represents data for SetWebhook method.
|
||||
SetWebhookParameters struct {
|
||||
// HTTPS url to send updates to. Use an empty string to remove webhook
|
||||
// integration
|
||||
URL string `json:"url"`
|
||||
|
||||
// Upload your public key certificate so that the root certificate in use can
|
||||
// be checked. See our self-signed guide for details.
|
||||
Certificate InputFile `json:"certificate,omitempty"`
|
||||
|
||||
// Maximum allowed number of simultaneous HTTPS connections to the webhook
|
||||
// for update delivery, 1-100. Defaults to 40. Use lower values to limit the
|
||||
// load on your bot‘s server, and higher values to increase your bot’s
|
||||
// throughput.
|
||||
MaxConnections int `json:"max_connections,omitempty"`
|
||||
|
||||
// List the types of updates you want your bot to receive. For example,
|
||||
// specify [“message”, “edited_channel_post”, “callback_query”] to only
|
||||
// receive updates of these types. See Update for a complete list of
|
||||
// available update types. Specify an empty list to receive all updates
|
||||
// regardless of type (default). If not specified, the previous setting will
|
||||
// be used.
|
||||
//
|
||||
// Please note that this parameter doesn't affect updates created before the
|
||||
// call to the setWebhook, so unwanted updates may be received for a short
|
||||
// period of time.
|
||||
AllowedUpdates []string `json:"allowed_updates,omitempty"`
|
||||
}
|
||||
|
||||
// SetGameScoreParameters represents data for SetGameScore method.
|
||||
SetGameScoreParameters struct {
|
||||
// User identifier
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Pass True, if the game message should not be automatically edited to
|
||||
// include the current scoreboard
|
||||
DisableEditMessage bool `json:"disable_edit_message,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"`
|
||||
}
|
||||
|
||||
// SetStickerPositionInSetParameters represents data for SetStickerPositionInSet
|
||||
// method.
|
||||
SetStickerPositionInSetParameters struct {
|
||||
// File identifier of the sticker
|
||||
Sticker string `json:"sticker"`
|
||||
|
||||
// New sticker position in the set, zero-based
|
||||
Position int `json:"position"`
|
||||
}
|
||||
|
||||
// SetChatPermissionsParameters represents data for SetChatPermissions method.
|
||||
SetChatPermissionsParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// New default chat permissions
|
||||
Permissions ChatPermissions `json:"permissions"`
|
||||
}
|
||||
|
||||
SetChatAdministratorCustomTitle struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Unique identifier of the target user
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// New custom title for the administrator; 0-16 characters, emoji are not allowed
|
||||
CustomTitle string `json:"custom_title"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewWebhook creates new SetWebhookParameters only with required parameters.
|
||||
func NewWebhook(url string, file interface{}) *SetWebhookParameters {
|
||||
return &SetWebhookParameters{
|
||||
URL: url,
|
||||
Certificate: file,
|
||||
}
|
||||
}
|
||||
|
||||
// NewGameScore creates SetGameScoreParameters only with required parameters.
|
||||
func NewGameScore(userID, score int) *SetGameScoreParameters {
|
||||
return &SetGameScoreParameters{
|
||||
UserID: userID,
|
||||
Score: score,
|
||||
}
|
||||
}
|
||||
|
||||
// SetChatDescription change the description of a supergroup or a channel. The
|
||||
// bot must be an administrator in the chat for this to work and must have the
|
||||
// appropriate admin rights. Returns True on success.
|
||||
func (bot *Bot) SetChatDescription(chatID int64, description string) (bool, error) {
|
||||
dst, err := parser.Marshal(&SetChatDescriptionParameters{
|
||||
ChatID: chatID,
|
||||
Description: description,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSetChatDescription)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetChatPhoto set a new profile photo for the chat. Photos can't be changed for private chats. The
|
||||
// bot must be an administrator in the chat for this to work and must have the appropriate admin
|
||||
// rights. Returns True on success.
|
||||
//
|
||||
// Note: In regular groups (non-supergroups), this method will only work if the 'All Members Are
|
||||
// Admins' setting is off in the target group.
|
||||
func (bot *Bot) SetChatPhoto(chatID int64, chatPhoto interface{}) (bool, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Add("chat_id", strconv.FormatInt(chatID, 10))
|
||||
|
||||
resp, err := bot.Upload(MethodSetChatPhoto, TypePhoto, "chat_photo", chatPhoto, args)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetChatStickerSet set a new group sticker set for a supergroup. The bot must be an administrator
|
||||
// in the chat for this to work and must have the appropriate admin rights. Use the field
|
||||
// can_set_sticker_set optionally returned in getChat requests to check if the bot can use this
|
||||
// method. Returns True on success.
|
||||
func (bot *Bot) SetChatStickerSet(chatID int64, stickerSetName string) (bool, error) {
|
||||
dst, err := parser.Marshal(&SetChatStickerSetParameters{
|
||||
ChatID: chatID,
|
||||
StickerSetName: stickerSetName,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSetChatStickerSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetChatTitle change the title of a chat. Titles can't be changed for private
|
||||
// chats. The bot must be an administrator in the chat for this to work and must
|
||||
// have the appropriate admin rights. Returns True on success.
|
||||
//
|
||||
// Note: In regular groups (non-supergroups), this method will only work if the
|
||||
// 'All Members Are Admins' setting is off in the target group.
|
||||
func (bot *Bot) SetChatTitle(chatID int64, title string) (bool, error) {
|
||||
dst, err := parser.Marshal(&SetChatTitleParameters{
|
||||
ChatID: chatID,
|
||||
Title: title,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSetChatTitle)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetPassportDataErrors informs a user that some of the Telegram Passport
|
||||
// elements they provided contains errors. The user will not be able to re-submit
|
||||
// their Passport to you until the errors are fixed (the contents of the field
|
||||
// for which you returned the error must change). Returns True on success.
|
||||
//
|
||||
// Use this if the data submitted by the user doesn't satisfy the standards your
|
||||
// service requires for any reason. For example, if a birthday date seems
|
||||
// invalid, a submitted document is blurry, a scan shows evidence of tampering,
|
||||
// etc. Supply some details in the error message to make sure the user knows how
|
||||
// to correct the issues.
|
||||
func (b *Bot) SetPassportDataErrors(userId int, errors []PassportElementError) (bool, error) {
|
||||
dst, err := parser.Marshal(&SetPassportDataErrorsParameters{
|
||||
UserID: userId,
|
||||
Errors: errors,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodSetPassportDataErrors)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetWebhook specify a url and receive incoming updates via an outgoing webhook.
|
||||
// Whenever there is an update for the bot, we will send an HTTPS POST request to
|
||||
// the specified url, containing a JSON-serialized Update. In case of an
|
||||
// unsuccessful request, we will give up after a reasonable amount of attempts.
|
||||
// Returns true.
|
||||
//
|
||||
// If you'd like to make sure that the Webhook request comes from Telegram, we
|
||||
// recommend using a secret path in the URL, e.g. https://www.example.com/<token>.
|
||||
// Since nobody else knows your bot‘s token, you can be pretty sure it’s us.
|
||||
func (bot *Bot) SetWebhook(params *SetWebhookParameters) (bool, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.Add("url", params.URL)
|
||||
|
||||
if len(params.AllowedUpdates) > 0 {
|
||||
args.Add("allowed_updates", strings.Join(params.AllowedUpdates, ","))
|
||||
}
|
||||
if params.MaxConnections > 0 &&
|
||||
params.MaxConnections <= 100 {
|
||||
args.Add("max_connections", strconv.Itoa(params.MaxConnections))
|
||||
}
|
||||
|
||||
var resp *Response
|
||||
var err error
|
||||
if params.Certificate != nil {
|
||||
resp, err = bot.Upload(MethodSetWebhook, "certificate", "cert.pem", params.Certificate, args)
|
||||
} else {
|
||||
var dst []byte
|
||||
dst, err = parser.Marshal(params)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err = bot.request(dst, MethodSetWebhook)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetGameScore set the score of the specified user in a game. On success, if the
|
||||
// message was sent by the bot, returns the edited Message, otherwise returns
|
||||
// True. Returns an error, if the new score is not greater than the user's
|
||||
// current score in the chat and force is False.
|
||||
func (bot *Bot) SetGameScore(params *SetGameScoreParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodSetGameScore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// SetStickerPositionInSet move a sticker in a set created by the bot to a
|
||||
// specific position. Returns True on success.
|
||||
func (b *Bot) SetStickerPositionInSet(sticker string, position int) (bool, error) {
|
||||
dst, err := parser.Marshal(&SetStickerPositionInSetParameters{
|
||||
Sticker: sticker,
|
||||
Position: position,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodSetStickerPositionInSet)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetChatPermissions set default chat permissions for all members. The bot must be an administrator in the group or a
|
||||
// supergroup for this to work and must have the can_restrict_members admin rights. Returns True on success.
|
||||
func (b *Bot) SetChatPermissions(params SetChatPermissionsParameters) (bool, error) {
|
||||
dst, err := parser.Marshal(¶ms)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodSetChatPermissions)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// SetChatAdministratorCustomTitle method to set a custom title for an administrator in a supergroup promoted by the bot. Returns True on success.
|
||||
func (b *Bot) SetChatAdministratorCustomTitle(params SetChatAdministratorCustomTitle) (bool, error) {
|
||||
dst, err := parser.Marshal(¶ms)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodSetChatAdministratorCustomTitle)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
package telegram
|
||||
|
||||
import "strconv"
|
||||
|
||||
type (
|
||||
// Sticker represents a sticker.
|
||||
Sticker struct {
|
||||
// Identifier for this file, which can be used to download or reuse the file
|
||||
FileID string `json:"file_id"`
|
||||
|
||||
// Unique identifier for this file, which is supposed to be the same over time and for different bots. Can't be used to download or reuse the file.
|
||||
FileUniqueID string `json:"file_unique_id"`
|
||||
|
||||
// Sticker width
|
||||
Width int `json:"width"`
|
||||
|
||||
// Sticker height
|
||||
Height int `json:"height"`
|
||||
|
||||
// true, if the sticker is animated
|
||||
IsAnimated bool `json:"is_animated"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// File size
|
||||
FileSize int `json:"file_size,omitempty"`
|
||||
}
|
||||
|
||||
// StickerSet represents a sticker set.
|
||||
StickerSet struct {
|
||||
// Sticker set name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Sticker set title
|
||||
Title string `json:"title"`
|
||||
|
||||
// List of all set stickers
|
||||
Stickers []Sticker `json:"stickers"`
|
||||
|
||||
// True, if the sticker set contains masks
|
||||
ContainsMasks bool `json:"contains_masks"`
|
||||
|
||||
// true, if the sticker set contains animated stickers
|
||||
IsAnimated bool `json:"is_animated"`
|
||||
}
|
||||
|
||||
// MaskPosition describes the position on faces where a mask should be placed by default.
|
||||
MaskPosition struct {
|
||||
// The part of the face relative to which the mask should be placed. One of "forehead", "eyes", "mouth", or "chin".
|
||||
Point string `json:"point"`
|
||||
|
||||
// Shift by X-axis measured in widths of the mask scaled to the face size, from left to right. For example, choosing -1.0 will place mask just to the left of the default mask position.
|
||||
XShift float32 `json:"x_shift"`
|
||||
|
||||
// Shift by Y-axis measured in heights of the mask scaled to the face size, from top to bottom. For example, 1.0 will place the mask just below the default mask position.
|
||||
YShift float32 `json:"y_shift"`
|
||||
|
||||
// Mask scaling coefficient. For example, 2.0 means double size.
|
||||
Scale float32 `json:"scale"`
|
||||
}
|
||||
|
||||
// SendStickerParameters represents data for SetSticker method.
|
||||
SendSticker struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Sticker to send
|
||||
Sticker InputFile `json:"sticker"`
|
||||
|
||||
// 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"`
|
||||
|
||||
// Additional interface options. A JSON-serialized object for an inline keyboard, custom reply keyboard, instructions to remove reply keyboard or to force a reply from the user.
|
||||
ReplyMarkup ReplyMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// GetStickerSetParameters represents data for GetStickerSet method.
|
||||
GetStickerSet struct {
|
||||
// Name of the sticker set
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
UploadStickerFile struct {
|
||||
// User identifier of sticker file owner
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Png image with the sticker, must be up to 512 kilobytes in size,
|
||||
// dimensions must not exceed 512px, and either width or height
|
||||
// must be exactly 512px.
|
||||
PNGSticker *InputFile `json:"png_sticker"`
|
||||
}
|
||||
|
||||
CreateNewStickerSet struct {
|
||||
// User identifier of created sticker set owner
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Short name of sticker set, to be used in t.me/addstickers/ URLs
|
||||
// (e.g., animals). Can contain only english letters, digits and
|
||||
// underscores. Must begin with a letter, can't contain consecutive
|
||||
// underscores and must end in “_by_<bot username>”. <bot_username>
|
||||
// is case insensitive. 1-64 characters.
|
||||
Name string `json:"name"`
|
||||
|
||||
// Sticker set title, 1-64 characters
|
||||
Title string `json:"title"`
|
||||
|
||||
// Png image with the sticker, must be up to 512 kilobytes in size,
|
||||
// dimensions must not exceed 512px, and either width or height must
|
||||
// be exactly 512px. Pass a file_id as a String to send a file that
|
||||
// already exists on the Telegram servers, pass an HTTP URL as a
|
||||
// String for Telegram to get a file from the Internet, or upload
|
||||
// a new one using multipart/form-data.
|
||||
PNGSticker *InputFile `json:"png_sticker"`
|
||||
|
||||
// One or more emoji corresponding to the sticker
|
||||
Emojis string `json:"emojis"`
|
||||
|
||||
// Pass True, if a set of mask stickers should be created
|
||||
ContainsMasks bool `json:"contains_masks,omitempty"`
|
||||
|
||||
// A JSON-serialized object for position where the mask should be
|
||||
// placed on faces
|
||||
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
|
||||
}
|
||||
|
||||
AddStickerToSet struct {
|
||||
// User identifier of sticker set owner
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Sticker set name
|
||||
Name string `json:"name"`
|
||||
|
||||
// Png image with the sticker, must be up to 512 kilobytes in size, dimensions must not exceed 512px, and either width or height must be exactly 512px. Pass a file_id as a String to send a file that already exists on the Telegram servers, pass an HTTP URL as a String for Telegram to get a file from the Internet, or upload a new one using multipart/form-data. More info on Sending Files »
|
||||
PNGSticker *InputFile `json:"png_sticker"`
|
||||
|
||||
// One or more emoji corresponding to the sticker
|
||||
Emojis string `json:"emojis"`
|
||||
|
||||
// A JSON-serialized object for position where the mask should be placed on faces
|
||||
MaskPosition *MaskPosition `json:"mask_position,omitempty"`
|
||||
}
|
||||
|
||||
// SetStickerPositionInSetParameters represents data for SetStickerPositionInSet method.
|
||||
SetStickerPositionInSet struct {
|
||||
// File identifier of the sticker
|
||||
Sticker string `json:"sticker"`
|
||||
|
||||
// New sticker position in the set, zero-based
|
||||
Position int `json:"position"`
|
||||
}
|
||||
|
||||
// DeleteStickerFromSetParameters represents data for DeleteStickerFromSet method.
|
||||
DeleteStickerFromSet struct {
|
||||
// File identifier of the sticker
|
||||
Sticker string `json:"sticker"`
|
||||
}
|
||||
)
|
||||
|
||||
// SendSticker send .webp stickers. On success, the sent Message is returned.
|
||||
func (b *Bot) SendSticker(p SendSticker) (*Message, error) {
|
||||
src, err := b.Do(MethodSendSticker, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetStickerSet get a sticker set. On success, a StickerSet object is returned.
|
||||
func (b *Bot) GetStickerSet(name string) (*StickerSet, error) {
|
||||
src, err := b.Do(MethodGetStickerSet, GetStickerSet{Name: name})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(StickerSet)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// UploadStickerFile upload a .png file with a sticker for later use in createNewStickerSet and addStickerToSet methods (can be used multiple times). Returns the uploaded File on success.
|
||||
func (b *Bot) UploadStickerFile(userID int, pngSticker *InputFile) (*File, error) {
|
||||
params := make(map[string]string)
|
||||
params["user_id"] = strconv.Itoa(userID)
|
||||
|
||||
var err error
|
||||
if params["png_sticker"], err = b.marshler.MarshalToString(pngSticker); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
src, err := b.Upload(MethodUploadStickerFile, params, pngSticker)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(File)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// CreateNewStickerSet create new sticker set owned by a user. The bot will be able to edit the created sticker set. Returns True on success.
|
||||
func (b *Bot) CreateNewStickerSet(p CreateNewStickerSet) (bool, error) {
|
||||
params := make(map[string]string)
|
||||
params["user_id"] = strconv.Itoa(p.UserID)
|
||||
params["name"] = p.Name
|
||||
params["title"] = p.Title
|
||||
params["emojis"] = p.Emojis
|
||||
params["contains_masks"] = strconv.FormatBool(p.ContainsMasks)
|
||||
|
||||
var err error
|
||||
if params["png_sticker"], err = b.marshler.MarshalToString(p.PNGSticker); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if params["mask_position"], err = b.marshler.MarshalToString(p.MaskPosition); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
files := make([]*InputFile, 0)
|
||||
if p.PNGSticker.IsAttachment() {
|
||||
files = append(files, p.PNGSticker)
|
||||
}
|
||||
|
||||
src, err := b.Upload(MethodCreateNewStickerSet, params, files...)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// AddStickerToSet add a new sticker to a set created by the b. Returns True on success.
|
||||
func (b *Bot) AddStickerToSet(p AddStickerToSet) (bool, error) {
|
||||
params := make(map[string]string)
|
||||
params["user_id"] = strconv.Itoa(p.UserID)
|
||||
params["name"] = p.Name
|
||||
params["emojis"] = p.Emojis
|
||||
|
||||
var err error
|
||||
if params["png_sticker"], err = b.marshler.MarshalToString(p.PNGSticker); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if params["mask_position"], err = b.marshler.MarshalToString(p.MaskPosition); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
files := make([]*InputFile, 0)
|
||||
if p.PNGSticker.IsAttachment() {
|
||||
files = append(files, p.PNGSticker)
|
||||
}
|
||||
|
||||
src, err := b.Upload(MethodAddStickerToSet, params, files...)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SetStickerPositionInSet move a sticker in a set created by the bot to a specific position. Returns True on success.
|
||||
func (b *Bot) SetStickerPositionInSet(sticker string, position int) (bool, error) {
|
||||
src, err := b.marshler.Marshal(&SetStickerPositionInSet{
|
||||
Sticker: sticker,
|
||||
Position: position,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeleteStickerFromSet delete a sticker from a set created by the b. Returns True on success.
|
||||
func (b *Bot) DeleteStickerFromSet(sticker string) (bool, error) {
|
||||
src, err := b.Do(MethodDeleteStickerFromSet, DeleteStickerFromSet{Sticker: sticker})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// InSet checks that the current sticker in the stickers set.
|
||||
func (s Sticker) InSet() bool { return s.SetName != "" }
|
||||
|
||||
func (s Sticker) HasThumb() bool { return s.Thumb != nil }
|
||||
|
||||
func (s Sticker) IsMask() bool { return s.MaskPosition != nil }
|
||||
|
||||
func (s Sticker) File() File {
|
||||
return File{
|
||||
FileID: s.FileID,
|
||||
FileUniqueID: s.FileUniqueID,
|
||||
FileSize: s.FileSize,
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestStickerInSet(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
s := Sticker{SetName: "HotCherry"}
|
||||
assert.True(t, s.InSet())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
s := Sticker{}
|
||||
assert.False(t, s.InSet())
|
||||
})
|
||||
}
|
||||
|
||||
func TestStickerHasThumb(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
s := Sticker{Thumb: &PhotoSize{FileID: "abc"}}
|
||||
assert.True(t, s.HasThumb())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
s := Sticker{}
|
||||
assert.False(t, s.HasThumb())
|
||||
})
|
||||
}
|
||||
|
||||
func TestStickerIsMask(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
s := Sticker{MaskPosition: &MaskPosition{Point: PointEyes}}
|
||||
assert.True(t, s.IsMask())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
s := Sticker{}
|
||||
assert.False(t, s.IsMask())
|
||||
})
|
||||
}
|
||||
|
||||
func TestStickerFile(t *testing.T) {
|
||||
t.Run("valid", func(t *testing.T) {
|
||||
s := Sticker{FileID: "abc", FileUniqueID: "really_abc", FileSize: 42}
|
||||
assert.Equal(t, s.File(), File{
|
||||
FileID: "abc",
|
||||
FileUniqueID: "really_abc",
|
||||
FileSize: 42,
|
||||
})
|
||||
})
|
||||
t.Run("empty", func(t *testing.T) {
|
||||
var s Sticker
|
||||
assert.Equal(t, s.File(), File{})
|
||||
})
|
||||
}
|
28
stop.go
28
stop.go
|
@ -1,28 +0,0 @@
|
|||
package telegram
|
||||
|
||||
type StopPollConfig struct {
|
||||
// Unique identifier for the target chat. A native poll can't be sent to a private chat.
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Identifier of the original message with the poll
|
||||
MessageID int `json:"message_id"`
|
||||
|
||||
// A JSON-serialized object for a new message inline keyboard.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
func (b *Bot) StopPoll(params StopPollConfig) (*Poll, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := b.request(dst, MethodStopPoll)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var poll Poll
|
||||
err = parser.Unmarshal(resp.Result, &poll)
|
||||
return &poll, err
|
||||
}
|
118
telegram.go
118
telegram.go
|
@ -1,11 +1,13 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
gojson "encoding/json"
|
||||
"errors"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
json "github.com/json-iterator/go"
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
|
@ -14,55 +16,93 @@ import (
|
|||
// of the query can be found in the result field. In case of an unsuccessful
|
||||
// request, ok equals false, and the error is explained in the error field.
|
||||
type Response struct {
|
||||
Ok bool `json:"ok"`
|
||||
ErrorCode int `json:"error_code,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Result gojson.RawMessage `json:"result,omitempty"`
|
||||
Parameters *ResponseParameters `json:"parameters,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
ErrorCode int `json:"error_code,omitempty"`
|
||||
Ok bool `json:"ok"`
|
||||
Parameters []*ResponseParameters `json:"parameters,omitempty"`
|
||||
Result json.RawMessage `json:"result,omitempty"`
|
||||
}
|
||||
|
||||
var (
|
||||
defaultClient = http.Client{}
|
||||
parser = json.ConfigFastest
|
||||
)
|
||||
func (b *Bot) Do(method string, payload interface{}) ([]byte, error) {
|
||||
u := http.AcquireURI()
|
||||
defer http.ReleaseURI(u)
|
||||
u.SetScheme("https")
|
||||
u.SetHost("api.telegram.org")
|
||||
u.SetPath(path.Join("bot"+b.AccessToken, method))
|
||||
|
||||
func (b *Bot) request(dst []byte, method string) (*Response, error) {
|
||||
if b.Client == nil {
|
||||
b.SetClient(&defaultClient)
|
||||
var buf bytes.Buffer
|
||||
if err := b.marshler.NewEncoder(&buf).Encode(payload); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
requestURI := http.AcquireURI()
|
||||
requestURI.SetScheme("https")
|
||||
requestURI.SetHost("api.telegram.org")
|
||||
requestURI.SetPath(path.Join("bot"+b.AccessToken, method))
|
||||
|
||||
req := http.AcquireRequest()
|
||||
defer http.ReleaseRequest(req)
|
||||
req.Header.SetContentType("application/json; charset=utf-8")
|
||||
req.Header.SetMethod(http.MethodPost)
|
||||
if dst == nil {
|
||||
req.Header.SetMethod(http.MethodGet)
|
||||
}
|
||||
req.Header.SetRequestURI(requestURI.String())
|
||||
req.Header.SetUserAgent(path.Join("telegram", Version))
|
||||
req.Header.SetHostBytes(requestURI.Host())
|
||||
req.SetBody(dst)
|
||||
req.SetRequestURIBytes(u.RequestURI())
|
||||
req.Header.SetContentType("application/json")
|
||||
req.SetBody(buf.Bytes())
|
||||
|
||||
resp := http.AcquireResponse()
|
||||
defer http.ReleaseResponse(resp)
|
||||
|
||||
if err := b.Client.Do(req, resp); err != nil {
|
||||
if err := b.client.Do(req, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var data Response
|
||||
if err := parser.Unmarshal(resp.Body(), &data); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !data.Ok {
|
||||
return nil, errors.New(data.Description)
|
||||
}
|
||||
|
||||
return &data, nil
|
||||
return resp.Body(), nil
|
||||
}
|
||||
|
||||
func (b *Bot) Upload(method string, payload map[string]string, files ...*InputFile) ([]byte, error) {
|
||||
if len(files) == 0 {
|
||||
return b.Do(method, payload)
|
||||
}
|
||||
|
||||
body := new(bytes.Buffer)
|
||||
w := multipart.NewWriter(body)
|
||||
|
||||
for i := range files {
|
||||
_, fileName := filepath.Split(files[i].Attachment.Name())
|
||||
|
||||
part, err := w.CreateFormFile(fileName, fileName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, err = io.Copy(part, files[i].Attachment); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
for key, val := range payload {
|
||||
if err := w.WriteField(key, val); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if err := w.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
u := http.AcquireURI()
|
||||
defer http.ReleaseURI(u)
|
||||
u.SetScheme("https")
|
||||
u.SetHost("api.telegram.org")
|
||||
u.SetPath(path.Join("bot"+b.AccessToken, method))
|
||||
|
||||
req := http.AcquireRequest()
|
||||
defer http.ReleaseRequest(req)
|
||||
req.Header.SetMethod(http.MethodPost)
|
||||
req.SetRequestURIBytes(u.RequestURI())
|
||||
req.Header.SetContentType(w.FormDataContentType())
|
||||
req.Header.SetMultipartFormBoundary(w.Boundary())
|
||||
body.WriteTo(req.BodyWriter())
|
||||
|
||||
resp := http.AcquireResponse()
|
||||
defer http.ReleaseResponse(resp)
|
||||
|
||||
if err := b.client.Do(req, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resp.Body(), nil
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
33
unban.go
33
unban.go
|
@ -1,33 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// UnbanChatMemberParameters represents data for UnbanChatMember method.
|
||||
type UnbanChatMemberParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
UserID int `json:"user_id"`
|
||||
}
|
||||
|
||||
// UnbanChatMember unban a previously kicked user in a supergroup or channel. The
|
||||
// user will not return to the group or channel automatically, but will be able
|
||||
// to join via link, etc. The bot must be an administrator for this to work.
|
||||
// Returns True on success.
|
||||
func (bot *Bot) UnbanChatMember(chatID int64, userID int) (bool, error) {
|
||||
params := UnbanChatMemberParameters{
|
||||
ChatID: chatID,
|
||||
UserID: userID,
|
||||
}
|
||||
dst, err := parser.Marshal(¶ms)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodUnbanChatMember)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
26
unpin.go
26
unpin.go
|
@ -1,26 +0,0 @@
|
|||
package telegram
|
||||
|
||||
// UnpinChatMessageParameters represents data for UnpinChatMessage method.
|
||||
type UnpinChatMessageParameters struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
}
|
||||
|
||||
// UnpinChatMessage unpin a message in a supergroup chat. The bot must be an
|
||||
// administrator in the chat for this to work and must have the appropriate admin
|
||||
// rights. Returns True on success.
|
||||
func (bot *Bot) UnpinChatMessage(chatID int64) (bool, error) {
|
||||
dst, err := parser.Marshal(&UnpinChatMessageParameters{ChatID: chatID})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodUnpinChatMessage)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var ok bool
|
||||
err = parser.Unmarshal(resp.Result, &ok)
|
||||
return ok, err
|
||||
}
|
|
@ -0,0 +1,299 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type (
|
||||
// Update represents an incoming update.
|
||||
//
|
||||
// At most one of the optional parameters can be present in any given update.
|
||||
Update struct {
|
||||
// The update‘s unique identifier. Update identifiers start from a
|
||||
// certain positive number and increase sequentially. This ID becomes
|
||||
// especially handy if you’re using Webhooks, since it allows you to
|
||||
// ignore repeated updates or to restore the correct update sequence,
|
||||
// should they get out of order.
|
||||
UpdateID int `json:"update_id"`
|
||||
|
||||
// New incoming message of any kind — text, photo, sticker, etc.
|
||||
Message *Message `json:"message,omitempty"`
|
||||
|
||||
// New version of a message that is known to the bot and was edited
|
||||
EditedMessage *Message `json:"edited_message,omitempty"`
|
||||
|
||||
// New incoming channel post of any kind — text, photo, sticker, etc.
|
||||
ChannelPost *Message `json:"channel_post,omitempty"`
|
||||
|
||||
// New version of a channel post that is known to the bot and was edited
|
||||
EditedChannelPost *Message `json:"adited_channel_post,omitempty"`
|
||||
|
||||
// New incoming inline query
|
||||
InlineQuery *InlineQuery `json:"inline_query,omitempty"`
|
||||
|
||||
// The result of an inline query that was chosen by a user and sent to
|
||||
// their chat partner.
|
||||
ChosenInlineResult *ChosenInlineResult `json:"chosen_inline_result,omitempty"`
|
||||
|
||||
// New incoming callback query
|
||||
CallbackQuery *CallbackQuery `json:"callback_query,omitempty"`
|
||||
|
||||
// New incoming shipping query. Only for invoices with flexible price
|
||||
ShippingQuery *ShippingQuery `json:"shipping_query,omitempty"`
|
||||
|
||||
// New incoming pre-checkout query. Contains full information about
|
||||
// checkout
|
||||
PreCheckoutQuery *PreCheckoutQuery `json:"pre_checkout_query,omitempty"`
|
||||
|
||||
// New poll state. Bots receive only updates about polls, which are sent or stopped by the bot
|
||||
Poll *Poll `json:"poll,omitempty"`
|
||||
}
|
||||
|
||||
// WebhookInfo contains information about the current status of a webhook.
|
||||
WebhookInfo struct {
|
||||
// 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"`
|
||||
|
||||
// Number of updates awaiting delivery
|
||||
PendingUpdateCount int `json:"pending_update_count"`
|
||||
|
||||
// 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"`
|
||||
}
|
||||
|
||||
// GetUpdatesParameters represents data for GetUpdates method.
|
||||
GetUpdates struct {
|
||||
// Identifier of the first update to be returned. Must be greater by one than the highest among the
|
||||
// identifiers of previously received updates. By default, updates starting with the earliest unconfirmed
|
||||
// update are returned. An update is considered confirmed as soon as getUpdates is called with an offset
|
||||
// higher than its update_id. The negative offset can be specified to retrieve updates starting from -offset
|
||||
// update from the end of the updates queue. All previous updates will forgotten.
|
||||
Offset int `json:"offset,omitempty"`
|
||||
|
||||
// Limits the number of updates to be retrieved. Values between 1—100 are accepted. Defaults to 100.
|
||||
Limit int `json:"limit,omitempty"`
|
||||
|
||||
// Timeout in seconds for long polling. Defaults to 0, i.e. usual short polling. Should be positive, short
|
||||
// polling should be used for testing purposes only.
|
||||
Timeout int `json:"timeout,omitempty"`
|
||||
|
||||
// List the types of updates you want your bot to receive. For example, specify ["message",
|
||||
// "edited_channel_post", "callback_query"] to only receive updates of these types. See Update for a complete
|
||||
// list of available update types. Specify an empty list to receive all updates regardless of type (default).
|
||||
// If not specified, the previous setting will be used.
|
||||
//
|
||||
// Please note that this parameter doesn't affect updates created before the call to the getUpdates, so
|
||||
// unwanted updates may be received for a short period of time.
|
||||
AllowedUpdates []string `json:"allowed_updates,omitempty"`
|
||||
}
|
||||
|
||||
// SetWebhookParameters represents data for SetWebhook method.
|
||||
SetWebhook struct {
|
||||
// HTTPS url to send updates to. Use an empty string to remove webhook
|
||||
// integration
|
||||
URL string `json:"url"`
|
||||
|
||||
// Upload your public key certificate so that the root certificate in use can
|
||||
// be checked. See our self-signed guide for details.
|
||||
Certificate InputFile `json:"certificate,omitempty"`
|
||||
|
||||
// Maximum allowed number of simultaneous HTTPS connections to the webhook
|
||||
// for update delivery, 1-100. Defaults to 40. Use lower values to limit the
|
||||
// load on your bot‘s server, and higher values to increase your bot’s
|
||||
// throughput.
|
||||
MaxConnections int `json:"max_connections,omitempty"`
|
||||
|
||||
// List the types of updates you want your bot to receive. For example,
|
||||
// specify [“message”, “edited_channel_post”, “callback_query”] to only
|
||||
// receive updates of these types. See Update for a complete list of
|
||||
// available update types. Specify an empty list to receive all updates
|
||||
// regardless of type (default). If not specified, the previous setting will
|
||||
// be used.
|
||||
//
|
||||
// Please note that this parameter doesn't affect updates created before the
|
||||
// call to the setWebhook, so unwanted updates may be received for a short
|
||||
// period of time.
|
||||
AllowedUpdates []string `json:"allowed_updates,omitempty"`
|
||||
}
|
||||
)
|
||||
|
||||
// GetUpdates receive incoming updates using long polling. An Array of Update objects is returned.
|
||||
func (b *Bot) GetUpdates(p *GetUpdates) ([]*Update, error) {
|
||||
src, err := b.Do(MethodGetUpdates, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make([]*Update, 0)
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// SetWebhook specify a url and receive incoming updates via an outgoing webhook. Whenever there is an update for the bot, we will send an HTTPS POST request to the specified url, containing a JSON-serialized Update. In case of an unsuccessful request, we will give up after a reasonable amount of attempts. Returns true.
|
||||
//
|
||||
// If you'd like to make sure that the Webhook request comes from Telegram, we recommend using a secret path in the URL, e.g. https://www.example.com/<token>. Since nobody else knows your bot‘s token, you can be pretty sure it’s us.
|
||||
func (b *Bot) SetWebhook(p SetWebhook) (bool, error) {
|
||||
var src []byte
|
||||
var err error
|
||||
|
||||
// if p.Certificate != nil {
|
||||
// src, err = b.Upload(MethodSetWebhook, "certificate", "cert.pem", params.Certificate, args)
|
||||
// } else {
|
||||
src, err = b.Do(MethodSetWebhook, p)
|
||||
// }
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeleteWebhook remove webhook integration if you decide to switch back to getUpdates. Returns True on success. Requires no parameters.
|
||||
func (b *Bot) DeleteWebhook() (bool, error) {
|
||||
src, err := b.Do(MethodDeleteWebhook, nil)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetWebhookInfo get current webhook status. Requires no parameters. On success, returns a WebhookInfo object. If the bot is using getUpdates, will return an object with the url field empty.
|
||||
func (b *Bot) GetWebhookInfo() (*WebhookInfo, error) {
|
||||
src, err := b.Do(MethodGetWebhookInfo, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(WebhookInfo)
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// IsMessage checks that the current update is a message creation event.
|
||||
func (u Update) IsMessage() bool { return u.Message != nil }
|
||||
|
||||
// IsEditedMessage checks that the current update is a editing message event.
|
||||
func (u Update) IsEditedMessage() bool { return u.EditedMessage != nil }
|
||||
|
||||
// IsChannelPost checks that the current update is a post channel creation event.
|
||||
func (u Update) IsChannelPost() bool { return u.ChannelPost != nil }
|
||||
|
||||
// IsEditedChannelPost checks that the current update is a editing post channel event.
|
||||
func (u Update) IsEditedChannelPost() bool { return u.EditedChannelPost != nil }
|
||||
|
||||
// IsInlineQuery checks that the current update is a inline query update.
|
||||
func (u Update) IsInlineQuery() bool { return u.InlineQuery != nil }
|
||||
|
||||
// IsChosenInlineResult checks that the current update is a chosen inline result update.
|
||||
func (u Update) IsChosenInlineResult() bool { return u.ChosenInlineResult != nil }
|
||||
|
||||
// IsCallbackQuery checks that the current update is a callback query update.
|
||||
func (u Update) IsCallbackQuery() bool { return u.CallbackQuery != nil }
|
||||
|
||||
// IsShippingQuery checks that the current update is a shipping query update.
|
||||
func (u Update) IsShippingQuery() bool { return u.ShippingQuery != nil }
|
||||
|
||||
// IsPreCheckoutQuery checks that the current update is a pre checkout query update.
|
||||
func (u Update) IsPreCheckoutQuery() bool { return u.PreCheckoutQuery != nil }
|
||||
|
||||
// IsPoll checks that the current update is a poll update.
|
||||
func (u Update) IsPoll() bool { return u.Poll != nil }
|
||||
|
||||
// Type return update type for current update.
|
||||
func (u Update) Type() string {
|
||||
switch {
|
||||
case u.IsCallbackQuery():
|
||||
return UpdateCallbackQuery
|
||||
case u.IsChannelPost():
|
||||
return UpdateChannelPost
|
||||
case u.IsChosenInlineResult():
|
||||
return UpdateChosenInlineResult
|
||||
case u.IsEditedChannelPost():
|
||||
return UpdateEditedChannelPost
|
||||
case u.IsEditedMessage():
|
||||
return UpdateEditedMessage
|
||||
case u.IsInlineQuery():
|
||||
return UpdateInlineQuery
|
||||
case u.IsMessage():
|
||||
return UpdateMessage
|
||||
case u.IsPreCheckoutQuery():
|
||||
return UpdatePreCheckoutQuery
|
||||
case u.IsShippingQuery():
|
||||
return UpdateShippingQuery
|
||||
case u.IsPoll():
|
||||
return UpdatePoll
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (wi WebhookInfo) LastErrorTime() time.Time { return time.Unix(wi.LastErrorDate, 0) }
|
||||
|
||||
func (wi WebhookInfo) HasURL() bool { return wi.URL != "" }
|
||||
|
||||
func (wi WebhookInfo) URI() *http.URI {
|
||||
if !wi.HasURL() {
|
||||
return nil
|
||||
}
|
||||
|
||||
u := http.AcquireURI()
|
||||
u.Update(wi.URL)
|
||||
return u
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
func TestUpdateIsMessage(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{Message: &Message{ID: 42}}
|
||||
assert.True(t, u.IsMessage())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsMessage())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsEditedMessage(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{EditedMessage: &Message{ID: 42}}
|
||||
assert.True(t, u.IsEditedMessage())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsEditedMessage())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsChannelPost(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{ChannelPost: &Message{ID: 42}}
|
||||
assert.True(t, u.IsChannelPost())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsChannelPost())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsEditedChannelPost(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{EditedChannelPost: &Message{ID: 42}}
|
||||
assert.True(t, u.IsEditedChannelPost())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsEditedChannelPost())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsInlineQuery(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{InlineQuery: &InlineQuery{Query: "abc"}}
|
||||
assert.True(t, u.IsInlineQuery())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsInlineQuery())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsChosenInlineResult(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{ChosenInlineResult: &ChosenInlineResult{ResultID: "abc"}}
|
||||
assert.True(t, u.IsChosenInlineResult())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsChosenInlineResult())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsCallbackQuery(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{CallbackQuery: &CallbackQuery{ID: "abc"}}
|
||||
assert.True(t, u.IsCallbackQuery())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsCallbackQuery())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsShippingQuery(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{ShippingQuery: &ShippingQuery{ID: "abc"}}
|
||||
assert.True(t, u.IsShippingQuery())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsShippingQuery())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsPreCheckoutQuery(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{PreCheckoutQuery: &PreCheckoutQuery{ID: "abc"}}
|
||||
assert.True(t, u.IsPreCheckoutQuery())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsPreCheckoutQuery())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateIsPoll(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
u := Update{Poll: &Poll{ID: "abc"}}
|
||||
assert.True(t, u.IsPoll())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
u := Update{}
|
||||
assert.False(t, u.IsPoll())
|
||||
})
|
||||
}
|
||||
|
||||
func TestUpdateType(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
update Update
|
||||
expResult string
|
||||
}{{
|
||||
name: UpdateCallbackQuery,
|
||||
update: Update{CallbackQuery: &CallbackQuery{ID: "abc"}},
|
||||
expResult: UpdateCallbackQuery,
|
||||
}, {
|
||||
name: UpdateChannelPost,
|
||||
update: Update{ChannelPost: &Message{ID: 42}},
|
||||
expResult: UpdateChannelPost,
|
||||
}, {
|
||||
name: UpdateChosenInlineResult,
|
||||
update: Update{ChosenInlineResult: &ChosenInlineResult{Query: "query"}},
|
||||
expResult: UpdateChosenInlineResult,
|
||||
}, {
|
||||
name: UpdateEditedChannelPost,
|
||||
update: Update{EditedChannelPost: &Message{ID: 42}},
|
||||
expResult: UpdateEditedChannelPost,
|
||||
}, {
|
||||
name: UpdateEditedMessage,
|
||||
update: Update{EditedMessage: &Message{ID: 42}},
|
||||
expResult: UpdateEditedMessage,
|
||||
}, {
|
||||
name: UpdateInlineQuery,
|
||||
update: Update{InlineQuery: &InlineQuery{ID: "abc"}},
|
||||
expResult: UpdateInlineQuery,
|
||||
}, {
|
||||
name: UpdateMessage,
|
||||
update: Update{Message: &Message{ID: 42}},
|
||||
expResult: UpdateMessage,
|
||||
}, {
|
||||
name: UpdatePoll,
|
||||
update: Update{Poll: &Poll{ID: "abc"}},
|
||||
expResult: UpdatePoll,
|
||||
}, {
|
||||
name: UpdatePreCheckoutQuery,
|
||||
update: Update{PreCheckoutQuery: &PreCheckoutQuery{ID: "abc"}},
|
||||
expResult: UpdatePreCheckoutQuery,
|
||||
}, {
|
||||
name: UpdateShippingQuery,
|
||||
update: Update{ShippingQuery: &ShippingQuery{ID: "abc"}},
|
||||
expResult: UpdateShippingQuery,
|
||||
}, {
|
||||
name: "other",
|
||||
update: Update{},
|
||||
expResult: "",
|
||||
}} {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
assert.Equal(t, tc.update.Type(), tc.expResult)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebhookInfoLastErrorTime(t *testing.T) {
|
||||
now := time.Now().Round(time.Second)
|
||||
wi := WebhookInfo{LastErrorDate: now.Unix()}
|
||||
assert.Equal(t, wi.LastErrorTime(), now)
|
||||
}
|
||||
|
||||
func TestWebhookInfoHasURL(t *testing.T) {
|
||||
t.Run("true", func(t *testing.T) {
|
||||
wi := WebhookInfo{URL: "https://bot.toby3d.me"}
|
||||
assert.True(t, wi.HasURL())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
wi := WebhookInfo{}
|
||||
assert.False(t, wi.HasURL())
|
||||
})
|
||||
}
|
||||
|
||||
func TestWebhookInfoURI(t *testing.T) {
|
||||
u := http.AcquireURI()
|
||||
defer http.ReleaseURI(u)
|
||||
|
||||
u.Update("https://bot.toby3d.me")
|
||||
t.Run("true", func(t *testing.T) {
|
||||
wi := WebhookInfo{URL: u.String()}
|
||||
assert.Equal(t, wi.URI().String(), u.String())
|
||||
})
|
||||
t.Run("false", func(t *testing.T) {
|
||||
wi := WebhookInfo{}
|
||||
assert.Nil(t, wi.URI())
|
||||
})
|
||||
}
|
|
@ -1,34 +1,8 @@
|
|||
package telegram
|
||||
|
||||
type (
|
||||
// EditMessageLiveLocationParameters represents data for EditMessageLiveLocation
|
||||
// method.
|
||||
EditMessageLiveLocationParameters struct {
|
||||
// Required if inline_message_id is not specified. Unique identifier for the
|
||||
// target chat or username of the target channel (in the format
|
||||
// @channelusername)
|
||||
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"`
|
||||
|
||||
// Latitude of new location
|
||||
Latitude float32 `json:"latitude"`
|
||||
|
||||
// Longitude of new location
|
||||
Longitude float32 `json:"longitude"`
|
||||
|
||||
// A JSON-serialized object for a new inline keyboard.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// EditMessageTextParameters represents data for EditMessageText method.
|
||||
EditMessageTextParameters struct {
|
||||
EditMessageText struct {
|
||||
// Required if inline_message_id is not specified. Unique identifier for the
|
||||
// target chat or username of the target channel (in the format
|
||||
// @channelusername)
|
||||
|
@ -57,7 +31,7 @@ type (
|
|||
}
|
||||
|
||||
// EditMessageCaptionParameters represents data for EditMessageCaption method.
|
||||
EditMessageCaptionParameters struct {
|
||||
EditMessageCaption struct {
|
||||
// Required if inline_message_id is not specified. Unique identifier for the
|
||||
// target chat or username of the target channel (in the format
|
||||
// @channelusername)
|
||||
|
@ -83,7 +57,7 @@ type (
|
|||
}
|
||||
|
||||
// EditMessageMediaParameters represents data for EditMessageMedia method.
|
||||
EditMessageMediaParameters struct {
|
||||
EditMessageMedia struct {
|
||||
// Required if inline_message_id is not specified. Unique identifier for the target chat or username of the target channel (in the format @channelusername)
|
||||
ChatID int64 `json:"chat_id,omitempty"`
|
||||
|
||||
|
@ -101,7 +75,7 @@ type (
|
|||
}
|
||||
|
||||
// EditMessageReplyMarkupParameters represents data for EditMessageReplyMarkup method.
|
||||
EditMessageReplyMarkupParameters struct {
|
||||
EditMessageReplyMarkup struct {
|
||||
// Required if inline_message_id is not specified. Unique identifier for the
|
||||
// target chat or username of the target channel (in the format
|
||||
// @channelusername)
|
||||
|
@ -118,81 +92,70 @@ type (
|
|||
// A JSON-serialized object for an inline keyboard.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
StopPoll struct {
|
||||
// Unique identifier for the target chat. A native poll can't be sent to a private chat.
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Identifier of the original message with the poll
|
||||
MessageID int `json:"message_id"`
|
||||
|
||||
// A JSON-serialized object for a new message inline keyboard.
|
||||
ReplyMarkup *InlineKeyboardMarkup `json:"reply_markup,omitempty"`
|
||||
}
|
||||
|
||||
// DeleteMessageParameters represents data for DeleteMessage method.
|
||||
DeleteMessage struct {
|
||||
// Unique identifier for the target chat
|
||||
ChatID int64 `json:"chat_id"`
|
||||
|
||||
// Identifier of the message to delete
|
||||
MessageID int `json:"message_id"`
|
||||
}
|
||||
)
|
||||
|
||||
// NewLiveLocation creates EditMessageLiveLocationParameters only with required
|
||||
// parameters.
|
||||
func NewLiveLocation(latitude, longitude float32) *EditMessageLiveLocationParameters {
|
||||
return &EditMessageLiveLocationParameters{
|
||||
Latitude: latitude,
|
||||
Longitude: longitude,
|
||||
}
|
||||
}
|
||||
|
||||
// NewMessageText creates EditMessageTextParameters only with required parameters.
|
||||
func NewMessageText(text string) *EditMessageTextParameters {
|
||||
return &EditMessageTextParameters{
|
||||
Text: text,
|
||||
}
|
||||
}
|
||||
|
||||
// EditMessageLiveLocation edit live location messages sent by the bot or via the
|
||||
// bot (for inline bots). A location can be edited until its live_period expires
|
||||
// or editing is explicitly disabled by a call to stopMessageLiveLocation. On
|
||||
// success, if the edited message was sent by the bot, the edited Message is
|
||||
// returned, otherwise True is returned.
|
||||
func (bot *Bot) EditMessageLiveLocation(params *EditMessageLiveLocationParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodEditMessageLiveLocation)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
}
|
||||
|
||||
// EditMessageText edit text and game messages sent by the bot or via the bot
|
||||
// (for inline bots). On success, if edited message is sent by the bot, the
|
||||
// edited Message is returned, otherwise True is returned.
|
||||
func (bot *Bot) EditMessageText(params *EditMessageTextParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
func (b *Bot) EditMessageText(p *EditMessageText) (*Message, error) {
|
||||
src, err := b.Do(MethodEditMessageText, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodEditMessageText)
|
||||
if err != nil {
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// EditMessageCaption edit captions of messages sent by the bot or via the bot
|
||||
// (for inline bots). On success, if edited message is sent by the bot, the
|
||||
// edited Message is returned, otherwise True is returned.
|
||||
func (bot *Bot) EditMessageCaption(params *EditMessageCaptionParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
func (b *Bot) EditMessageCaption(p *EditMessageCaption) (*Message, error) {
|
||||
src, err := b.Do(MethodEditMessageCaption, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodEditMessageCaption)
|
||||
if err != nil {
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// EditMessageMedia edit audio, document, photo, or video messages. If a message
|
||||
|
@ -201,37 +164,94 @@ func (bot *Bot) EditMessageCaption(params *EditMessageCaptionParameters) (*Messa
|
|||
// edited, new file can't be uploaded. Use previously uploaded file via its
|
||||
// file_id or specify a URL. On success, if the edited message was sent by the
|
||||
// bot, the edited Message is returned, otherwise True is returned.
|
||||
func (b *Bot) EditMessageMedia(emmp *EditMessageMediaParameters) (*Message, error) {
|
||||
src, err := parser.Marshal(emmp)
|
||||
func (b *Bot) EditMessageMedia(p EditMessageMedia) (*Message, error) {
|
||||
src, err := b.Do(MethodEditMessageMedia, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := b.request(src, MethodEditMessageMedia)
|
||||
if err != nil {
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// EditMessageReplyMarkup edit only the reply markup of messages sent by the bot
|
||||
// or via the bot (for inline bots). On success, if edited message is sent by the
|
||||
// bot, the edited Message is returned, otherwise True is returned.
|
||||
func (bot *Bot) EditMessageReplyMarkup(params *EditMessageReplyMarkupParameters) (*Message, error) {
|
||||
dst, err := parser.Marshal(params)
|
||||
func (b *Bot) EditMessageReplyMarkup(p EditMessageReplyMarkup) (*Message, error) {
|
||||
src, err := b.Do(MethodEditMessageReplyMarkup, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp, err := bot.request(dst, MethodEditMessageReplyMarkup)
|
||||
if err != nil {
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var msg Message
|
||||
err = parser.Unmarshal(resp.Result, &msg)
|
||||
return &msg, err
|
||||
result := new(Message)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (b *Bot) StopPoll(p StopPoll) (*Poll, error) {
|
||||
src, err := b.Do(MethodStopPoll, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := new(Poll)
|
||||
if err = b.marshler.Unmarshal(resp.Result, result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// DeleteMessage delete a message, including service messages, with the following limitations:
|
||||
//
|
||||
// - A message can only be deleted if it was sent less than 48 hours ago.
|
||||
// - Bots can delete outgoing messages in private chats, groups, and supergroups.
|
||||
// - Bots can delete incoming messages in private chats.
|
||||
// - Bots granted can_post_messages permissions can delete outgoing messages in channels.
|
||||
// - If the bot is an administrator of a group, it can delete any message there.
|
||||
// - If the bot has can_delete_messages permission in a supergroup or a channel, it can delete any message there.
|
||||
//
|
||||
// Returns True on success.
|
||||
func (b *Bot) DeleteMessage(chatID int64, messageID int) (bool, error) {
|
||||
src, err := b.Do(MethodDeleteMessage, DeleteMessage{
|
||||
ChatID: chatID,
|
||||
MessageID: messageID,
|
||||
})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
resp := new(Response)
|
||||
if err = b.marshler.Unmarshal(src, resp); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
var result bool
|
||||
if err = b.marshler.Unmarshal(resp.Result, &result); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
186
upload.go
186
upload.go
|
@ -1,186 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
type UploadStickerFileParameters struct {
|
||||
// User identifier of sticker file owner
|
||||
UserID int `json:"user_id"`
|
||||
|
||||
// Png image with the sticker, must be up to 512 kilobytes in size,
|
||||
// dimensions must not exceed 512px, and either width or height
|
||||
// must be exactly 512px.
|
||||
PNGSticker interface{} `json:"png_sticker"`
|
||||
}
|
||||
|
||||
// ErrBadFileType describes error of the unsupported file data type for uploading
|
||||
var ErrBadFileType = errors.New("bad file type")
|
||||
|
||||
/*
|
||||
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:
|
||||
each file object has a file_id field, simply pass this file_id as a parameter instead of uploading.
|
||||
There are no limits for files sent this way.
|
||||
|
||||
2. Provide Telegram with an *fasthttp.URI for the file to be sent. Telegram will download and send the
|
||||
file. 5 MB max size for photos and 20 MB max for other types of content.
|
||||
|
||||
3. Post the file using multipart/form-data in the usual way that files are uploaded via the
|
||||
browser. Use []byte or io.Reader for this. 10 MB max size for photos, 50 MB for other files.
|
||||
|
||||
Sending by FileID
|
||||
|
||||
* It is not possible to change the file type when resending by file_id. I.e. a video can't be sent
|
||||
as a photo, a photo can't be sent as a document, etc.
|
||||
|
||||
* It is not possible to resend thumbnails.
|
||||
|
||||
* Resending a photo by file_id will send all of its sizes.
|
||||
|
||||
* file_id is unique for each individual bot and can't be transferred from one bot to another.
|
||||
|
||||
Sending by URL
|
||||
|
||||
* When sending by *fasthttp.URI the target file must have the correct MIME type (e.g., audio/mpeg for
|
||||
sendAudio, etc.).
|
||||
|
||||
* In sendDocument, sending by URL will currently only work for gif, pdf and zip files.
|
||||
|
||||
* To use SendVoice, the file must have the type audio/ogg and be no more than 1MB in size. 1–20MB
|
||||
voice notes will be sent as files.
|
||||
|
||||
* Other configurations may work but we can't guarantee that they will.
|
||||
*/
|
||||
func (b *Bot) Upload(method, key, name string, file InputFile, args *http.Args) (*Response, error) {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
multi := multipart.NewWriter(buffer)
|
||||
|
||||
requestURI := http.AcquireURI()
|
||||
requestURI.SetScheme("https")
|
||||
requestURI.SetHost("api.telegram.org")
|
||||
requestURI.SetPath(path.Join("bot"+b.AccessToken, method))
|
||||
|
||||
args.VisitAll(func(key, value []byte) {
|
||||
_ = multi.WriteField(string(key), string(value))
|
||||
})
|
||||
|
||||
if err := createFileField(multi, file, key, name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := multi.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req := http.AcquireRequest()
|
||||
defer http.ReleaseRequest(req)
|
||||
req.SetBody(buffer.Bytes())
|
||||
req.Header.SetContentType(multi.FormDataContentType())
|
||||
req.Header.SetMethod("POST")
|
||||
req.Header.SetRequestURI(requestURI.String())
|
||||
req.Header.SetUserAgent(path.Join("telegram", Version))
|
||||
req.Header.SetHostBytes(requestURI.Host())
|
||||
|
||||
resp := http.AcquireResponse()
|
||||
defer http.ReleaseResponse(resp)
|
||||
|
||||
if err := http.Do(req, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var response Response
|
||||
if err := parser.Unmarshal(resp.Body(), &response); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !response.Ok {
|
||||
return nil, errors.New(response.Description)
|
||||
}
|
||||
|
||||
return &response, nil
|
||||
}
|
||||
|
||||
func createFileField(w *multipart.Writer, file interface{}, key, val string) (err error) {
|
||||
switch src := file.(type) {
|
||||
case string: // Send FileID of file on disk path
|
||||
return createFileFieldString(w, key, src)
|
||||
case *http.URI: // Send by URL
|
||||
return w.WriteField(key, src.String())
|
||||
case []byte: // Upload new
|
||||
return createFileFieldRaw(w, key, val, bytes.NewReader(src))
|
||||
case io.Reader: // Upload new
|
||||
return createFileFieldRaw(w, key, val, src)
|
||||
default:
|
||||
return ErrBadFileType
|
||||
}
|
||||
}
|
||||
|
||||
func createFileFieldString(w *multipart.Writer, key, src string) (err error) {
|
||||
_, err = os.Stat(src)
|
||||
|
||||
switch {
|
||||
case os.IsNotExist(err):
|
||||
err = w.WriteField(key, src)
|
||||
case os.IsExist(err):
|
||||
err = uploadFromDisk(w, key, src)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
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 createFileFieldRaw(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
|
||||
}
|
||||
|
||||
// UploadStickerFile upload a .png file with a sticker for later use in
|
||||
// createNewStickerSet and addStickerToSet methods (can be used multiple times).
|
||||
// Returns the uploaded File on success.
|
||||
func (b *Bot) UploadStickerFile(userID int, pngSticker interface{}) (*File, error) {
|
||||
args := http.AcquireArgs()
|
||||
defer http.ReleaseArgs(args)
|
||||
args.SetUint("user_id", userID)
|
||||
|
||||
resp, err := b.Upload(MethodUploadStickerFile, TypeSticker, "sticker", pngSticker, args)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var f File
|
||||
err = parser.Unmarshal(resp.Result, &f)
|
||||
return &f, err
|
||||
}
|
195
utils_test.go
195
utils_test.go
|
@ -1,195 +0,0 @@
|
|||
package telegram
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
http "github.com/valyala/fasthttp"
|
||||
)
|
||||
|
||||
const (
|
||||
testPhrase = "Hello, world!"
|
||||
testLink = "https://toby3d.me/"
|
||||
testID = 123456789
|
||||
// testUsername = "toby3d"
|
||||
// testChannel = "toby3dRu"
|
||||
testCode = "<spoiler>hide me</spoiler>"
|
||||
)
|
||||
|
||||
var (
|
||||
testPhotoSize = PhotoSize{
|
||||
FileID: "cba",
|
||||
FileSize: 123,
|
||||
Width: 128,
|
||||
Height: 128,
|
||||
}
|
||||
testAnimation = Animation{
|
||||
FileID: "abc",
|
||||
FileName: "animation",
|
||||
FileSize: 321,
|
||||
Thumb: &testPhotoSize,
|
||||
}
|
||||
testAudio = Audio{
|
||||
Performer: "One-Aloner",
|
||||
Title: "(Not) your reality (Doki Doki Literature Club cover)",
|
||||
Thumb: &testPhotoSize,
|
||||
}
|
||||
)
|
||||
|
||||
func TestMarkdown(t *testing.T) {
|
||||
t.Run("bold", func(t *testing.T) {
|
||||
assert.Equal(t, "*"+testPhrase+"*", NewMarkdownBold(testPhrase))
|
||||
})
|
||||
t.Run("italic", func(t *testing.T) {
|
||||
assert.Equal(t, "_"+testPhrase+"_", NewMarkdownItalic(testPhrase))
|
||||
})
|
||||
t.Run("link", func(t *testing.T) {
|
||||
link := http.AcquireURI()
|
||||
defer http.ReleaseURI(link)
|
||||
link.Update(testLink)
|
||||
assert.Equal(t, "["+testPhrase+"]("+testLink+")", NewMarkdownURL(testPhrase, link))
|
||||
})
|
||||
t.Run("mention", func(t *testing.T) {
|
||||
assert.Equal(t, "["+testPhrase+"](tg://user/?id="+strconv.Itoa(testID)+")", NewMarkdownMention(testPhrase, testID))
|
||||
})
|
||||
t.Run("code", func(t *testing.T) {
|
||||
assert.Equal(t, "`"+testCode+"`", NewMarkdownCode(testCode))
|
||||
})
|
||||
t.Run("code block", func(t *testing.T) {
|
||||
assert.Equal(t, "```"+testCode+"```", NewMarkdownCodeBlock(testCode))
|
||||
})
|
||||
}
|
||||
|
||||
func TestHTML(t *testing.T) {
|
||||
t.Run("bold", func(t *testing.T) {
|
||||
assert.Equal(t, "<b>"+testPhrase+"</b>", NewHTMLBold(testPhrase))
|
||||
})
|
||||
t.Run("italic", func(t *testing.T) {
|
||||
assert.Equal(t, "<i>"+testPhrase+"</i>", NewHTMLItalic(testPhrase))
|
||||
})
|
||||
t.Run("link", func(t *testing.T) {
|
||||
link := http.AcquireURI()
|
||||
defer http.ReleaseURI(link)
|
||||
link.Update(testLink)
|
||||
assert.Equal(t, `<a href="`+link.String()+`">`+testPhrase+`</a>`, NewHTMLURL(testPhrase, link))
|
||||
})
|
||||
t.Run("mention", func(t *testing.T) {
|
||||
assert.Equal(t, `<a href="tg://user/?id=`+strconv.Itoa(testID)+`">`+testPhrase+`</a>`, NewHTMLMention(testPhrase, testID))
|
||||
})
|
||||
t.Run("code", func(t *testing.T) {
|
||||
assert.Equal(t, "<code>"+testCode+"</code>", NewHTMLCode(testCode))
|
||||
})
|
||||
t.Run("code block", func(t *testing.T) {
|
||||
assert.Equal(t, "<pre>"+testCode+"</pre>", NewHTMLCodeBlock(testCode))
|
||||
})
|
||||
}
|
||||
|
||||
func TestAnimation(t *testing.T) {
|
||||
t.Run("has thumb", func(t *testing.T) {
|
||||
t.Run("false", func(t *testing.T) {
|
||||
a := new(Animation)
|
||||
assert.False(t, a.HasThumb())
|
||||
})
|
||||
t.Run("true", func(t *testing.T) {
|
||||
assert.True(t, testAnimation.HasThumb())
|
||||
})
|
||||
})
|
||||
t.Run("file", func(t *testing.T) {
|
||||
assert.NotNil(t, testAnimation.File())
|
||||
})
|
||||
}
|
||||
|
||||
func TestAudio(t *testing.T) {
|
||||
t.Run("has performer", func(t *testing.T) {
|
||||
t.Run("false", func(t *testing.T) {
|
||||
a := new(Audio)
|
||||
assert.False(t, a.HasPerformer())
|
||||
})
|
||||
t.Run("true", func(t *testing.T) {
|
||||
assert.True(t, testAudio.HasPerformer())
|
||||
})
|
||||
})
|
||||
t.Run("has title", func(t *testing.T) {
|
||||
t.Run("false", func(t *testing.T) {
|
||||
a := new(Audio)
|
||||
assert.False(t, a.HasTitle())
|
||||
})
|
||||
t.Run("true", func(t *testing.T) {
|
||||
assert.True(t, testAudio.HasTitle())
|
||||
})
|
||||
})
|
||||
t.Run("has thumb", func(t *testing.T) {
|
||||
t.Run("false", func(t *testing.T) {
|
||||
a := new(Audio)
|
||||
assert.False(t, a.HasThumb())
|
||||
})
|
||||
t.Run("true", func(t *testing.T) {
|
||||
assert.True(t, testAudio.HasThumb())
|
||||
})
|
||||
})
|
||||
t.Run("file", func(t *testing.T) {
|
||||
assert.NotNil(t, testAudio.File())
|
||||
})
|
||||
t.Run("full name", func(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
message string
|
||||
audio *Audio
|
||||
separator string
|
||||
expResult string
|
||||
}{{
|
||||
message: "empty",
|
||||
expResult: DefaultAudioTitle,
|
||||
}, {
|
||||
message: "separator only",
|
||||
separator: DefaultAudioSeparator,
|
||||
expResult: DefaultAudioTitle,
|
||||
}, {
|
||||
message: "title only",
|
||||
audio: &Audio{
|
||||
Title: testAudio.Title,
|
||||
},
|
||||
expResult: testAudio.Title,
|
||||
}, {
|
||||
message: "performer only",
|
||||
audio: &Audio{
|
||||
Performer: testAudio.Performer,
|
||||
},
|
||||
expResult: testAudio.Performer + DefaultAudioSeparator + DefaultAudioTitle,
|
||||
}, {
|
||||
message: "title & performer",
|
||||
audio: &Audio{
|
||||
Performer: testAudio.Performer,
|
||||
Title: testAudio.Title,
|
||||
},
|
||||
expResult: testAudio.Performer + DefaultAudioSeparator + testAudio.Title,
|
||||
}, {
|
||||
message: "title & separator",
|
||||
separator: " | ",
|
||||
audio: &Audio{
|
||||
Title: testAudio.Title,
|
||||
},
|
||||
expResult: testAudio.Title,
|
||||
}, {
|
||||
message: "performer & separator",
|
||||
separator: " | ",
|
||||
audio: &Audio{
|
||||
Performer: testAudio.Performer,
|
||||
},
|
||||
expResult: testAudio.Performer + " | " + DefaultAudioTitle,
|
||||
}, {
|
||||
message: "performer, title & separator",
|
||||
separator: " | ",
|
||||
audio: &Audio{
|
||||
Performer: testAudio.Performer,
|
||||
Title: testAudio.Title,
|
||||
},
|
||||
expResult: testAudio.Performer + " | " + testAudio.Title,
|
||||
}} {
|
||||
tc := tc
|
||||
t.Run(tc.message, func(t *testing.T) {
|
||||
assert.Equal(t, tc.expResult, tc.audio.FullName(tc.separator))
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue